fix(security): CVE-1 dependency pins + wire security scan result persistence

Two parts of the v3 security overhaul's CVE-1 (vulnerable dependencies)
category, done via the repo's own override mechanism rather than
`npm audit fix` (which is wrong for this pnpm monorepo and whose
opentelemetry "fix" is a destructive downgrade to agentdb@1.6.1 off the
3.x-alpha line).

- Dependency pins (source-level overrides, following the existing pattern):
  - root package.json: add missing js-yaml (>=4.3.0) — GHSA-h67p-54hq-rp68
    quadratic-DoS; root already pinned express/qs/opentelemetry.
  - v3/package.json pnpm.overrides: add js-yaml, express (>=4.22.2, qs DoS
    via body-parser), qs (>=6.15.2), and the @opentelemetry core/resources/
    sdk-trace-base/sdk-node set (>=2.8.0 / >=0.220.0) mirroring root's proven
    values — resolves the otel chain WITHOUT the agentdb downgrade.
  - Lockfiles are intentionally not regenerated here: the installed pnpm (11)
    would rewrite v3's lockfileVersion 6.0 → 9.0; regen must run under the
    repo's declared pnpm@8.15.0.

- Scan-result persistence: `security scan` now writes its result to
  `<target>/.claude/security-scans/scan-<type>-<depth>.json`, the exact path
  funnel/local-signals.ts:getSecurityStatus() reads for the statusline's
  security indicator. Best-effort (never fails the scan); deterministic name
  so repeated runs overwrite rather than accumulate. Verified end-to-end:
  getSecurityStatus goes PENDING/0 → IN_PROGRESS/1 after a scan.

Co-Authored-By: RuFlo <ruv@ruv.net>
This commit is contained in:
ruv committed 2026-07-12 16:20:12 -04:00
1 parent 05128db783
commit 7cf3b10848
3 files changed
+38 -1

No files matched your search

+1
View File
@@ -81,6 +81,7 @@
"overrides": {
"ruvector": "^0.2.27",
"better-sqlite3": ">=12.8.0",
"js-yaml": ">=4.3.0",
"hono": ">=4.12.25",
"@ruvector/rvf-wasm": "0.1.5",
"@hono/node-server": ">=1.19.14",
@@ -219,6 +219,35 @@ const scanCommand: Command = {
`Total Issues: ${findings.length}`,
].join('\n'), 'Scan Summary');
// Persist the scan result so downstream consumers (the statusline's
// getSecurityStatus in funnel/local-signals.ts, which reads
// `.claude/security-scans/*.json`) reflect real scan state. Best-effort:
// a failed write must never fail the scan itself.
try {
const scanDirOut = path.join(path.resolve(target), '.claude', 'security-scans');
fs.mkdirSync(scanDirOut, { recursive: true });
const record = {
timestamp: new Date().toISOString(),
target,
depth,
type: scanType,
summary: {
critical: criticalCount,
high: highCount,
medium: mediumCount,
low: lowCount,
total: findings.length,
},
findings,
};
// Deterministic name keyed on scan config so repeated runs overwrite
// rather than accumulate stale reports.
const outFile = path.join(scanDirOut, `scan-${scanType}-${depth}.json`);
fs.writeFileSync(outFile, JSON.stringify(record, null, 2));
} catch {
// Persistence is advisory only — ignore write failures.
}
// Auto-fix if requested
if (fix && criticalCount + highCount > 0) {
output.writeln();
+8 -1
View File
@@ -70,7 +70,14 @@
"@vitest/coverage-v8": ">=4.1.0",
"handlebars": ">=4.7.9",
"protobufjs": ">=8.6.0",
"@ruvector/ruvllm": ">=2.6.0"
"@ruvector/ruvllm": ">=2.6.0",
"js-yaml": ">=4.3.0",
"express": ">=4.22.2",
"qs": ">=6.15.2",
"@opentelemetry/core": ">=2.8.0",
"@opentelemetry/resources": ">=2.8.0",
"@opentelemetry/sdk-trace-base": ">=2.8.0",
"@opentelemetry/sdk-node": ">=0.220.0"
}
}
}