Skip to content

[nightshift] security-footgun: credential exfiltration and SSRF vulnerabilities #16

@nightshift-micr

Description

@nightshift-micr

Security Vulnerability & Footgun Analysis — micr-dev/tokens (slopmeter)

Automated by Nightshift v3 (GLM 5.1).


P1 Critical — Credential Handling & Token Exposure

1. Cursor Access Token Extracted from Local DB and Used in HTTP Requests

  • File: packages/cli/src/lib/cursor.ts, lines 136–160, 235–283, 285–324
  • Description: The tool reads accessToken and refreshToken from the Cursor SQLite database (state.vscdb) via readCursorAuthStateFromDatabase(). These are live session tokens. The accessToken is then sent as Authorization: Bearer and Cookie headers in up to 8 HTTP fetch attempts to getCursorWebBaseUrl() (default https://cursor.com). If CURSOR_WEB_BASE_URL is overridden via env var, tokens are sent to an attacker-controlled endpoint.
  • Fix: Add URL validation for CURSOR_WEB_BASE_URL — restrict to https://cursor.com or https://*.cursor.com. Log a warning when non-default URL is used. Consider using a consent prompt before extracting tokens.

P1 High — SSRF & Credential Exfiltration

2. SSRF via CURSOR_WEB_BASE_URL Environment Variable

  • File: packages/cli/src/lib/cursor.ts, lines 225–229
  • Description: getCursorWebBaseUrl() reads from env and strips trailing slashes, but performs no validation. Combined with the token extraction above, this allows an attacker who controls this env var to exfiltrate Cursor session tokens to an arbitrary server.
  • Fix: Validate hostname is cursor.com or a subdomain thereof.

3. SSRF via SLOPMETER_WEB_DATA_URL Environment Variable

  • File: packages/web/scripts/publish-usage.ts, lines 75–91
  • Description: readHostedPayload() fetches from process.env.SLOPMETER_WEB_DATA_URL without any URL validation. An attacker who can set this env var can cause the tool to make arbitrary HTTP requests (SSRF), potentially hitting internal services.
  • Fix: Validate that the URL scheme is https:// and the hostname matches an allowlist.

P2 Medium — Insecure File Operations & Missing Validation

4. JSON.parse on Untrusted File Contents Without Schema Validation

  • Files: packages/cli/src/lib/droid.ts:76, packages/cli/src/lib/codex.ts:511, packages/cli/src/lib/pi.ts:144, packages/web/scripts/publish-usage.ts:70,98
  • Description: Multiple JSON.parse() calls on file contents with only as T type assertions. No runtime validation. A malicious or corrupted JSON file could cause unexpected behavior.
  • Fix: Use runtime schema validation (e.g., zod) on parsed JSON before use.

5. Unbounded File Read via readFileSync in droid.ts

  • File: packages/cli/src/lib/droid.ts, line 76
  • Description: Unlike other providers that use streaming JSONL readers with size limits, the Droid provider reads entire files synchronously with readFileSync + JSON.parse without any file size check. A very large or malicious .settings.json file could cause OOM.
  • Fix: Use the readJsonDocument() utility with maxBytes limit (as used in Gemini/Claude providers).

6. Environment Variable Path Injection via Multiple *_HOME / *_DIR Variables

  • Files: codex.ts:207-209, gemini.ts:39-42, open-code.ts:76-78, pi.ts:47-57, hermes.ts:46-48, helios.ts:48-50, claude-code.ts:104-113, cursor.ts:81-103
  • Description: All env vars are resolved to paths and used for file/SQLite operations. An attacker who can set env vars can redirect the tool to read arbitrary files without checking they reside within expected directories.
  • Fix: Validate that resolved paths are within expected base directories.

7. Temp Directory Race Condition (TOCTOU) in SQLite Snapshots

  • Files: packages/cli/src/lib/sqlite.ts:10-35, packages/cli/src/lib/cursor.ts:166-190, packages/cli/src/lib/open-code.ts:154-178
  • Description: SQLite snapshot pattern uses mkdtemp + copyFile + process + rm. If the process crashes, temp files persist. On multi-user systems, predictable slopmeter-* prefix could enable symlink attacks.
  • Fix: Register cleanup handlers (process.on('exit', ...)).

8. process.emitWarning Monkey-Patching in open-code.ts

  • File: packages/cli/src/lib/open-code.ts, lines 108–135
  • Description: Globally replaces process.emitWarning with a wrapper that suppresses SQLite experimental warnings. During async operations, other concurrent code may see the patched version.
  • Fix: Use a more targeted approach, such as a one-time listener.

9. Error Messages Leak File System Paths

  • Files: utils.ts:282-296, codex.ts:505, pi.ts:139, cursor.ts:321-323
  • Description: Error messages include full file paths. If surfaced in a web context, they reveal server file system structure.
  • Fix: In web-facing contexts, sanitize paths before displaying errors.

P3 Low — Minor Issues

10. No Security Headers in Next.js App

  • File: packages/web/next.config.ts
  • Fix: Add CSP, X-Frame-Options, X-Content-Type-Options headers.

11. SVG escapeXml Doesn't Escape Quotes

  • File: packages/cli/src/graph.ts, lines 354–359
  • Fix: Also escape " to " and ' to '.

12. Integer Overflow in Token Calculations

  • File: packages/cli/src/lib/utils.ts, lines 100–109, 127–152
  • Fix: Add Number.isFinite() checks on intermediate totals.

13. getPositiveIntegerEnv Accepts Arbitrarily Large Values

  • File: packages/cli/src/lib/utils.ts, lines 595–609
  • Fix: Add an upper bound cap.

Summary

Severity Count Key Risk
P1 Critical 1 Cursor session tokens exfiltrated via SSRF
P1 High 2 SSRF via env-controlled URLs
P2 Medium 6 Missing path bounds checking, unsafe JSON parsing, error leakage
P3 Low 4 Missing security headers, incomplete SVG escaping, verbose logging

Most critical finding: The combination of Cursor token extraction (cursor.ts:136-160) with env-controlled fetch URL (cursor.ts:225-229) creates a credential exfiltration vector. An attacker who can set CURSOR_WEB_BASE_URL can capture live Cursor session tokens.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions