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.
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
packages/cli/src/lib/cursor.ts, lines 136–160, 235–283, 285–324accessTokenandrefreshTokenfrom the Cursor SQLite database (state.vscdb) viareadCursorAuthStateFromDatabase(). These are live session tokens. TheaccessTokenis then sent asAuthorization: BearerandCookieheaders in up to 8 HTTP fetch attempts togetCursorWebBaseUrl()(defaulthttps://cursor.com). IfCURSOR_WEB_BASE_URLis overridden via env var, tokens are sent to an attacker-controlled endpoint.CURSOR_WEB_BASE_URL— restrict tohttps://cursor.comorhttps://*.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_URLEnvironment Variablepackages/cli/src/lib/cursor.ts, lines 225–229getCursorWebBaseUrl()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.cursor.comor a subdomain thereof.3. SSRF via
SLOPMETER_WEB_DATA_URLEnvironment Variablepackages/web/scripts/publish-usage.ts, lines 75–91readHostedPayload()fetches fromprocess.env.SLOPMETER_WEB_DATA_URLwithout 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.https://and the hostname matches an allowlist.P2 Medium — Insecure File Operations & Missing Validation
4.
JSON.parseon Untrusted File Contents Without Schema Validationpackages/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,98JSON.parse()calls on file contents with onlyas Ttype assertions. No runtime validation. A malicious or corrupted JSON file could cause unexpected behavior.zod) on parsed JSON before use.5. Unbounded File Read via
readFileSyncindroid.tspackages/cli/src/lib/droid.ts, line 76readFileSync+JSON.parsewithout any file size check. A very large or malicious.settings.jsonfile could cause OOM.readJsonDocument()utility withmaxByteslimit (as used in Gemini/Claude providers).6. Environment Variable Path Injection via Multiple
*_HOME/*_DIRVariablescodex.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-1037. Temp Directory Race Condition (TOCTOU) in SQLite Snapshots
packages/cli/src/lib/sqlite.ts:10-35,packages/cli/src/lib/cursor.ts:166-190,packages/cli/src/lib/open-code.ts:154-178mkdtemp+copyFile+ process +rm. If the process crashes, temp files persist. On multi-user systems, predictableslopmeter-*prefix could enable symlink attacks.process.on('exit', ...)).8.
process.emitWarningMonkey-Patching inopen-code.tspackages/cli/src/lib/open-code.ts, lines 108–135process.emitWarningwith a wrapper that suppresses SQLite experimental warnings. During async operations, other concurrent code may see the patched version.9. Error Messages Leak File System Paths
utils.ts:282-296,codex.ts:505,pi.ts:139,cursor.ts:321-323P3 Low — Minor Issues
10. No Security Headers in Next.js App
packages/web/next.config.ts11. SVG
escapeXmlDoesn't Escape Quotespackages/cli/src/graph.ts, lines 354–359"to"and'to'.12. Integer Overflow in Token Calculations
packages/cli/src/lib/utils.ts, lines 100–109, 127–152Number.isFinite()checks on intermediate totals.13.
getPositiveIntegerEnvAccepts Arbitrarily Large Valuespackages/cli/src/lib/utils.ts, lines 595–609Summary
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 setCURSOR_WEB_BASE_URLcan capture live Cursor session tokens.