T09 · Insecure Skill Coding Practices
- Location
references/campaign.md:115- Finding
Insecure Persistence and Plaintext Disclosure of a Bearer Job Token
- Content
View full analysis
Vulnerability Details
File Location:
references/campaign.md, lines 115–118
Vulnerability Type: Plaintext sensitive-data storage and disclosure
Risk Level: MediumVulnerable Code Snippet
markdown **Before submitting — confirm you can persist the credentials.** `jobId` + `jobToken` is the only credential that retrieves the report: there is no "list my jobs by address" endpoint, so a lost credential is unrecoverable and unappealable, and since every call is paid, the payment is lost with it. Confirm you have somewhere durable to write them (cross-turn task state, **not** a transient shell variable) **before** calling `POST /x402/analyze/async` — the moment the signed request is replayed the payment is made and cannot be undone. **Mandatory steps after submission:** 1. **Write `jobId` and `jobToken` to that durable state immediately, before the first poll.** If the write fails anyway, do not quietly continue: the job is already paid for and cannot be un-submitted, so **show the user both values in plaintext right away** and ask them to keep them, so the report stays retrievable by hand.Technical Analysis
The instructions correctly recognize
jobTokenas a credential required to retrieve a paid analysis report. However, they require it to be written to an unspecified durable, cross-turn state without mandating encryption, access controls, retention limits, or secure deletion.The fallback behavior explicitly requires displaying both
jobIdandjobTokenin plaintext. This places the bearer credential in the conversation transcript, where it may be retained in logs, synchronization systems, analytics pipelines, or user-visible history.This behavior also conflicts with the root credential policy in
SKILL.md:143, which states:markdown - **Credential protection**: Never log, display, or ask for session tokens, clientId, API keys, private keys, seed phrases, or passwords. Redact sensitive fields from CLI output.A b ...[truncated 1852 chars]
- Remediation
View remediation
Remediation Suggestions
- Classify
jobTokenexplicitly as a sensitive bearer credential under the root credential-protection policy. - Store it only in an encrypted secret store or runtime credential vault with access limited to the current Skill and job.
- Keep only a non-sensitive opaque lookup handle in ordinary cross-turn task state.
- Never write the token to general memory, logs, telemetry, temporary files, command history, or conversation transcripts.
- Remove the instruction to display the full token in plaintext when persistence fails.
- If secure persistence is unavailable, stop before submitting the paid request and inform the user that the runtime cannot securely retain the retrieval credential.
- If a post-payment storage failure occurs, offer a secure export channel designed for secrets rather than chat output. If no secure channel exists, clearly report the failure without exposing the token to additional systems.
- Apply explicit expiration and deletion controls so the credential is erased immediately after report retrieval, job failure, or server-side expiry.
- Redact
jobToken, payment signature headers, presigned download URLs, and equivalent bearer values from all command output and error reports. - Document the minimum scope and lifetime expected for
jobToken, and support server-side revocation or rotation where available.
- Classify
