Back to skill

Security audit

RUNSTR Fitness

Security checks for vulnerabilities and agentic risk

Overview

This skill is meant to read RUNSTR fitness backups, but it asks for a full Nostr private key and directs agents to persist sensitive health summaries without clear opt-in controls.

Review this carefully before installing. Do not paste a main Nostr nsec into the agent; use a dedicated fitness-only identity or a local signer/key manager if possible. Treat any saved health summary as sensitive and only allow memory persistence after explicit consent, with a plan to review and delete it. Prefer a pinned, verified nak version rather than installing a mutable latest release.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:37
Finding
Nostr Private Key Exposed Through Chat and Process Arguments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 37-41 and 103-123 **Vulnerability Type**: Sensitive credential exposure through conversation history, shell expansion, and command-line arguments **Risk Level**: High ### Vulnerable Code ```markdown ### 3. Give Your Bot Your nsec Your **nsec** is your Nostr private key. Find it in RUNSTR under **Settings > Keys** (or your Nostr key manager). **Tell your bot:** "Here's my RUNSTR nsec: nsec1..." Your bot uses the nsec to decrypt your encrypted fitness backup from Nostr. The nsec is never stored, logged, or transmitted — it's used only for the decryption step in your current session. ``` ```bash content=$(nak req -k 30078 -a $hex_pk -t d=runstr-workout-backup -l 1 \ wss://relay.damus.io wss://nos.lol | jq -r '.content') # Decrypt (NIP-44 self-decryption: user to own pubkey) decrypted=$(echo "$content" | nak encrypt --sec $hex_sk $hex_pk --decrypt) ``` ```javascript // /tmp/decrypt-runstr.mjs — run with: node /tmp/decrypt-runstr.mjs <hex_sk> '<content>' import { gunzipSync } from 'zlib'; import NDK, { NDKPrivateKeySigner } from '@nostr-dev-kit/ndk'; const signer = new NDKPrivateKeySigner(process.argv[2]); const user = await signer.user(); const decrypted = await signer.decrypt(user, process.argv[3]); try { console.log(gunzipSync(Buffer.from(decrypted, 'base64')).toString()); } catch { console.log(decrypted); } ``` ### Technical Analysis The skill directs the user to disclose a complete Nostr private key directly to the agent. This places the credential in the conversation context, where it may be retained in session history, telemetry, diagnostics, or platform logs. The decoded key is subsequently expanded into a shell command and, in the Node.js fallback, supplied explicitly through `process.argv`. Command-line arguments can be visible to local process-inspection tools and may be captured by shell history, process accounting, monitoring software, crash reports, or diagnostic ...[truncated 1597 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not ask users to enter an `nsec` into a chat conversation. 2. Integrate with a local Nostr signer or key manager that performs decryption without exposing private-key material to the agent. 3. Use a dedicated fitness-only Nostr identity to limit the consequences of compromise. 4. If direct key use is unavoidable, obtain it through a protected secret prompt or file descriptor rather than command-line arguments. 5. Never pass the key through `process.argv`, shell interpolation, environment variables retained by process supervisors, or temporary files. 6. Quote all non-secret shell variables defensively and prevent command tracing while secret-bearing operations execute. 7. Redact credentials from errors, logs, telemetry, and command transcripts. 8. Clear in-memory secret buffers where supported and ensure decrypted temporary data is deleted securely. 9. Replace the unconditional privacy assertion with an accurate disclosure of the platform’s session-retention and logging behavior. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:225
Finding
Sensitive Health and Behavioral Data Persisted Without Explicit Consent or Retention Controls<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 225-254 **Vulnerability Type**: Persistent storage of sensitive health information without data-minimization or lifecycle controls **Risk Level**: Medium ### Vulnerable Code ```markdown ### Step 6: Store Health Summary in Memory Save a structured summary for future conversations so you don't re-query every time: ```markdown # Health & Fitness Summary Last updated: YYYY-MM-DD Source: RUNSTR (Nostr encrypted backup) User: <name or npub> ## Recent Activity (Last 30 Days) - Total workouts: X - Running: X workouts, Y km, avg pace Z/km - Walking: X workouts, Y km - Cycling: X workouts, Y km ## Frequency - X workouts/week avg - Most active: [weekday] ## Habits - [Habit]: X day streak ## Mood & Energy - Avg mood: [level], Avg energy: X/5 ## Steps - Avg: X,XXX/day ## Insights - [Patterns and observations] ``` ``` ### Technical Analysis The skill explicitly instructs the agent to save a structured health summary in long-term memory. The retained information can include identity attributes, exercise history, behavioral habits, mood, energy, steps, and inferred patterns. Although retaining a user-requested summary can be a legitimate feature, these instructions do not require explicit opt-in consent, define a retention period, limit access, specify deletion procedures, or minimize the stored fields. The data was originally protected by an encrypted Nostr backup, but the proposed memory record is a decrypted derivative whose protection depends entirely on the agent platform’s memory controls. This issue is classified as insecure storage rather than agent memory poisoning because the stored content is health data, not attacker-controlled instructions intended to alter future agent behavior. ### Attack Path 1. The agent obtains and decrypts the RUNSTR backup. 2. It extracts sensitive workout, habit, journal, mood, energy, and step information. 3. Following the skill instructions, it write ...[truncated 1062 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Default to session-only analysis and do not persist a summary automatically. 2. Obtain explicit, informed user consent before writing any health information to long-term memory. 3. Clearly list the fields that will be retained and allow the user to approve or remove individual categories. 4. Store only the minimum information required for the requested coaching functionality. 5. Avoid retaining journal contents, mood details, sensitive habit names, precise schedules, and direct identity links unless specifically requested. 6. Define a short retention period and automatically expire stale summaries. 7. Provide user-accessible commands to inspect, update, export, and permanently delete the stored summary. 8. Apply access controls and encryption appropriate for sensitive health information. 9. Record the consent state and last update time without storing the private key or raw decrypted backup. 10. Warn users that persistent agent memory may be available in later conversations. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:58
Finding
Unpinned Third-Party Tool Installed From a Mutable Latest Version<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 58-61 **Vulnerability Type**: Unpinned third-party dependency and supply-chain exposure **Risk Level**: Medium ### Vulnerable Code ```markdown ### Prerequisites `nak` (Nostr Army Knife) must be installed: ```bash go install github.com/fiatjaf/nak@latest ``` ``` The same mutable installation command is repeated in the troubleshooting guidance at line 275: ```markdown | nak not installed | `go install github.com/fiatjaf/nak@latest` | ``` ### Technical Analysis The installation command uses the mutable `@latest` selector rather than a reviewed release or commit. Consequently, the code installed during a future skill invocation may differ from the code that existed when the skill was audited. The skill later invokes this dependency while processing a decoded Nostr private key and decrypted health data. If the upstream repository, release process, maintainer account, or dependency chain is compromised, a malicious version could execute during installation or capture sensitive material when the tool is invoked. No evidence shows that the named project is currently malicious. The confirmed issue is the absence of version pinning, checksum verification, provenance validation, and an auditable update policy. ### Attack Path 1. An attacker compromises the upstream repository, maintainer credentials, release pipeline, or a transitive dependency. 2. The compromised code becomes the version resolved by `@latest`. 3. A user or agent follows the skill setup instructions and installs that version. 4. The malicious package executes during build or installs a modified `nak` binary. 5. The skill invokes the binary with operations involving the decoded private key and encrypted backup. 6. The malicious binary steals the key or decrypted information, modifies output, or executes arbitrary commands under the installing user’s privileges. ### Impact Assessment A compromised dependency would execute ...[truncated 576 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace `@latest` with a specific reviewed semantic version or immutable commit identifier. 2. Document the expected version and supported upgrade procedure. 3. Verify release checksums, signatures, or build provenance before installation. 4. Review dependency changes before updating the pinned version. 5. Prefer reproducible builds and a trusted internal artifact cache where available. 6. Run the tool with minimal operating-system privileges and restrict network and filesystem access. 7. Avoid exposing private keys to the dependency; use a separate local signer or narrowly scoped decryption interface. 8. Add integrity verification to automated setup instructions and fail closed if validation fails. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Missing User Warnings

High
Confidence
98% confidence
Finding
The skill instructs the user to provide their Nostr private key directly to the bot, which is a highly sensitive credential capable of broader account actions beyond merely decrypting fitness backups. Presenting this as a normal setup step without a strong warning about account compromise, impersonation, and irreversible exposure conditions users to hand secrets to an AI agent and creates a direct path to credential misuse or leakage.

Ssd 3

High
Confidence
99% confidence
Finding
Telling users to give a private key directly to the bot exposes the most sensitive Nostr credential to an untrusted processing environment. If logged, cached, leaked through telemetry, or mishandled by downstream tooling, the key could enable account takeover, impersonation, decryption of protected data, and abuse beyond the stated fitness use case.

Missing User Warnings

High
Confidence
97% confidence
Finding
The skill directs the agent to retain a persistent health summary across conversations without a clear user warning or opt-in, despite the data including workouts, habits, mood, journal content, and steps. Because this is sensitive health-adjacent personal data, silent persistence materially raises privacy risk, secondary-use risk, and harm from accidental disclosure or model memory access in future interactions.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The skill tells users their nsec is only used transiently for decryption, but later instructs the agent to retain a derived health summary for future conversations. Even if the private key itself is not stored, persisting outputs derived from decrypted health data undermines the stated privacy boundary and creates an unauthorized long-term retention path for sensitive personal information.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The instruction to store a reusable long-term memory profile includes sensitive health, mood, habit, and activity data that exceeds what is necessary to answer a single user request. Persistent profiling of health-related data increases exposure in later sessions, expands breach impact, and may violate user expectations and privacy requirements for sensitive data handling.

Ssd 3

Medium
Confidence
95% confidence
Finding
Persisting a structured summary of health and mood data creates a durable repository of sensitive personal information that can be accessed outside the original task context. This broadens the attack surface and magnifies the consequences of memory leakage, unauthorized retrieval, or reuse in unrelated conversations.

Static analysis

No suspicious patterns detected.