@securecode-ai/mcp 0.5.5 → 0.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/dist/api/types.d.ts +7 -0
  2. package/dist/approval/auditLog.d.ts +1 -1
  3. package/dist/approval/auditLog.js +11 -3
  4. package/dist/approval/auditLog.js.map +1 -1
  5. package/dist/approval/broker.d.ts +7 -2
  6. package/dist/approval/broker.js +239 -110
  7. package/dist/approval/broker.js.map +1 -1
  8. package/dist/approval/policy.d.ts +10 -0
  9. package/dist/approval/policy.js +104 -0
  10. package/dist/approval/policy.js.map +1 -0
  11. package/dist/approval/types.d.ts +11 -2
  12. package/dist/approval/types.js +10 -1
  13. package/dist/approval/types.js.map +1 -1
  14. package/dist/attack/agentScanExecutor.d.ts +35 -1
  15. package/dist/attack/agentScanExecutor.js +405 -76
  16. package/dist/attack/agentScanExecutor.js.map +1 -1
  17. package/dist/attack/agentScanLoop.d.ts +20 -0
  18. package/dist/attack/agentScanLoop.js +1264 -60
  19. package/dist/attack/agentScanLoop.js.map +1 -1
  20. package/dist/attack/agentScanProtocol.d.ts +382 -6
  21. package/dist/attack/agentScanProtocol.js +110 -4
  22. package/dist/attack/agentScanProtocol.js.map +1 -1
  23. package/dist/attack/agentTrace.d.ts +73 -0
  24. package/dist/attack/agentTrace.js +228 -0
  25. package/dist/attack/agentTrace.js.map +1 -0
  26. package/dist/attack/architectureScoutExecutor.d.ts +18 -0
  27. package/dist/attack/architectureScoutExecutor.js +211 -0
  28. package/dist/attack/architectureScoutExecutor.js.map +1 -0
  29. package/dist/attack/architectureScoutLoop.d.ts +36 -0
  30. package/dist/attack/architectureScoutLoop.js +403 -0
  31. package/dist/attack/architectureScoutLoop.js.map +1 -0
  32. package/dist/attack/architectureScoutProtocol.d.ts +209 -0
  33. package/dist/attack/architectureScoutProtocol.js +47 -0
  34. package/dist/attack/architectureScoutProtocol.js.map +1 -0
  35. package/dist/attack/candidateStore.d.ts +95 -0
  36. package/dist/attack/candidateStore.js +231 -0
  37. package/dist/attack/candidateStore.js.map +1 -0
  38. package/dist/attack/evidenceLedger.d.ts +67 -0
  39. package/dist/attack/evidenceLedger.js +192 -0
  40. package/dist/attack/evidenceLedger.js.map +1 -0
  41. package/dist/attack/finishGate.d.ts +62 -0
  42. package/dist/attack/finishGate.js +209 -0
  43. package/dist/attack/finishGate.js.map +1 -0
  44. package/dist/attack/fixCodeMerge.d.ts +27 -0
  45. package/dist/attack/fixCodeMerge.js +42 -0
  46. package/dist/attack/fixCodeMerge.js.map +1 -0
  47. package/dist/attack/fixVerifyLoop.d.ts +55 -0
  48. package/dist/attack/fixVerifyLoop.js +187 -0
  49. package/dist/attack/fixVerifyLoop.js.map +1 -0
  50. package/dist/attack/investigationProfiles.d.ts +36 -0
  51. package/dist/attack/investigationProfiles.js +144 -0
  52. package/dist/attack/investigationProfiles.js.map +1 -0
  53. package/dist/attack/investigationState.d.ts +227 -0
  54. package/dist/attack/investigationState.js +666 -0
  55. package/dist/attack/investigationState.js.map +1 -0
  56. package/dist/attack/mutationOperators.d.ts +22 -0
  57. package/dist/attack/mutationOperators.js +170 -0
  58. package/dist/attack/mutationOperators.js.map +1 -0
  59. package/dist/attack/mutationTest.d.ts +33 -0
  60. package/dist/attack/mutationTest.js +110 -0
  61. package/dist/attack/mutationTest.js.map +1 -0
  62. package/dist/attack/proofGate.d.ts +20 -0
  63. package/dist/attack/proofGate.js +104 -0
  64. package/dist/attack/proofGate.js.map +1 -0
  65. package/dist/attack/proofTypes.d.ts +57 -0
  66. package/dist/attack/proofTypes.js +32 -0
  67. package/dist/attack/proofTypes.js.map +1 -0
  68. package/dist/attack/protocolValidator.d.ts +50 -0
  69. package/dist/attack/protocolValidator.js +427 -0
  70. package/dist/attack/protocolValidator.js.map +1 -0
  71. package/dist/attack/qualityMetrics.d.ts +133 -0
  72. package/dist/attack/qualityMetrics.js +226 -0
  73. package/dist/attack/qualityMetrics.js.map +1 -0
  74. package/dist/attack/scanScheduler.d.ts +52 -0
  75. package/dist/attack/scanScheduler.js +265 -0
  76. package/dist/attack/scanScheduler.js.map +1 -0
  77. package/dist/attack/scanState.d.ts +58 -0
  78. package/dist/attack/scanState.js +102 -0
  79. package/dist/attack/scanState.js.map +1 -0
  80. package/dist/attack/searchIntent.d.ts +16 -0
  81. package/dist/attack/searchIntent.js +57 -0
  82. package/dist/attack/searchIntent.js.map +1 -0
  83. package/dist/attack/verifyLoop.d.ts +43 -0
  84. package/dist/attack/verifyLoop.js +314 -14
  85. package/dist/attack/verifyLoop.js.map +1 -1
  86. package/dist/attack/workItem.d.ts +57 -0
  87. package/dist/attack/workItem.js +225 -0
  88. package/dist/attack/workItem.js.map +1 -0
  89. package/dist/audit/findingReviewQueue.d.ts +109 -0
  90. package/dist/audit/findingReviewQueue.js +335 -0
  91. package/dist/audit/findingReviewQueue.js.map +1 -0
  92. package/dist/audit/scanAuditLog.d.ts +160 -0
  93. package/dist/audit/scanAuditLog.js +404 -0
  94. package/dist/audit/scanAuditLog.js.map +1 -0
  95. package/dist/dependency/dependencyChecker.js +35 -9
  96. package/dist/dependency/dependencyChecker.js.map +1 -1
  97. package/dist/dependency/exploitPriority.d.ts +33 -0
  98. package/dist/dependency/exploitPriority.js +78 -0
  99. package/dist/dependency/exploitPriority.js.map +1 -0
  100. package/dist/dependency/finding.d.ts +16 -0
  101. package/dist/dependency/osvClient.js +2 -0
  102. package/dist/dependency/osvClient.js.map +1 -1
  103. package/dist/dependency/types.d.ts +12 -1
  104. package/dist/mcp/server.js +13 -2
  105. package/dist/mcp/server.js.map +1 -1
  106. package/dist/mcp/tools.d.ts +1 -0
  107. package/dist/mcp/tools.js +127 -6
  108. package/dist/mcp/tools.js.map +1 -1
  109. package/dist/project-map/agentMemory.d.ts +83 -1
  110. package/dist/project-map/agentMemory.js +197 -7
  111. package/dist/project-map/agentMemory.js.map +1 -1
  112. package/dist/project-map/architectureContext.d.ts +202 -0
  113. package/dist/project-map/architectureContext.js +421 -0
  114. package/dist/project-map/architectureContext.js.map +1 -0
  115. package/dist/project-map/blastRadius.d.ts +54 -0
  116. package/dist/project-map/blastRadius.js +196 -0
  117. package/dist/project-map/blastRadius.js.map +1 -0
  118. package/dist/project-map/callGraphExtractor.d.ts +13 -0
  119. package/dist/project-map/callGraphExtractor.js +222 -0
  120. package/dist/project-map/callGraphExtractor.js.map +1 -0
  121. package/dist/project-map/capabilityRegistry.d.ts +46 -0
  122. package/dist/project-map/capabilityRegistry.js +91 -0
  123. package/dist/project-map/capabilityRegistry.js.map +1 -0
  124. package/dist/project-map/findTests.d.ts +29 -0
  125. package/dist/project-map/findTests.js +236 -0
  126. package/dist/project-map/findTests.js.map +1 -0
  127. package/dist/project-map/handlerInventory.d.ts +112 -0
  128. package/dist/project-map/handlerInventory.js +184 -0
  129. package/dist/project-map/handlerInventory.js.map +1 -0
  130. package/dist/project-map/implementationResolver.d.ts +43 -0
  131. package/dist/project-map/implementationResolver.js +217 -0
  132. package/dist/project-map/implementationResolver.js.map +1 -0
  133. package/dist/project-map/mapContext.d.ts +6 -1
  134. package/dist/project-map/mapContext.js +1 -0
  135. package/dist/project-map/mapContext.js.map +1 -1
  136. package/dist/project-map/scanCache.d.ts +57 -3
  137. package/dist/project-map/scanCache.js +61 -2
  138. package/dist/project-map/scanCache.js.map +1 -1
  139. package/dist/project-map/symbolIndex.d.ts +39 -0
  140. package/dist/project-map/symbolIndex.js +385 -0
  141. package/dist/project-map/symbolIndex.js.map +1 -0
  142. package/dist/tooling/agentEvalScoring.d.ts +77 -0
  143. package/dist/tooling/agentEvalScoring.js +140 -0
  144. package/dist/tooling/agentEvalScoring.js.map +1 -0
  145. package/dist/tooling/agentRegression.d.ts +53 -0
  146. package/dist/tooling/agentRegression.js +99 -0
  147. package/dist/tooling/agentRegression.js.map +1 -0
  148. package/dist/tools/agentScan.d.ts +69 -0
  149. package/dist/tools/agentScan.js +702 -43
  150. package/dist/tools/agentScan.js.map +1 -1
  151. package/dist/tools/findingReviewTools.d.ts +22 -0
  152. package/dist/tools/findingReviewTools.js +121 -0
  153. package/dist/tools/findingReviewTools.js.map +1 -0
  154. package/dist/tools/fix.js +1 -1
  155. package/dist/tools/fix.js.map +1 -1
  156. package/dist/tools/map.js +191 -1
  157. package/dist/tools/map.js.map +1 -1
  158. package/dist/tools/runTests.d.ts +2 -0
  159. package/dist/tools/runTests.js +29 -0
  160. package/dist/tools/runTests.js.map +1 -0
  161. package/dist/utils/effectMock.d.ts +1 -0
  162. package/dist/utils/effectMock.js +162 -0
  163. package/dist/utils/effectMock.js.map +1 -0
  164. package/dist/utils/gitContext.d.ts +26 -0
  165. package/dist/utils/gitContext.js +317 -0
  166. package/dist/utils/gitContext.js.map +1 -0
  167. package/dist/utils/localTestRunner.d.ts +57 -2
  168. package/dist/utils/localTestRunner.js +122 -115
  169. package/dist/utils/localTestRunner.js.map +1 -1
  170. package/dist/utils/securityConfig.d.ts +17 -0
  171. package/dist/utils/securityConfig.js +192 -0
  172. package/dist/utils/securityConfig.js.map +1 -0
  173. package/dist/utils/testCommandPolicy.d.ts +36 -0
  174. package/dist/utils/testCommandPolicy.js +252 -0
  175. package/dist/utils/testCommandPolicy.js.map +1 -0
  176. package/dist/utils/testRunner.d.ts +56 -0
  177. package/dist/utils/testRunner.js +246 -0
  178. package/dist/utils/testRunner.js.map +1 -0
  179. package/dist/utils/testSafety.d.ts +40 -2
  180. package/dist/utils/testSafety.js +205 -26
  181. package/dist/utils/testSafety.js.map +1 -1
  182. package/dist/utils/verificationSandbox.d.ts +113 -0
  183. package/dist/utils/verificationSandbox.js +656 -0
  184. package/dist/utils/verificationSandbox.js.map +1 -0
  185. package/package.json +1 -1
@@ -1,131 +1,138 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
2
+ /**
3
+ * Local test runner — drives execution of LLM-generated verification tests
4
+ * through the verification sandbox.
5
+ *
6
+ * SECURITY MODEL (post-rewrite):
7
+ * 1. `checkTestSafety()` runs first as defense-in-depth. If it blocks,
8
+ * we return early without spawning anything.
9
+ * 2. `detectSandbox()` returns the best available real isolation backend
10
+ * (Docker preferred, Deno as a JS/TS-only fallback). If neither is
11
+ * available, this runner returns `sandbox-unavailable` — it does NOT
12
+ * fall back to executing the script with host privileges.
13
+ * 3. The sandbox backend executes the script with no network, a
14
+ * read-only workspace, a tmpfs /tmp, capped CPU/memory/pids, and a
15
+ * scrubbed env (only NODE_ENV and PATH). The verdict is parsed from
16
+ * stdout/stderr against `/PASS:/` and `/FAIL:/` markers.
17
+ *
18
+ * The previous implementation spread the full `process.env` into the
19
+ * child and ran via `execFileSync` with no isolation. That allowed
20
+ * prompt-injected content in scanned source to ride into the
21
+ * verify-generate prompt and produce a test that exfiltrated secrets.
22
+ */
35
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.SANDBOX_UNAVAILABLE_MESSAGE = void 0;
36
25
  exports.runLocalTest = runLocalTest;
37
- const fs = __importStar(require("fs"));
38
- const path = __importStar(require("path"));
39
- const child_process_1 = require("child_process");
26
+ exports.runTestCommand = runTestCommand;
40
27
  const testSafety_1 = require("./testSafety");
41
- const PASS_PATTERN = /^PASS:\s*(.+)$/m;
42
- const FAIL_PATTERN = /^FAIL:\s*(.+)$/m;
43
- const TIMEOUT_MS = 30_000;
44
- async function runLocalTest(script, runner, workspaceRoot) {
28
+ const effectMock_1 = require("./effectMock");
29
+ const verificationSandbox_1 = require("./verificationSandbox");
30
+ const DEFAULT_TIMEOUT_MS = 30_000;
31
+ /**
32
+ * The message shown when no isolation backend is available. Exported so the
33
+ * agent-scan tool can reuse it in its top-level `verifyHint` (instead of
34
+ * every finding carrying the full text in its `provenReason`).
35
+ *
36
+ * Why this matters: without a sandbox, the verify loop returns INCONCLUSIVE
37
+ * for every high/medium finding. The headline differentiator of Pipeline 2
38
+ * ("exploit-verified, not just LLM-believed") is offline. The user needs to
39
+ * know — in one place, with a copy-pasteable install path — what to do.
40
+ */
41
+ exports.SANDBOX_UNAVAILABLE_MESSAGE = 'No verification sandbox backend (Docker or Deno) was detected locally. ' +
42
+ 'Exploit verification was skipped — the finding is reported as INCONCLUSIVE ' +
43
+ 'with confidence capped at 75%. To enable exploit-verified findings:\n' +
44
+ ' • Docker (preferred, supports any language): https://docs.docker.com/get-docker\n' +
45
+ ' • Deno (JS/TS only, lighter install): https://deno.com/#installation\n' +
46
+ 'If neither is available, the API-side sandbox (on the server) is used as an ' +
47
+ 'automatic fallback — no local install required, but slower (network round-trip per finding).';
48
+ async function runLocalTest(script, runner, workspaceRoot, options) {
49
+ // 1. Defense-in-depth static check.
45
50
  const safety = (0, testSafety_1.checkTestSafety)(script, workspaceRoot);
46
51
  if (!safety.allowed) {
47
- return { verdict: 'error', output: `Test script blocked: ${safety.reason}`, exitCode: -1 };
52
+ return { verdict: 'blocked', output: `Test script blocked: ${safety.reason}`, exitCode: -1 };
48
53
  }
49
- const testDir = path.join(workspaceRoot, '.securecode');
50
- if (!fs.existsSync(testDir))
51
- fs.mkdirSync(testDir, { recursive: true });
52
- const isPython = runner === 'python' || runner === 'python3';
53
- const isTsRunner = runner === 'tsx' || runner === 'ts' || runner === 'bun' || runner === 'deno' || runner === 'pnpm-tsx' || runner === 'yarn-tsx';
54
- const ext = isPython ? '.py' : (isTsRunner ? '.test.ts' : '.test.js');
55
- const testFile = path.join(testDir, `verify-test-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${ext}`);
56
- try {
57
- fs.writeFileSync(testFile, script, 'utf8');
58
- let stdout = '';
59
- let stderr = '';
60
- let exitCode = 0;
61
- let timedOut = false;
62
- try {
63
- const isWindows = process.platform === 'win32';
64
- let runnerBin;
65
- let runnerArgs;
66
- if (runner === 'tsx') {
67
- runnerBin = 'npx';
68
- runnerArgs = ['tsx', testFile];
69
- }
70
- else if (runner === 'pnpm-tsx') {
71
- runnerBin = 'pnpm';
72
- runnerArgs = ['exec', 'tsx', testFile];
73
- }
74
- else if (runner === 'yarn-tsx') {
75
- runnerBin = 'yarn';
76
- runnerArgs = ['tsx', testFile];
77
- }
78
- else if (runner === 'deno') {
79
- runnerBin = 'deno';
80
- runnerArgs = ['run', '--allow-read', '--allow-env', testFile];
81
- }
82
- else if (runner === 'bun' && isWindows) {
83
- runnerBin = 'npx';
84
- runnerArgs = ['bun', testFile];
85
- }
86
- else {
87
- runnerBin = runner;
88
- runnerArgs = [testFile];
89
- }
90
- stdout = (0, child_process_1.execFileSync)(runnerBin, runnerArgs, {
91
- cwd: workspaceRoot,
92
- timeout: TIMEOUT_MS,
93
- encoding: 'utf8',
94
- stdio: ['pipe', 'pipe', 'pipe'],
95
- env: { ...process.env, NODE_ENV: 'test' },
96
- shell: isWindows,
97
- });
98
- }
99
- catch (err) {
100
- stdout = err.stdout || '';
101
- stderr = err.stderr || '';
102
- exitCode = err.status ?? 1;
103
- if (err.signal === 'SIGTERM')
104
- timedOut = true;
105
- }
106
- const output = (stdout + '\n' + stderr).trim();
107
- if (timedOut) {
108
- return { verdict: 'timeout', output: 'Test timed out after 30s', exitCode: -1 };
109
- }
110
- if (PASS_PATTERN.test(output)) {
111
- return { verdict: 'pass', output, exitCode };
112
- }
113
- if (FAIL_PATTERN.test(output)) {
114
- return { verdict: 'fail', output, exitCode };
115
- }
116
- if (exitCode === 0) {
117
- return { verdict: 'error', output: output + '\nTest exited 0 but did not print PASS: or FAIL:', exitCode };
54
+ if (options?.setupScript) {
55
+ const setupSafety = (0, testSafety_1.checkTestSafety)(options.setupScript, workspaceRoot);
56
+ if (!setupSafety.allowed) {
57
+ return { verdict: 'blocked', output: `Setup script blocked: ${setupSafety.reason}`, exitCode: -1 };
118
58
  }
119
- return { verdict: 'error', output, exitCode };
120
59
  }
121
- catch (err) {
122
- return { verdict: 'error', output: err.message || String(err), exitCode: -1 };
60
+ // 2. Resolve the sandbox backend. Production: detectSandbox(). Tests: inject.
61
+ const backend = options?.sandboxBackend ?? (0, verificationSandbox_1.detectSandbox)();
62
+ if (!backend) {
63
+ return {
64
+ verdict: 'sandbox-unavailable',
65
+ output: exports.SANDBOX_UNAVAILABLE_MESSAGE,
66
+ exitCode: -1,
67
+ };
123
68
  }
124
- finally {
69
+ // 2b. Auto-create effect mock for JS/TS projects (harmless if unused).
70
+ // Must happen before the sandbox mounts the workspace.
71
+ if (runner !== 'python' && runner !== 'python3') {
125
72
  try {
126
- fs.unlinkSync(testFile);
73
+ (0, effectMock_1.createEffectMock)(workspaceRoot);
127
74
  }
128
75
  catch { }
129
76
  }
77
+ // 3. Execute inside the sandbox.
78
+ const execOpts = {
79
+ script,
80
+ runner,
81
+ workspaceRoot,
82
+ setupScript: options?.setupScript,
83
+ timeoutMs: options?.timeoutMs ?? DEFAULT_TIMEOUT_MS,
84
+ signal: options?.signal,
85
+ };
86
+ const result = await backend.execute(execOpts);
87
+ // Preserve the "exited 0 but no PASS/FAIL marker" message — it's a
88
+ // useful signal that the test ran but didn't follow the protocol.
89
+ if (result.verdict === 'error' && result.exitCode === 0) {
90
+ return {
91
+ verdict: 'error',
92
+ output: `${result.output}\nTest exited 0 but did not print PASS: or FAIL:`,
93
+ exitCode: result.exitCode,
94
+ backend: result.backend,
95
+ };
96
+ }
97
+ return {
98
+ verdict: result.verdict,
99
+ output: result.output,
100
+ exitCode: result.exitCode,
101
+ backend: result.backend,
102
+ };
103
+ }
104
+ /**
105
+ * Run a validated test command (npm test, pytest, etc.) inside the sandbox.
106
+ * Uses command mode — no script file is written; the executable + args are
107
+ * passed directly to the sandbox backend. The sandbox enforces network=none,
108
+ * read-only workspace, and resource limits.
109
+ *
110
+ * Returns the same LocalTestResult shape as runLocalTest, with exit-code-based
111
+ * verdicts (0 = pass, nonzero = fail).
112
+ */
113
+ async function runTestCommand(executable, args, workspaceRoot, options) {
114
+ const backend = options?.sandboxBackend ?? (0, verificationSandbox_1.detectSandbox)();
115
+ if (!backend) {
116
+ return {
117
+ verdict: 'sandbox-unavailable',
118
+ output: exports.SANDBOX_UNAVAILABLE_MESSAGE,
119
+ exitCode: -1,
120
+ };
121
+ }
122
+ const execOpts = {
123
+ mode: 'command',
124
+ executable,
125
+ args,
126
+ workspaceRoot,
127
+ timeoutMs: options?.timeoutMs ?? DEFAULT_TIMEOUT_MS,
128
+ signal: options?.signal,
129
+ };
130
+ const result = await backend.execute(execOpts);
131
+ return {
132
+ verdict: result.verdict,
133
+ output: result.output,
134
+ exitCode: result.exitCode,
135
+ backend: result.backend,
136
+ };
130
137
  }
131
138
  //# sourceMappingURL=localTestRunner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"localTestRunner.js","sourceRoot":"","sources":["../../src/utils/localTestRunner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"localTestRunner.js","sourceRoot":"","sources":["../../src/utils/localTestRunner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Security config discovery — finds and parses security-relevant config
3
+ * files in the workspace so the agent can reason about ACTUAL config
4
+ * instead of guessing from prompt rules.
5
+ *
6
+ * Replaces the system prompt's hardcoded FP-suppression rules ("config-gated
7
+ * rate limits are not vulnerabilities") with a tool that lets the agent
8
+ * check the config and reason about what it finds.
9
+ *
10
+ * Security rules:
11
+ * - For .env files, return key NAMES and set/unset status only — never values
12
+ * - Prefer .env.example over real .env
13
+ * - All paths workspace-confined via resolveWorkspacePath
14
+ * - Output truncated to 16KB
15
+ */
16
+ export type ConfigKind = 'auth' | 'cors' | 'rate_limit' | 'headers' | 'env' | 'all';
17
+ export declare function readSecurityConfig(workspaceRoot: string, kind?: ConfigKind): Promise<string>;
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ /**
3
+ * Security config discovery — finds and parses security-relevant config
4
+ * files in the workspace so the agent can reason about ACTUAL config
5
+ * instead of guessing from prompt rules.
6
+ *
7
+ * Replaces the system prompt's hardcoded FP-suppression rules ("config-gated
8
+ * rate limits are not vulnerabilities") with a tool that lets the agent
9
+ * check the config and reason about what it finds.
10
+ *
11
+ * Security rules:
12
+ * - For .env files, return key NAMES and set/unset status only — never values
13
+ * - Prefer .env.example over real .env
14
+ * - All paths workspace-confined via resolveWorkspacePath
15
+ * - Output truncated to 16KB
16
+ */
17
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ var desc = Object.getOwnPropertyDescriptor(m, k);
20
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
21
+ desc = { enumerable: true, get: function() { return m[k]; } };
22
+ }
23
+ Object.defineProperty(o, k2, desc);
24
+ }) : (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ o[k2] = m[k];
27
+ }));
28
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
29
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
30
+ }) : function(o, v) {
31
+ o["default"] = v;
32
+ });
33
+ var __importStar = (this && this.__importStar) || (function () {
34
+ var ownKeys = function(o) {
35
+ ownKeys = Object.getOwnPropertyNames || function (o) {
36
+ var ar = [];
37
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
38
+ return ar;
39
+ };
40
+ return ownKeys(o);
41
+ };
42
+ return function (mod) {
43
+ if (mod && mod.__esModule) return mod;
44
+ var result = {};
45
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
46
+ __setModuleDefault(result, mod);
47
+ return result;
48
+ };
49
+ })();
50
+ Object.defineProperty(exports, "__esModule", { value: true });
51
+ exports.readSecurityConfig = readSecurityConfig;
52
+ const fs = __importStar(require("fs"));
53
+ const path = __importStar(require("path"));
54
+ const files_1 = require("./files");
55
+ const CONFIG_PATTERNS = [
56
+ { file: '.env.example', kind: 'env', description: 'Environment variable template (safe to show keys)' },
57
+ { file: '.env', kind: 'env', description: 'Environment variables (KEYS ONLY — values redacted)' },
58
+ { file: '.env.local', kind: 'env', description: 'Local environment overrides (KEYS ONLY)' },
59
+ { file: '.env.production', kind: 'env', description: 'Production environment (KEYS ONLY)' },
60
+ { file: 'helmet.config.js', kind: 'headers', description: 'Helmet security headers config' },
61
+ { file: 'helmet.config.ts', kind: 'headers', description: 'Helmet security headers config' },
62
+ { file: 'cors.config.js', kind: 'cors', description: 'CORS configuration' },
63
+ { file: 'cors.config.ts', kind: 'cors', description: 'CORS configuration' },
64
+ { file: 'next.config.js', kind: 'headers', description: 'Next.js config (may contain headers/CSP)' },
65
+ { file: 'next.config.ts', kind: 'headers', description: 'Next.js config (may contain headers/CSP)' },
66
+ { file: 'next.config.mjs', kind: 'headers', description: 'Next.js config (may contain headers/CSP)' },
67
+ { file: 'express-rate-limit.config.js', kind: 'rate_limit', description: 'Express rate limit config' },
68
+ { file: 'rate-limit.config.js', kind: 'rate_limit', description: 'Rate limit config' },
69
+ { file: 'rate-limit.config.ts', kind: 'rate_limit', description: 'Rate limit config' },
70
+ ];
71
+ function findConfigFiles(workspaceRoot, kind) {
72
+ const out = [];
73
+ for (const pattern of CONFIG_PATTERNS) {
74
+ if (kind !== 'all' && pattern.kind !== kind)
75
+ continue;
76
+ const candidates = [
77
+ path.join(workspaceRoot, pattern.file),
78
+ path.join(workspaceRoot, 'config', pattern.file),
79
+ path.join(workspaceRoot, 'src', pattern.file),
80
+ ];
81
+ for (const candidate of candidates) {
82
+ if (fs.existsSync(candidate)) {
83
+ const rel = path.relative(workspaceRoot, candidate).replace(/\\/g, '/');
84
+ out.push({ path: rel, kind: pattern.kind, description: pattern.description });
85
+ break;
86
+ }
87
+ }
88
+ }
89
+ return out;
90
+ }
91
+ function redactEnvValues(content) {
92
+ return content
93
+ .split('\n')
94
+ .map(line => {
95
+ const trimmed = line.trim();
96
+ if (trimmed.startsWith('#') || trimmed === '')
97
+ return line;
98
+ const eqIdx = line.indexOf('=');
99
+ if (eqIdx === -1)
100
+ return line;
101
+ const key = line.slice(0, eqIdx).trim();
102
+ const isSecret = /SECRET|KEY|TOKEN|PASSWORD|PRIVATE|CREDENTIAL/i.test(key);
103
+ if (isSecret)
104
+ return `${key}=REDACTED`;
105
+ return `${key}=set`;
106
+ })
107
+ .join('\n');
108
+ }
109
+ function parseConfigFile(filePath, workspaceRoot) {
110
+ const abs = (0, files_1.resolveWorkspacePath)(workspaceRoot, filePath);
111
+ const content = fs.readFileSync(abs, 'utf8');
112
+ const ext = path.extname(filePath).toLowerCase();
113
+ if (filePath.includes('.env')) {
114
+ return redactEnvValues(content);
115
+ }
116
+ if (ext === '.js' || ext === '.ts' || ext === '.mjs' || ext === '.json') {
117
+ return content.slice(0, 12000);
118
+ }
119
+ return content.slice(0, 12000);
120
+ }
121
+ function searchInlineConfig(workspaceRoot, kind) {
122
+ const out = [];
123
+ const patterns = [
124
+ { regex: 'helmet\\s*\\(', kind: 'headers', label: 'helmet() call' },
125
+ { regex: 'cors\\s*\\(', kind: 'cors', label: 'cors() call' },
126
+ { regex: 'rateLimit\\s*\\(', kind: 'rate_limit', label: 'rateLimit() call' },
127
+ { regex: 'rate-limit', kind: 'rate_limit', label: 'rate-limit import' },
128
+ { regex: 'express-rate-limit', kind: 'rate_limit', label: 'express-rate-limit import' },
129
+ { regex: 'Content-Security-Policy|contentSecurityPolicy|CSP', kind: 'headers', label: 'CSP header' },
130
+ { regex: 'HSTS|strict-Transport-Security', kind: 'headers', label: 'HSTS header' },
131
+ { regex: 'X-Frame-Options|xFrameOptions', kind: 'headers', label: 'X-Frame-Options' },
132
+ { regex: 'X-Content-Type-Options|xContentTypeOptions', kind: 'headers', label: 'X-Content-Type-Options' },
133
+ ];
134
+ for (const p of patterns) {
135
+ if (kind !== 'all' && p.kind !== kind)
136
+ continue;
137
+ try {
138
+ const { searchCode } = require('../utils/searchCode');
139
+ const result = searchCode(workspaceRoot, p.regex, '*.{js,ts,mjs,jsx,tsx}');
140
+ if (result && result.hits) {
141
+ for (const hit of result.hits.slice(0, 3)) {
142
+ out.push({
143
+ file: hit.path,
144
+ snippet: hit.text.slice(0, 200),
145
+ line: hit.line,
146
+ });
147
+ }
148
+ }
149
+ }
150
+ catch { /* best-effort */ }
151
+ }
152
+ return out;
153
+ }
154
+ async function readSecurityConfig(workspaceRoot, kind = 'all') {
155
+ const configFiles = findConfigFiles(workspaceRoot, kind);
156
+ const inlineConfigs = searchInlineConfig(workspaceRoot, kind);
157
+ if (configFiles.length === 0 && inlineConfigs.length === 0) {
158
+ return `No ${kind === 'all' ? '' : kind + ' '}security config files found. The project may not have explicit security config — check if it relies on framework defaults or environment variables.`;
159
+ }
160
+ const lines = [`Security config (${kind === 'all' ? 'all' : kind}):`];
161
+ if (configFiles.length > 0) {
162
+ lines.push('', 'Config files:');
163
+ for (const cf of configFiles.slice(0, 10)) {
164
+ lines.push(` ${cf.path} — ${cf.description}`);
165
+ try {
166
+ const content = parseConfigFile(cf.path, workspaceRoot);
167
+ lines.push(' ```');
168
+ for (const line of content.split('\n').slice(0, 40)) {
169
+ lines.push(` ${line}`);
170
+ }
171
+ if (content.split('\n').length > 40) {
172
+ lines.push(' ... (truncated)');
173
+ }
174
+ lines.push(' ```');
175
+ }
176
+ catch (e) {
177
+ lines.push(` (error reading: ${e.message})`);
178
+ }
179
+ }
180
+ }
181
+ if (inlineConfigs.length > 0) {
182
+ lines.push('', 'Inline config found in source:');
183
+ for (const ic of inlineConfigs.slice(0, 10)) {
184
+ lines.push(` ${ic.file}:${ic.line}`);
185
+ lines.push(` ${ic.snippet}`);
186
+ }
187
+ }
188
+ lines.push('');
189
+ lines.push('Use this evidence to determine if a security control is actually configured before reporting it as a vulnerability. A missing config file does not mean the control is absent — check inline config too.');
190
+ return lines.join('\n');
191
+ }
192
+ //# sourceMappingURL=securityConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"securityConfig.js","sourceRoot":"","sources":["../../src/utils/securityConfig.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Test command policy — strict validation for existing-test mode of run_tests.
3
+ *
4
+ * Allows only known package-manager test commands (npm/pnpm/yarn/bun test,
5
+ * pytest) with optional file/pattern arguments. Rejects shell operators,
6
+ * arbitrary executables, lifecycle commands other than test, absolute paths
7
+ * outside the workspace, and path traversal.
8
+ *
9
+ * Security rules:
10
+ * - No shell operators (&&, ||, ;, |, >, <, $(), backticks)
11
+ * - Only the `test` lifecycle command (no build/install/publish/run/exec)
12
+ * - No --shell/--script-shell escape flags
13
+ * - All file paths workspace-confined via resolveWorkspacePath
14
+ * - Output is a validated executable + args array (never a shell string)
15
+ */
16
+ export type TestPackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun' | 'pytest';
17
+ export interface ValidatedTestCommand {
18
+ packageManager: TestPackageManager;
19
+ executable: string;
20
+ args: string[];
21
+ cwd: string;
22
+ selectedFiles: string[];
23
+ timeoutMs: number;
24
+ }
25
+ export interface CommandPolicyResult {
26
+ ok: boolean;
27
+ command?: ValidatedTestCommand;
28
+ error?: string;
29
+ }
30
+ export declare function validateTestCommand(input: {
31
+ packageManager?: string;
32
+ testFiles?: string[];
33
+ testPattern?: string;
34
+ timeoutMs?: number;
35
+ }, workspaceRoot: string): CommandPolicyResult;
36
+ export declare function formatValidatedCommand(cmd: ValidatedTestCommand): string;