T09 · Insecure Skill Coding Practices
- Location
SKILL.md:12- Finding
Reusable Session Tokens Persisted in Plaintext
- Content
View full analysis
" REFRESH_TOKEN="" cat > "$IPA_COOKIE_FILE" <- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a coherent service integration, but it asks agents to store reusable account session tokens in plaintext and handle them in ways that could expose the account.
Review this before installing if the account matters to you. Avoid opting into saved session tokens unless TOOLS.md is protected from other users, extensions, backups, and future agent sessions; prefer session-only login or a proper credential store, and clear/revoke saved tokens if exposed.
SKILL.md:12Reusable Session Tokens Persisted in Plaintext
SKILL.md:85Passwords and Session Tokens Exposed Through Command-Line Arguments
SKILL.md:66Predictable and Insufficiently Protected Temporary Cookie Files
The skill explicitly instructs persistence of access and refresh token cookie values in TOOLS.md, a plaintext file. Session tokens function as bearer credentials, so anyone with access to that file could replay them to impersonate the user and access or modify their account.
### I'm Pretty Amazing
- **Username:** their-username (optional)
- **Access Token Cookie:** eyJhbGciOi...
- **Refresh Token Cookie:** eyJhbGciOi... (optional but recommended)
- **Access Token Expires At (UTC):** 2026-03-21T03:04:46Z
The token-handling section normalizes storing access tokens in TOOLS.md while merely warning not to print them. The core issue is not display but retention of reusable authentication material in plaintext, which materially increases account takeover risk.
Token handling:
The authentication flow directs the agent to read persisted access and refresh tokens from TOOLS.md for reuse. This creates a standing credential cache in a non-secret document, making theft or accidental disclosure of valid session material much more likely.
For cookie-auth endpoints, follow these steps:
**Step 0 — Reuse persisted auth if still valid (preferred):**
1. Read persisted `Access Token Cookie` (and `Refresh Token Cookie` if available) from TOOLS.md.
2. Verify that `Access Token Cookie` is present and `Access Token Expires At (UTC)` is a valid ISO 8601 timestamp (YYYY-MM-DDTHH:MM:SSZ). If either is missing or malformed, continue to Step 1.
3. If `Access Token Expires At (UTC)` is in the future, rebuild a cookie jar from those values and use that jar for requests.
4. If expired, continue to Step 1.
This line continues the reuse model for plaintext-stored access tokens based on expiry metadata, effectively encouraging long-lived secret retention. Reusing stored session cookies without a secure vault increases the blast radius of any disclosure of TOOLS.md.
**Step 0 — Reuse persisted auth if still valid (preferred):**
1. Read persisted `Access Token Cookie` (and `Refresh Token Cookie` if available) from TOOLS.md.
2. Verify that `Access Token Cookie` is present and `Access Token Expires At (UTC)` is a valid ISO 8601 timestamp (YYYY-MM-DDTHH:MM:SSZ). If either is missing or malformed, continue to Step 1.
3. If `Access Token Expires At (UTC)` is in the future, rebuild a cookie jar from those values and use that jar for requests.
4. If expired, continue to Step 1.
The guidance to rebuild a cookie jar from token values in TOOLS.md demonstrates direct operational reuse of exposed bearer secrets. This makes the plaintext file a complete source for authenticated session reconstruction and account impersonation.
**Step 0 — Reuse persisted auth if still valid (preferred):**
1. Read persisted `Access Token Cookie` (and `Refresh Token Cookie` if available) from TOOLS.md.
2. Verify that `Access Token Cookie` is present and `Access Token Expires At (UTC)` is a valid ISO 8601 timestamp (YYYY-MM-DDTHH:MM:SSZ). If either is missing or malformed, continue to Step 1.
3. If `Access Token Expires At (UTC)` is in the future, rebuild a cookie jar from those values and use that jar for requests.
4. If expired, continue to Step 1.
Canonical cookie-jar rebuild snippet (substitute persisted values from TOOLS.md):
The snippet assigns access and refresh tokens from TOOLS.md into shell variables, further exposing secrets to process environments and shell history depending on execution context. Combined with plaintext storage, this materially increases credential leakage opportunities.
IPA_COOKIE_FILE="/tmp/ipa-cookies-$$.txt"
ACCESS_TOKEN="<Access Token Cookie from TOOLS.md>"
REFRESH_TOKEN="<Refresh Token Cookie from TOOLS.md>"
cat > "$IPA_COOKIE_FILE" <<EOF
This instruction explicitly tells the agent to persist token expiry metadata alongside access and refresh tokens in TOOLS.md. Expiry metadata makes the cached credentials easier to operationalize by signaling when stolen tokens remain valid.
echo "$ACCESS_TOKEN_EXPIRES_AT_UTC"
Persist `ACCESS_TOKEN_EXPIRES_AT_UTC` as `Access Token Expires At (UTC)` in TOOLS.md.
Persist `ACCESS_TOKEN` as `Access Token Cookie` and `REFRESH_TOKEN` (if present) as `Refresh Token Cookie`.
**Step 2 — Make API calls (reuse the cookie file):**
Persisting both ACCESS_TOKEN and REFRESH_TOKEN in plaintext is especially dangerous because the refresh token can often mint new access tokens after expiry. That turns a local disclosure into potentially prolonged unauthorized access.
Persist `ACCESS_TOKEN_EXPIRES_AT_UTC` as `Access Token Expires At (UTC)` in TOOLS.md.
Persist `ACCESS_TOKEN` as `Access Token Cookie` and `REFRESH_TOKEN` (if present) as `Refresh Token Cookie`.
**Step 2 — Make API calls (reuse the cookie file):**
```bash
Embedding access and refresh tokens directly in a Cookie header exposes them in command text, which may be captured by logs, telemetry, shell history, debugging tools, or process listings. Because these are bearer-equivalent credentials, disclosure enables session hijacking.
curl -s https://api.imprettyamazing.com/wins/my-wins \
-H "Cookie: access_token=<Access Token Cookie from TOOLS.md>; refresh_token=<Refresh Token Cookie from TOOLS.md>"
Step 3 — Handle expired sessions:
The session-refresh logic again instructs updating plaintext-stored access and refresh tokens in TOOLS.md after re-login. This entrenches insecure credential persistence and ensures sensitive tokens remain continuously available for theft.
If any call returns `{"statusCode": 401, ...}`:
1. Prompt again for email/password (session-only).
2. Call `POST /auth/login` again and overwrite the cookie file with `-c`.
3. Re-extract cookies from `IPA_COOKIE_FILE`. If session persistence was previously opted in, update `access_token`, `refresh_token`, and `Access Token Expires At (UTC)` in TOOLS.md.
4. Retry the failed call.
**Rules:**
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
All cookie-auth actions require `-b "$IPA_COOKIE_FILE"` after login. **The API reference at [references/api.md](references/api.md) is the complete endpoint documentation. Read it before using any endpoint not shown above.**
- **Update/delete wins**: `PATCH /wins/:id` (JSON body), `DELETE /wins/:id`
- **Comments**: `POST /wins/:id/comments` with `{"content": "..."}`, `GET /wins/:id/comments`
- **Likes**: `POST /wins/:id/like`, `DELETE /wins/:id/like` (toggle)
- **Follow/unfollow**: `POST /follows/:userId`, `DELETE /follows/:userId`
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
- **Update/delete wins**: `PATCH /wins/:id` (JSON body), `DELETE /wins/:id`
- **Comments**: `POST /wins/:id/comments` with `{"content": "..."}`, `GET /wins/:id/comments`
- **Likes**: `POST /wins/:id/like`, `DELETE /wins/:id/like` (toggle)
- **Follow/unfollow**: `POST /follows/:userId`, `DELETE /follows/:userId`
- **Profile**: `PATCH /profile` (JSON: `username`, `bio` max 500 chars, `location`, `website`)
- **Avatar/cover**: `POST /profile/avatar` (multipart `avatar`), `POST /profile/cover` (multipart `cover`, keep file small)
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
- **Update/delete wins**: `PATCH /wins/:id` (JSON body), `DELETE /wins/:id`
- **Comments**: `POST /wins/:id/comments` with `{"content": "..."}`, `GET /wins/:id/comments`
- **Likes**: `POST /wins/:id/like`, `DELETE /wins/:id/like` (toggle)
- **Follow/unfollow**: `POST /follows/:userId`, `DELETE /follows/:userId`
- **Profile**: `PATCH /profile` (JSON: `username`, `bio` max 500 chars, `location`, `website`)
- **Avatar/cover**: `POST /profile/avatar` (multipart `avatar`), `POST /profile/cover` (multipart `cover`, keep file small)
- **Feedback**: `POST /feedback` with `{"category": "BUG|FEATURE_REQUEST|GENERAL", "message": "...", "pageUrl": "...", "pageContext": "..."}`
The document advises persisting access_token and optionally refresh_token, parsing JWT expiry, and reusing them for authentication. These tokens are bearer-equivalent session credentials; if an agent stores or handles them insecurely, anyone who obtains them can impersonate the user until expiry or refresh, making this especially dangerous in a skill that automates posting, profile changes, follows, and other authenticated actions.
Client guidance: you may persist cookie token values (`access_token`, optionally `refresh_token`) and reuse them until access-token expiry, then re-login.
Canonical expiry tracking: derive `Access Token Expires At (UTC)` from the `access_token` JWT `exp` claim and refresh auth when expired.
| Method | Endpoint | Description |
|--------|----------|-------------|
The skill description includes proactive and broad triggers like posting wins, tracking achievements, and suggesting a win after something notable, which could match many ordinary conversations and cause the skill to activate unexpectedly. Because the skill can then solicit credentials and interact with an external service, accidental invocation increases privacy and consent risk.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
IPA_COOKIE_FILE="/tmp/ipa-cookies-$$.txt"
curl -s -X POST https://api.imprettyamazing.com/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"EMAIL","password":"PASSWORD"}' \
-c "$IPA_COOKIE_FILE"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
IPA_COOKIE_FILE="/tmp/ipa-cookies-$$.txt"
curl -s -X POST https://api.imprettyamazing.com/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"EMAIL","password":"PASSWORD"}' \
-c "$IPA_COOKIE_FILE"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
IPA_COOKIE_FILE="/tmp/ipa-cookies-$$.txt"
curl -s -X POST https://api.imprettyamazing.com/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"EMAIL","password":"PASSWORD"}' \
-c "$IPA_COOKIE_FILE"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
IPA_COOKIE_FILE="/tmp/ipa-cookies-$$.txt"
curl -s -X POST https://api.imprettyamazing.com/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"EMAIL","password":"PASSWORD"}' \
-c "$IPA_COOKIE_FILE"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
IPA_COOKIE_FILE="/tmp/ipa-cookies-$$.txt"
curl -s -X POST https://api.imprettyamazing.com/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"EMAIL","password":"PASSWORD"}' \
-c "$IPA_COOKIE_FILE"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
IPA_COOKIE_FILE="/tmp/ipa-cookies-$$.txt"
curl -s -X POST https://api.imprettyamazing.com/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"EMAIL","password":"PASSWORD"}' \
-c "$IPA_COOKIE_FILE"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
Step 2 — Make API calls (reuse the cookie file):
curl -s https://api.imprettyamazing.com/wins/my-wins \
-b "$IPA_COOKIE_FILE"
Use -b "$IPA_COOKIE_FILE" on every cookie-auth request.
This example instructs the agent to construct a raw Cookie header directly from access and refresh token values stored in TOOLS.md. That increases exposure of bearer-equivalent session secrets by placing them into command lines and prompt-accessible plaintext storage, where they may be leaked through logs, process inspection, or unintended file access.
If only persisted cookie values are available (no cookie file yet), you can call with an explicit cookie header (substitute values from TOOLS.md):
curl -s https://api.imprettyamazing.com/wins/my-wins \
-H "Cookie: access_token=<Access Token Cookie from TOOLS.md>; refresh_token=<Refresh Token Cookie from TOOLS.md>"
The API guidance explicitly tells clients they may persist access_token and refresh_token cookie values and reuse them, but it does not warn that these are sensitive session credentials that should be handled like secrets. In an agent/skill context, this can encourage long-lived storage of session tokens in logs, memory, or local state, increasing the chance of account takeover if those values are exposed.
No suspicious patterns detected.