Mostly safe โ a couple of notes worth reading.
Scanned 5/3/2026, 6:32:01 PMยทCached resultยทFast Scanยท45 rulesยทHow we decide โ
AIVSS Score
Low
Severity Breakdown
0
critical
0
high
54
medium
34
low
MCP Server Information
Findings
This package scores 75/100 with a B grade but carries 54 medium-severity findings, primarily around readiness gaps (34), resource exhaustion risks (34), and server configuration issues (19). The resource exhaustion vulnerabilities are particularly concerning as they could allow denial-of-service attacks, while the readiness and configuration gaps suggest the package may not be production-hardened. You should address these medium-severity issues before deploying this to a critical environment, though the absence of high or critical findings means it's not inherently unsafe for lower-risk use cases.
No known CVEs found for this package or its dependencies.
Scan Details
Want deeper analysis?
Fast scan found 88 findings using rule-based analysis. Upgrade for LLM consensus across 5 judges, AI-generated remediation, and cross-file taint analysis.
Building your own MCP server?
Same rules, same LLM judges, same grade. Private scans stay isolated to your account and never appear in the public registry. Required for code your team hasnโt shipped yet.
Showing 1โ30 of 88 findings
88 findings
User-controlled value printed to terminal without ANSI escape sanitization. Malicious input can inject cursor-control sequences, rewrite earlier output, or hide shell commands from the operator.
Evidence
| 275 | // event type breakdown |
| 276 | const types = db.prepare("SELECT type, COUNT(*) as cnt FROM session_events GROUP BY type ORDER BY cnt DESC").all(); |
| 277 | console.log(` event types: ${types.map(t => `${t.type}(${t.cnt})`).join(", ")}`); |
| 278 | |
| 279 | // session_resume (compaction) |
| 280 | const resume = db.prepare("SELECT COUNT(*) as cnt FROM session_resume").get(); |
Remediation
Strip C0/C1 control codes before printing user-controlled values. Python: re.sub(r"[\x00-\x08\x0b-\x1f\x7f]", "", s). Prefer a structured logger (json/logfmt) over raw print to stdout.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 10 | ### curl / wget โ BLOCKED |
| 11 | Intercepted and replaced with error. Do NOT retry. |
| 12 | Use: `ctx_fetch_and_index(url, source)` or `ctx_execute(language: "javascript", code: "const r = await fetch(...)")` |
| 13 | |
| 14 | ### Inline HTTP โ BLOCKED |
| 15 | `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, `http.request(` โ intercepted. Do NOT retry. |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 172 | ### Debug an API endpoint |
| 173 | ```javascript |
| 174 | const resp = await fetch('http://localhost:3000/api/orders'); |
| 175 | const { orders } = await resp.json(); |
| 176 | |
| 177 | const bugs = []; |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 10 | ### curl / wget โ BLOCKED |
| 11 | Shell `curl`/`wget` intercepted and blocked. Do NOT retry. |
| 12 | Use: `context-mode_ctx_fetch_and_index(url, source)` or `context-mode_ctx_execute(language: "javascript", code: "const r = await fetch(...)")` |
| 13 | |
| 14 | ### Inline HTTP โ BLOCKED |
| 15 | `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, `http.request(` โ intercepted. Do NOT retry. |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 554 | }); |
| 555 | |
| 556 | // GitHub stars |
| 557 | fetch('https://api.github.com/repos/mksglu/context-mode') |
| 558 | .then(r=>r.json()) |
| 559 | .then(d=>{ |
| 560 | document.getElementById('stat-stars').textContent= |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 540 | document.querySelectorAll('.rev').forEach(e=>o.observe(e)); |
| 541 | |
| 542 | // Dynamic stats from GitHub |
| 543 | fetch('https://raw.githubusercontent.com/mksglu/context-mode/main/stats.json') |
| 544 | .then(r=>r.json()) |
| 545 | .then(d=>{ |
| 546 | document.getElementById('stat-users').textContent=d.message||'66.3k+'; |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 10 | ### curl / wget โ BLOCKED |
| 11 | Shell `curl`/`wget` intercepted and blocked. Do NOT retry. |
| 12 | Use: `@context-mode/ctx_fetch_and_index(url, source)` or `@context-mode/ctx_execute(language: "javascript", code: "const r = await fetch(...)")` |
| 13 | |
| 14 | ### Inline HTTP โ BLOCKED |
| 15 | `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, `http.request(` โ intercepted. Do NOT retry. |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 583 | }; |
| 584 | ``` |
| 585 | |
| 586 | **Python subprocess list form:** Additionally detects `subprocess.run(["rm", "-rf", "/"])` and extracts args to form `"rm -rf /"` for deny-pattern evaluation. |
| 587 | |
| 588 | **Extracted commands** are checked against the same Bash deny patterns used for direct shell commands. |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 1777 | } |
| 1778 | |
| 1779 | async function main() { |
| 1780 | const resp = await fetch(url); |
| 1781 | if (!resp.ok) { console.error("HTTP " + resp.status); process.exit(1); } |
| 1782 | const contentType = resp.headers.get('content-type') || ''; |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 10 | ### curl / wget โ BLOCKED |
| 11 | Terminal `curl`/`wget` intercepted and blocked. Do NOT retry. |
| 12 | Use: `ctx_fetch_and_index(url, source)` or `ctx_execute(language: "javascript", code: "const r = await fetch(...)")` |
| 13 | |
| 14 | ### Inline HTTP โ BLOCKED |
| 15 | `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, `http.request(` โ intercepted. Do NOT retry. |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 195 | BAD โ will timeout on API calls: |
| 196 | Tool: execute |
| 197 | code: | |
| 198 | const resp = await fetch('https://api.slow-service.com/data'); |
| 199 | console.log(await resp.json()); |
| 200 | language: javascript |
| 201 | timeout_ms: 5000 โ API may take 10+ seconds |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 1 | # JavaScript / TypeScript Patterns for execute |
| 2 | |
| 3 | Practical patterns for using `execute` with `language: javascript`. |
| 4 | All examples assume Node.js runtime with native fetch (Node 18+). |
| 5 | |
| 6 | --- |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 185 | ```typescript |
| 186 | // GOOD: Each function is independently mockable |
| 187 | const api = { |
| 188 | getUser: (id) => fetch(`/users/${id}`), |
| 189 | getOrders: (userId) => fetch(`/users/${userId}/orders`), |
| 190 | createOrder: (data) => fetch('/orders', { method: 'POST', body: data }), |
| 191 | }; |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 10 | ### curl / wget โ FORBIDDEN |
| 11 | Do NOT use `curl`/`wget` via `run_command`. Dumps raw HTTP into context. |
| 12 | Use: `mcp__context-mode__ctx_fetch_and_index(url, source)` or `mcp__context-mode__ctx_execute(language: "javascript", code: "const r = await fetch(...)")` |
| 13 | |
| 14 | ### Inline HTTP โ FORBIDDEN |
| 15 | No `node -e "fetch(..."`, `python -c "requests.get(..."` via `run_command`. Bypasses sandbox. |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 10 | ### curl / wget โ BLOCKED |
| 11 | Shell `curl`/`wget` intercepted and blocked. Do NOT retry. |
| 12 | Use: `context-mode__ctx_fetch_and_index(url, source)` or `context-mode__ctx_execute(language: "javascript", code: "const r = await fetch(...)")` |
| 13 | |
| 14 | ### Inline HTTP โ BLOCKED |
| 15 | `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, `http.request(` โ intercepted. Do NOT retry. |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 11 | ```javascript |
| 12 | // execute: Analyze API health endpoint |
| 13 | const resp = await fetch('https://api.example.com/health'); |
| 14 | const data = await resp.json(); |
| 15 | |
| 16 | console.log('=== Service Health ==='); |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 140 | events: (dbHash: string, sessionId: string) => |
| 141 | get<SessionEventData>(`/sessions/${dbHash}/events/${encodeURIComponent(sessionId)}`), |
| 142 | deleteSource: (dbHash: string, sourceId: number) => |
| 143 | fetch(`${API}/content/${dbHash}/source/${sourceId}`, { method: "DELETE" }).then(r => r.json() as Promise<{ ok: boolean }>), |
| 144 | }; |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 532 | }; |
| 533 | ``` |
| 534 | |
| 535 | **Python subprocess list form:** Additionally detects `subprocess.run(["rm", "-rf", "/"])` and extracts args to form `"rm -rf /"` for deny-pattern evaluation. |
| 536 | |
| 537 | **Extracted commands** are checked against the same Bash deny patterns used for direct shell commands. |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 186 | // GOOD: Each function is independently mockable |
| 187 | const api = { |
| 188 | getUser: (id) => fetch(`/users/${id}`), |
| 189 | getOrders: (userId) => fetch(`/users/${userId}/orders`), |
| 190 | createOrder: (data) => fetch('/orders', { method: 'POST', body: data }), |
| 191 | }; |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 192 | // BAD: Mocking requires conditional logic inside the mock |
| 193 | const api = { |
| 194 | fetch: (endpoint, options) => fetch(endpoint, options), |
| 195 | }; |
| 196 | ``` |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 10 | ### curl / wget โ BLOCKED |
| 11 | Shell `curl`/`wget` intercepted and blocked. Do NOT retry. |
| 12 | Use: `context-mode_ctx_fetch_and_index(url, source)` or `context-mode_ctx_execute(language: "javascript", code: "const r = await fetch(...)")` |
| 13 | |
| 14 | ### Inline HTTP โ BLOCKED |
| 15 | `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, `http.request(` โ intercepted. Do NOT retry. |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 10 | ### curl / wget โ FORBIDDEN |
| 11 | Do NOT use `curl`/`wget` in shell. Dumps raw HTTP into context. |
| 12 | Use: `mcp:context-mode:ctx_fetch_and_index(url, source)` or `mcp:context-mode:ctx_execute(language: "javascript", code: "const r = await fetch(...)")` |
| 13 | |
| 14 | ### Inline HTTP โ FORBIDDEN |
| 15 | No `node -e "fetch(..."`, `python -c "requests.get(..."`. Bypasses sandbox. |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 10 | ### curl / wget โ FORBIDDEN |
| 11 | Do NOT use `curl`/`wget` in shell. Dumps raw HTTP into context. |
| 12 | Use: `ctx_fetch_and_index(url, source)` or `ctx_execute(language: "javascript", code: "const r = await fetch(...)")` |
| 13 | |
| 14 | ### Inline HTTP โ FORBIDDEN |
| 15 | No `node -e "fetch(..."`, `python -c "requests.get(..."`. Bypasses sandbox. |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 558 | | Tool | Action | |
| 559 | |------|--------| |
| 560 | | Bash (curl/wget) | Replaces command with echo redirect to `fetch_and_index` | |
| 561 | | Bash (inline HTTP: fetch(), requests.get(), http.get()) | Replaces command with echo redirect to `execute` | |
| 562 | | Bash (other) | Security check, then pass through | |
| 563 | | Read | Adds guidance: use `execute_file` for analysis, Read for editing | |
| 564 | | Grep | Adds guidance: use `execute` with shell for searches | |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 609 | | Tool | Action | |
| 610 | |------|--------| |
| 611 | | Bash (curl/wget) | Replaces command with echo redirect to `ctx_fetch_and_index` | |
| 612 | | Bash (inline HTTP: fetch(), requests.get(), http.get()) | Replaces command with echo redirect to `ctx_execute` | |
| 613 | | Bash (other) | Security check, then pass through | |
| 614 | | Read | Adds guidance: use `ctx_execute_file` for analysis, Read for editing | |
| 615 | | Grep | Adds guidance: use `ctx_execute` with shell for searches | |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 187 | const api = { |
| 188 | getUser: (id) => fetch(`/users/${id}`), |
| 189 | getOrders: (userId) => fetch(`/users/${userId}/orders`), |
| 190 | createOrder: (data) => fetch('/orders', { method: 'POST', body: data }), |
| 191 | }; |
| 192 | |
| 193 | // BAD: Mocking requires conditional logic inside the mock |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 203 | GOOD โ generous timeout for network: |
| 204 | Tool: execute |
| 205 | code: | |
| 206 | const resp = await fetch('https://api.slow-service.com/data'); |
| 207 | console.log(JSON.stringify(await resp.json(), null, 2)); |
| 208 | language: javascript |
| 209 | timeout_ms: 30000 โ 30 seconds for network calls |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 529 | /** |
| 530 | * Extract all string elements from a Python subprocess list call. |
| 531 | * |
| 532 | * subprocess.run(["rm", "-rf", "/"]) โ "rm -rf /" |
| 533 | * |
| 534 | * This catches the list-of-strings form that the single-string regex misses. |
| 535 | */ |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 10 | ### curl / wget โ BLOCKED |
| 11 | Terminal `curl`/`wget` intercepted and blocked. Do NOT retry. |
| 12 | Use: `ctx_fetch_and_index(url, source)` or `ctx_execute(language: "javascript", code: "const r = await fetch(...)")` |
| 13 | |
| 14 | ### Inline HTTP โ BLOCKED |
| 15 | `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, `http.request(` โ intercepted. Do NOT retry. |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 86 | | Situation | Tool | Example | |
| 87 | |-----------|------|---------| |
| 88 | | Hit an API endpoint | `ctx_execute` | `fetch('http://localhost:3000/api/orders')` | |
| 89 | | Run CLI that returns data | `ctx_execute` | `gh pr list`, `aws s3 ls`, `kubectl get pods` | |
| 90 | | Run tests | `ctx_execute` | `npm test`, `pytest`, `go test ./...` | |
| 91 | | Git operations | `ctx_execute` | `git log --oneline -50`, `git diff HEAD~5` | |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 10 | ### curl / wget โ BLOCKED |
| 11 | Bash `curl`/`wget` intercepted and replaced with error. Do NOT retry. |
| 12 | Use: `mcp__context-mode__ctx_fetch_and_index(url, source)` or `mcp__context-mode__ctx_execute(language: "javascript", code: "const r = await fetch(...)")` |
| 13 | |
| 14 | ### Inline HTTP โ BLOCKED |
| 15 | `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, `http.request(` โ intercepted. Do NOT retry. |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 125 | } |
| 126 | |
| 127 | async function get<T>(path: string): Promise<T> { |
| 128 | const r = await fetch(`${API}${path}`); |
| 129 | return r.json() as Promise<T>; |
| 130 | } |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 10 | ### curl / wget โ FORBIDDEN (hook-enforced) |
| 11 | Do NOT use `curl`/`wget` in `bash`. Pi hooks block these. Dumps raw HTTP into context. |
| 12 | Use: `ctx_fetch_and_index(url, source)` or `ctx_execute(language: "javascript", code: "const r = await fetch(...)")` |
| 13 | |
| 14 | ### Inline HTTP โ FORBIDDEN |
| 15 | No `node -e "fetch(..."`, `python -c "requests.get(..."`. Bypasses sandbox. |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 10 | ### curl / wget โ BLOCKED |
| 11 | Shell `curl`/`wget` intercepted and blocked. Do NOT retry. |
| 12 | Use: `mcp__context-mode__ctx_fetch_and_index(url, source)` or `mcp__context-mode__ctx_execute(language: "javascript", code: "const r = await fetch(...)")` |
| 13 | |
| 14 | ### Inline HTTP โ BLOCKED |
| 15 | `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, `http.request(` โ intercepted. Do NOT retry. |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
Network / IO / subprocess call without an explicit timeout. A malicious or hung upstream (HTTP host, socket peer, child process) can pin threads, exhaust connection/process pools, and make the MCP server unresponsive. Always pass a bounded timeout. v2 extends v1 with subprocess coverage (R03 from the legacy readiness audit).
Evidence
| 1192 | Bun.serve({ |
| 1193 | port: PORT, |
| 1194 | hostname: "127.0.0.1", |
| 1195 | fetch(req) { |
| 1196 | const url = new URL(req.url); |
| 1197 | const data = route(req.method, url.pathname, url.searchParams); |
| 1198 | if (data !== null) { |
Remediation
Pass timeout= on every call: - HTTP: `requests.get(url, timeout=5)`, `httpx.get(url, timeout=5.0)` - Node fetch: `AbortSignal.timeout(5000)` - Subprocess: `subprocess.run(["cmd"], timeout=30, check=True)` Pick a value short enough to fail fast and retry.
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 2071 | " Indexing is serial regardless of concurrency โ fetches race, FTS5 writes don't (avoids SQLite WAL contention).\n\n" + |
| 2072 | "When reporting results โ terse like caveman. Technical substance exact. Only fluff die. Pattern: [thing] [action] [reason]. [next step].", |
| 2073 | inputSchema: z.object({ |
| 2074 | url: z.string().optional().describe("Single URL to fetch and index (legacy single-shape)"), |
| 2075 | source: z |
| 2076 | .string() |
| 2077 | .optional() |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" โ the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
MCP tool input schema exposes an unconstrained string/any field with a risky name (command/query/sql/code/script/url/path/expr/ eval). Any caller can pass arbitrary values, which typically widens the tool's blast radius well beyond its intent. Narrow the schema with `.enum()`, `.regex()`, `.max()`, `Literal[...]`, Pydantic `Field(max_length=..., pattern=...)`, or a JSON Schema `enum` / `pattern` / `maxLength`.
Evidence
| 2081 | requests: z |
| 2082 | .array( |
| 2083 | z.object({ |
| 2084 | url: z.string().describe("URL to fetch"), |
| 2085 | source: z.string().optional().describe("Label for this URL's indexed content"), |
| 2086 | }), |
| 2087 | ) |
Remediation
Shape the schema to the tool's actual intent: - Zod: chain `.enum([...])`, `.regex(/.../)`, or `.max(n)`; prefer `z.enum([...])` or `z.literal(...)` when the value set is small. - Pydantic: use `Literal["a", "b"]` or `Field(max_length=..., pattern=r"...")`. - JSON Schema: add `"enum"`, `"pattern"`, or `"maxLength"` to the property. An overbroad schema is an "overpowered tool" โ the model has nothing to prevent it from calling the tool with input far beyond what the tool's prose contract
Package declares an install-time hook (npm postinstall/preinstall/prepare, setup.py cmdclass override, custom setuptools install class, or non-default pyproject build-backend). Anyone installing this package runs the hook. Confirm the hook is necessary and review its contents; prefer shipping a plain library without install-time execution.
Evidence
| 93 | "test:compare": "npx tsx tests/context-comparison.ts", |
| 94 | "test:ecosystem": "npx tsx tests/ecosystem-benchmark.ts", |
| 95 | "install:openclaw": "node -e \"if(process.platform==='win32'){console.error('OpenClaw install requires bash (Git Bash or WSL)');process.exit(1)}else{require('child_process').execSync('bash scripts/install-openclaw-plugin.sh',{stdio:'inherit'})}\"", |
| 96 | "postinstall": "node scripts/postinstall.mjs" |
| 97 | }, |
| 98 | "dependencies": { |
| 99 | "@clack/prompts": "^1.0.1", |
Remediation
Prefer libraries that do not require install-time code execution: - Drop `postinstall`/`preinstall`/`prepare` scripts if the work can happen at runtime or build-time instead. - Ship pre-built native binaries rather than compiling via a custom `cmdclass` or `build_ext` override. - For Dockerfiles: replace `RUN curl โฆ | sh` with a pinned download + checksum verification + explicit `RUN` of a named script. - If the hook is unavoidable, document exactly what it does so downstream reviewers
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 16 | bundle: |
| 17 | runs-on: ubuntu-latest |
| 18 | steps: |
| 19 | - uses: actions/checkout@v4 |
| 20 | |
| 21 | - uses: actions/setup-node@v4 |
| 22 | with: |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 32 | with: |
| 33 | node-version: ${{ env.NODE_VERSION }} |
| 34 | |
| 35 | - uses: actions/setup-python@v5 |
| 36 | with: |
| 37 | python-version: "3.12" |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 28 | steps: |
| 29 | - uses: actions/checkout@v4 |
| 30 | |
| 31 | - uses: actions/setup-node@v4 |
| 32 | with: |
| 33 | node-version: ${{ env.NODE_VERSION }} |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 32 | go-version: "stable" |
| 33 | cache: false |
| 34 | |
| 35 | - uses: erlef/setup-beam@v1 |
| 36 | if: runner.os != 'Windows' |
| 37 | with: |
| 38 | elixir-version: "1.17" |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 111 | - name: Upload OpenClaw logs on failure |
| 112 | if: failure() |
| 113 | uses: actions/upload-artifact@v4 |
| 114 | with: |
| 115 | name: openclaw-logs-${{ matrix.os }} |
| 116 | path: ${{ env.OPENCLAW_STATE_DIR }}/logs/ |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 37 | python-version: "3.12" |
| 38 | |
| 39 | - name: Cache better-sqlite3 native addon |
| 40 | uses: actions/cache@v4 |
| 41 | with: |
| 42 | path: node_modules/better-sqlite3/build |
| 43 | key: better-sqlite3-${{ runner.os }}-node${{ env.NODE_VERSION }}-${{ hashFiles('package-lock.json') }} |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 17 | name: test (${{ matrix.os }}) |
| 18 | |
| 19 | steps: |
| 20 | - uses: actions/checkout@v4 |
| 21 | |
| 22 | - uses: actions/setup-node@v4 |
| 23 | with: |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 23 | with: |
| 24 | node-version: 20 |
| 25 | |
| 26 | - uses: actions/setup-python@v5 |
| 27 | with: |
| 28 | python-version: "3.12" |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 27 | with: |
| 28 | python-version: "3.12" |
| 29 | |
| 30 | - uses: actions/setup-go@v5 |
| 31 | with: |
| 32 | go-version: "stable" |
| 33 | cache: false |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 26 | timeout-minutes: 15 |
| 27 | |
| 28 | steps: |
| 29 | - uses: actions/checkout@v4 |
| 30 | |
| 31 | - uses: actions/setup-node@v4 |
| 32 | with: |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 119 | - name: Upload test output on failure |
| 120 | if: failure() |
| 121 | uses: actions/upload-artifact@v4 |
| 122 | with: |
| 123 | name: test-output-${{ matrix.os }} |
| 124 | path: ${{ runner.temp }}/e2e-output.log |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 12 | update-stats: |
| 13 | runs-on: ubuntu-latest |
| 14 | steps: |
| 15 | - uses: actions/checkout@v4 |
| 16 | |
| 17 | - name: Fetch stats and update |
| 18 | env: |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 103 | - name: Upload session DBs on failure |
| 104 | if: failure() |
| 105 | uses: actions/upload-artifact@v4 |
| 106 | with: |
| 107 | name: session-dbs-${{ matrix.os }} |
| 108 | path: ~/.openclaw/context-mode/sessions/ |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 44 | - name: Cache OpenClaw binary |
| 45 | id: cache-openclaw |
| 46 | uses: actions/cache@v4 |
| 47 | with: |
| 48 | path: ~/.npm-global |
| 49 | key: openclaw-${{ runner.os }}-v${{ env.OPENCLAW_VERSION }} |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 18 | steps: |
| 19 | - uses: actions/checkout@v4 |
| 20 | |
| 21 | - uses: actions/setup-node@v4 |
| 22 | with: |
| 23 | node-version: 20 |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
GitHub Actions `uses:` reference is not pinned to a 40-character commit SHA. Tags (`@v4`) and branches (`@main`) are mutable โ a compromised maintainer or a tag rewrite can substitute malicious code into your CI pipeline silently. Pin to a SHA: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab`. For readability, include the version as a trailing comment: `# v4.1.1`. Tools like `pinact` / `ratchet` automate this. Allowed unpinned forms (excluded by the rule): - Local actions `.
Evidence
| 19 | steps: |
| 20 | - uses: actions/checkout@v4 |
| 21 | |
| 22 | - uses: actions/setup-node@v4 |
| 23 | with: |
| 24 | node-version: 20 |
Remediation
Pin every `uses:` to a 40-character commit SHA. Trailing comment with the version helps reviewers: `uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v4.1.1` Automate the migration with `pinact` (https://github.com/suzuki-shunsuke/pinact) or `ratchet` (https://github.com/sethvargo/ratchet). Add a `pinact run --check` pre-commit hook so future PRs stay pinned. Re-pin when the action releases a new version โ Dependabot can do this automatically with `version-update-strategy: inc
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 9 | `)}function B(t,r){if(t.length===0)return"";let s=new Set,n=[],o=[];for(let e of t)s.has(e.data)||(s.add(e.data),e.type==="rule_content"?n.push(` ${a(e.data)}`):n.push(` ${a(e.data)}`),o.push(e.data));if(n.length===0)return"";let c=h(o);return[` <rules count="${n.length}">`,...n,m(r,c)," </rules>"].join(` |
| 10 | `)}function J(t,r){if(t.length===0)return"";let s=[],n=[];for(let i of t)s.push(` ${a(i.data)}`),n.push(i.data);let o=h(n);return[` <git count="${t.length}">`,...s,m(r,o)," </git>" |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 1000 | // Report network bytes on process exit โ works with both promise and callback patterns. |
| 1001 | // process.on('exit') fires after all I/O completes, unlike .finally() which fires |
| 1002 | // when __cm_main() resolves (immediately for callback-based http.get without await). |
| 1003 | process.on('exit',()=>{if(__cm_net>0)try{process.stderr.write('__CM_NET__:'+__cm_net+'\\n')}catch{}}); |
| 1004 | ;(function(__cm_req){ |
| 1005 | // Intercept globalThis.fetch |
| 1006 | const __cm_f=globalThis.fetch; |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 985 | instrumentedCode = ` |
| 986 | // FS read instrumentation โ count bytes read via fs.readFileSync/readFile |
| 987 | let __cm_fs=0; |
| 988 | process.on('exit',()=>{if(__cm_fs>0)try{process.stderr.write('__CM_FS__:'+__cm_fs+'\\n')}catch{}}); |
| 989 | (function(){ |
| 990 | try{ |
| 991 | var f=typeof require!=='undefined'?require('fs'):null; |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 66 | // Resolve marker directory for this session (stable even on Windows/Git Bash |
| 67 | // where process.ppid shifts every invocation โ see #298). |
| 68 | const dir = guidanceDirFor(sessionId); |
| 69 | try { mkdirSync(dir, { recursive: true }); } catch {} |
| 70 | |
| 71 | // Atomic create-or-fail: O_CREAT | O_EXCL | O_WRONLY |
| 72 | // First process to create the file wins; others get EEXIST. |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 188 | let lockExists = { npm: false, yarn: false, pnpm: false }; |
| 189 | try { fs.accessSync('package-lock.json'); lockExists.npm = true; } catch {} |
| 190 | try { fs.accessSync('yarn.lock'); lockExists.yarn = true; } catch {} |
| 191 | try { fs.accessSync('pnpm-lock.yaml'); lockExists.pnpm = true; } catch {} |
| 192 | |
| 193 | console.log('=== Lock File Status ==='); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 2692 | `console.error("- [ ] Upgrade failed:",e.message);`, |
| 2693 | `process.exit(1);`, |
| 2694 | `}finally{`, |
| 2695 | `try{rmSync(T,{recursive:true,force:true})}catch{}`, |
| 2696 | `}`, |
| 2697 | ].join("\n"); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 342 | // Path traversal guard |
| 343 | if (!resolve(rp).startsWith(cacheRoot + sep)) continue; |
| 344 | // Remove dangling symlink |
| 345 | try { if (lstatSync(rp).isSymbolicLink()) unlinkSync(rp); } catch {} |
| 346 | const parent = dirname(rp); |
| 347 | if (!existsSync(parent)) mkdirSync(parent, { recursive: true }); |
| 348 | if (existsSync(pluginRoot)) { |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 187 | const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); |
| 188 | |
| 189 | let lockExists = { npm: false, yarn: false, pnpm: false }; |
| 190 | try { fs.accessSync('package-lock.json'); lockExists.npm = true; } catch {} |
| 191 | try { fs.accessSync('yarn.lock'); lockExists.yarn = true; } catch {} |
| 192 | try { fs.accessSync('pnpm-lock.yaml'); lockExists.pnpm = true; } catch {} |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 46 | ); |
| 47 | |
| 48 | CREATE INDEX IF NOT EXISTS idx_tool_calls_session ON tool_calls(session_id); |
| 49 | `);try{let t=this.db.pragma("table_xinfo(session_events)"),e=new Set(t.map(s=>s.name));e.has("project_dir")||this.db.exec("ALTER TABLE session_events ADD COLUMN project_dir TEXT NOT NULL DEFAULT ''"),e.has("attribution_source")||this.db.exec("ALTER TABLE session_events ADD COLUMN attribution_source TEXT NOT NULL DEFAULT 'unknown'"),e.has("attribution_confidence")||this.db.exec("ALTER TABLE session_events A |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 107 | updated_at = datetime('now')`),t(n.getToolCallTotals,`SELECT COALESCE(SUM(calls), 0) AS calls, |
| 108 | COALESCE(SUM(bytes_returned), 0) AS bytes_returned |
| 109 | FROM tool_calls WHERE session_id = ?`),t(n.getToolCallByTool,`SELECT tool, calls, bytes_returned |
| 110 | FROM tool_calls WHERE session_id = ? ORDER BY calls DESC`)}insertEvent(t,e,s="PostToolUse",r){let o=f("sha256").update(e.data).digest("hex").slice(0,16).toUpperCase(),a=String(r?.projectDir??e.project_dir??"").trim(),c=String(r?. |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 89 | // Clear ppid-based dir (legacy / fallback callers) and the sessionId dir if given |
| 90 | try { rmSync(guidanceDirFor(), { recursive: true, force: true }); } catch {} |
| 91 | if (sessionId) { |
| 92 | try { rmSync(guidanceDirFor(sessionId), { recursive: true, force: true }); } catch {} |
| 93 | } |
| 94 | } |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 142 | if(!resolve(p).startsWith(cacheRoot+sep))continue; |
| 143 | const parent=dirname(p); |
| 144 | if(!existsSync(parent))continue; |
| 145 | try{if(lstatSync(p).isSymbolicLink())unlinkSync(p)}catch{} |
| 146 | const dirs=readdirSync(parent).filter(d=>/^\\d+\\.\\d+/.test(d)&&statSync(join(parent,d)).isDirectory()); |
| 147 | if(!dirs.length)continue; |
| 148 | dirs.sort((a,b)=>{const pa=a.split(".").map(Number),pb=b.split(".").map(Number);for(let i=0;i<3;i++){if((pa[i]||0)!==(pb[i]||0))return(pa[i]||0)-(pb[i]||0)}return 0 |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 146 | const dirs=readdirSync(parent).filter(d=>/^\\d+\\.\\d+/.test(d)&&statSync(join(parent,d)).isDirectory()); |
| 147 | if(!dirs.length)continue; |
| 148 | dirs.sort((a,b)=>{const pa=a.split(".").map(Number),pb=b.split(".").map(Number);for(let i=0;i<3;i++){if((pa[i]||0)!==(pb[i]||0))return(pa[i]||0)-(pb[i]||0)}return 0}); |
| 149 | try{symlinkSync(join(parent,dirs[dirs.length-1]),p,process.platform==="win32"?"junction":undefined)}catch{} |
| 150 | } |
| 151 | } |
| 152 | }catch{} |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 40 | for (const rel of ["../package.json", "./package.json"]) { |
| 41 | const p = resolve(__pkg_dir, rel); |
| 42 | if (existsSync(p)) { |
| 43 | try { return JSON.parse(readFileSync(p, "utf8")).version; } catch {} |
| 44 | } |
| 45 | } |
| 46 | return "unknown"; |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 249 | .get(testSessionId, testSessionId.slice(0,8) + "%"); |
| 250 | d.close(); |
| 251 | if (row) { chosenDb = f; break; } |
| 252 | } catch {} |
| 253 | } |
| 254 | |
| 255 | // Fallback: most recently modified |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 149 | try{symlinkSync(join(parent,dirs[dirs.length-1]),p,process.platform==="win32"?"junction":undefined)}catch{} |
| 150 | } |
| 151 | } |
| 152 | }catch{} |
| 153 | `; |
| 154 | writeFileSync(healHookPath, healScript, { mode: 0o755 }); |
| 155 | } |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 1005 | // Intercept globalThis.fetch |
| 1006 | const __cm_f=globalThis.fetch; |
| 1007 | globalThis.fetch=async(...a)=>{const r=await __cm_f(...a); |
| 1008 | try{const cl=r.clone();const b=await cl.arrayBuffer();__cm_net+=b.byteLength}catch{} |
| 1009 | return r}; |
| 1010 | // Shadow CJS require with http/https network tracking. |
| 1011 | const __cm_hc=new Map(); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 118 | // Clean up old bash version if it exists |
| 119 | const oldBashHook = resolve(globalHooksDir, "context-mode-cache-heal.sh"); |
| 120 | if (existsSync(oldBashHook)) { |
| 121 | try { unlinkSync(oldBashHook); } catch {} |
| 122 | } |
| 123 | if (!existsSync(healHookPath)) { |
| 124 | if (!existsSync(globalHooksDir)) mkdirSync(globalHooksDir, { recursive: true }); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 41 | // Path traversal guard |
| 42 | if (!resolve(rp).startsWith(cacheRoot + sep)) continue; |
| 43 | // Remove dangling symlink |
| 44 | try { if (lstatSync(rp).isSymbolicLink()) unlinkSync(rp); } catch {} |
| 45 | const rpParent = dirname(rp); |
| 46 | if (!existsSync(rpParent)) mkdirSync(rpParent, { recursive: true }); |
| 47 | try { |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 1688 | totalSize += formatted.length; |
| 1689 | } |
| 1690 | } finally { |
| 1691 | try { timelineDB?.close(); } catch {} |
| 1692 | } |
| 1693 | |
| 1694 | let output = sections.join("\n\n---\n\n"); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 1 | import{createRequire as I}from"node:module";import{existsSync as U,unlinkSync as v,renameSync as M}from"node:fs";import{tmpdir as x}from"node:os";import{join as F}from"node:path";var g=class{#t;constructor(t){this.#t=t}pragma(t){let s=this.#t.prepare(`PRAGMA ${t}`).all();if(!s||s.length===0)return;if(s.length>1)return s;let r=Object.values(s[0]);return r.length===1?r[0]:s[0]}exec(t){let e="",s=null;for(let o=0;o<t.length;o++){let a=t[o];if(s)e+=a,a===s&&(s=null);else if(a==="'"||a==='"')e+=a,s=a |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 83 | if (!resolve(rp).startsWith(cacheRoot + sep)) continue; |
| 84 | try { |
| 85 | // Remove dangling symlink before creating new one |
| 86 | try { if (lstatSync(rp).isSymbolicLink()) unlinkSync(rp); } catch {} |
| 87 | const rpParent = dirname(rp); |
| 88 | if (!existsSync(rpParent)) mkdirSync(rpParent, { recursive: true }); |
| 89 | symlinkSync(__dirname, rp, process.platform === "win32" ? "junction" : undefined); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 861 | conns.forEach(c => c.close()); db.close(); |
| 862 | console.log(errors === 0 ? 'PASS: 90 writes, 0 SQLITE_BUSY' : 'FAIL: ' + errors + ' errors'); |
| 863 | } catch(e) { console.log('FAIL: ' + e.message); } |
| 864 | finally { try { fs.unlinkSync(dbPath); fs.unlinkSync(dbPath+'-wal'); fs.unlinkSync(dbPath+'-shm'); } catch {} } |
| 865 | " 2>/dev/null || echo "FAIL: timeout")" |
| 866 | check "Concurrent SQLite writes (3 conns ร 30)" "$(echo "$CONCUR" | grep -q '^PASS' && echo true || echo false)" |
| 867 | [ "$(echo "$CONCUR" | grep -q '^PASS' && |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 70 | return true; |
| 71 | } catch { |
| 72 | // Dead PID or unreadable โ clean up stale sentinel |
| 73 | try { unlinkSync(fullPath); } catch {} |
| 74 | } |
| 75 | } |
| 76 | return false; |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 87 | export function resetGuidanceThrottle(sessionId) { |
| 88 | _guidanceShown.clear(); |
| 89 | // Clear ppid-based dir (legacy / fallback callers) and the sessionId dir if given |
| 90 | try { rmSync(guidanceDirFor(), { recursive: true, force: true }); } catch {} |
| 91 | if (sessionId) { |
| 92 | try { rmSync(guidanceDirFor(sessionId), { recursive: true, force: true }); } catch {} |
| 93 | } |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 556 | npmExec("npm install --production=false", { cwd: cacheDir, stdio: "inherit", timeout: 300000 }); |
| 557 | } catch { |
| 558 | // Clean up partial install so next run retries fresh |
| 559 | try { rmSync(join(cacheDir, "node_modules"), { recursive: true, force: true }); } catch {} |
| 560 | throw new Error("npm install failed โ please retry"); |
| 561 | } |
| 562 | // Sentinel check: verify install completed (cold cache can timeout leaving partial node_modules) |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 189 | let lockExists = { npm: false, yarn: false, pnpm: false }; |
| 190 | try { fs.accessSync('package-lock.json'); lockExists.npm = true; } catch {} |
| 191 | try { fs.accessSync('yarn.lock'); lockExists.yarn = true; } catch {} |
| 192 | try { fs.accessSync('pnpm-lock.yaml'); lockExists.pnpm = true; } catch {} |
| 193 | |
| 194 | console.log('=== Lock File Status ==='); |
| 195 | Object.entries(lockExists).forEach(([mgr, exists]) => { |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 994 | f.readFileSync=function(){var r=ors.apply(this,arguments);if(Buffer.isBuffer(r))__cm_fs+=r.length;else if(typeof r==='string')__cm_fs+=Buffer.byteLength(r);return r;}; |
| 995 | var orf=f.readFile; |
| 996 | if(orf)f.readFile=function(){var a=Array.from(arguments),cb=a.pop();orf.apply(this,a.concat([function(e,d){if(!e&&d){if(Buffer.isBuffer(d))__cm_fs+=d.length;else if(typeof d==='string')__cm_fs+=Buffer.byteLength(d);}cb(e,d);}]));}; |
| 997 | }catch{} |
| 998 | })(); |
| 999 | let __cm_net=0; |
| 1000 | // Report network bytes on process exit |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 84 | const CM_FS_PRELOAD = join(tmpdir(), `cm-fs-preload-${process.pid}.js`); |
| 85 | writeFileSync( |
| 86 | CM_FS_PRELOAD, |
| 87 | `(function(){var __cm_fs=0;process.on('exit',function(){if(__cm_fs>0)try{process.stderr.write('__CM_FS__:'+__cm_fs+'\\n')}catch(e){}});try{var f=require('fs');var ors=f.readFileSync;f.readFileSync=function(){var r=ors.apply(this,arguments);if(Buffer.isBuffer(r))__cm_fs+=r.length;else if(typeof r==='string')__cm_fs+=Buffer.byteLength(r);return r;};}catch(e){}})();\n`, |
| 88 | ); |
| 89 | |
| 90 | // Lazy singleton โ |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 383 | const dbPath = join(CONTENT_DIR, `${dbHash}.db`); |
| 384 | const db = isBun ? new Database(dbPath) : new Database(dbPath); |
| 385 | db.prepare("DELETE FROM chunks WHERE source_id = ?").run(sourceId); |
| 386 | try { db.prepare("DELETE FROM chunks_trigram WHERE source_id = ?").run(sourceId); } catch {} |
| 387 | db.prepare("DELETE FROM sources WHERE id = ?").run(sourceId); |
| 388 | db.close(); |
| 389 | return { ok: true }; |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 8 | `)}function F(t,r){if(t.length===0)return"";let s=new Set,n=[],o=[];for(let e of t)s.has(e.data)||(s.add(e.data),n.push(` ${a(e.data)}`),o.push(e.data));if(n.length===0)return"";let c=h(o);return[` <decisions count="${n.length}">`,...n,m(r,c)," </decisions>"].join(` |
| 9 | `)}function B(t,r){if(t.length===0)return"";let s=new Set,n=[],o=[];for(let e of t)s.has(e.data)||(s.add(e.data),e.type==="rule_content"?n.push(` ${a(e.data)}`):n.push(` ${a(e.data)}`),o.push(e.data));if(n.length===0)retur |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 885 | try { |
| 886 | const reg = await adapter.checkPluginRegistration(); |
| 887 | if (reg) console.log(reg.status + ': ' + reg.check + ' โ ' + (reg.message || '')); |
| 888 | } catch {} |
| 889 | } catch(e) { console.log('error: ' + e.message); } |
| 890 | " 2>/dev/null || echo "error: timeout")" |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 2897 | }); |
| 2898 | } catch { |
| 2899 | // Clean up partial install so next run retries fresh |
| 2900 | try { rmSync(join(cacheDir, "node_modules"), { recursive: true, force: true }); } catch {} |
| 2901 | throw new Error("npm install failed โ please retry"); |
| 2902 | } |
| 2903 | // Sentinel check: verify install completed (cold cache can timeout leaving partial node_modules) |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.
Silent error swallowing detected. An except clause that does pass or ... discards the exception with no log, no metric, and no trace. This blinds incident response and hides real failures.
Evidence
| 1052 | } else if (e.t === 'cfg') { |
| 1053 | sec.configs.push({ name: e.k, path: e.path, exists: e.exists, content: e.content || null }); |
| 1054 | } |
| 1055 | } catch {} |
| 1056 | } |
| 1057 | result.summary = { pass, fail, warnings: warns, total: pass + fail }; |
| 1058 | fs.writeFileSync('$JSON_FILE', JSON.stringify(result, null, 2)); |
Remediation
Log the exception at minimum (`logger.exception(e)`), emit a metric, or re-raise if the error is not recoverable. If you genuinely want to ignore an exception, say so with a comment.