T09 · Insecure Skill Coding Practices
- Location
scripts/powpow-register.mjs:55- Finding
Shared Workflow State Can Leak Sessions Across Concurrent Users
- Content
View full analysis
Vulnerability Details
File Location:
scripts/powpow-register.mjs, lines 55–68
Vulnerability Type: Shared temporary state and cross-conversation session confusion
Risk Level: HighVulnerable Code
js const STATE_FILE = join(tmpdir(), 'powpow-register-state.json'); function loadState() { try { return JSON.parse(readFileSync(STATE_FILE, 'utf8')); } catch { return {}; } } function saveState(patch) { const s = { ...loadState(), ...patch }; writeFileSync(STATE_FILE, JSON.stringify(s, null, 2), { mode: 0o600 }); return s; }Technical Analysis
All registration workflows running under the same operating-system account use the fixed path
powpow-register-state.json. The state is not namespaced by conversation, user, or workflow instance.Although mode
0600prevents access by other OS users, it does not isolate different Agent conversations handled by the same account. The file stores identity and workflow data, including email, username, JWT, payment provider, and order identifiers. Subsequent commands load whichever values are present at execution time.This creates a reachable confused-deputy condition when workflows overlap or when stale state remains because
cleanuphas not run. One conversation can overwrite fields belonging to another. Commands such aslogin-link,create-order,query, andwhoamimay consequently operate with another conversation’s JWT or payment state.The JWT is especially sensitive because
login-linkembeds it in a one-click authentication URL. If state is replaced between registration and link generation, the generated link can authenticate the recipient as a different user.Attack Path
- Victim A begins registration under the shared Agent runtime.
- The script writes Victim A’s email, username, and later JWT to
/tmp/powpow-register-state.json. - Before Victim A’s workflow finishes or runs
cleanup, User B starts another workflow under the same OS account.
...[truncated 1274 chars]
- Remediation
View remediation
Remediation Suggestions
- Generate a cryptographically random workflow identifier for each registration conversation.
- Store each workflow in a separate private directory or file, such as:
powpow-register-<random-id>/state.json. - Require the workflow identifier for every state-dependent command and pass it through a protected Agent-side context rather than user-controlled content.
- Bind each state record to the expected conversation and user identity, and reject mismatches.
- Avoid merging unrelated state blindly; validate the expected workflow phase and account identity before each operation.
- Use atomic creation and replacement semantics to prevent interleaved writes.
- Set restrictive permissions on both the per-workflow directory and state file.
- Apply an expiration time and securely remove abandoned state.
- Ensure
cleanupdeletes only the current workflow’s state. - Before generating login links or initiating payment operations, display or validate the associated account identity so cross-session substitution is detected.
