@securecode-ai/mcp 0.5.4 → 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 (188) 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 +329 -15
  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 -101
  169. package/dist/utils/localTestRunner.js.map +1 -1
  170. package/dist/utils/runtimeDetect.d.ts +12 -2
  171. package/dist/utils/runtimeDetect.js +247 -10
  172. package/dist/utils/runtimeDetect.js.map +1 -1
  173. package/dist/utils/securityConfig.d.ts +17 -0
  174. package/dist/utils/securityConfig.js +192 -0
  175. package/dist/utils/securityConfig.js.map +1 -0
  176. package/dist/utils/testCommandPolicy.d.ts +36 -0
  177. package/dist/utils/testCommandPolicy.js +252 -0
  178. package/dist/utils/testCommandPolicy.js.map +1 -0
  179. package/dist/utils/testRunner.d.ts +56 -0
  180. package/dist/utils/testRunner.js +246 -0
  181. package/dist/utils/testRunner.js.map +1 -0
  182. package/dist/utils/testSafety.d.ts +40 -2
  183. package/dist/utils/testSafety.js +205 -26
  184. package/dist/utils/testSafety.js.map +1 -1
  185. package/dist/utils/verificationSandbox.d.ts +113 -0
  186. package/dist/utils/verificationSandbox.js +656 -0
  187. package/dist/utils/verificationSandbox.js.map +1 -0
  188. package/package.json +1 -1
@@ -1,117 +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 ext = (runner === 'tsx' || runner === 'ts' || runner === 'bun') ? '.test.ts' : '.test.js';
53
- const testFile = path.join(testDir, `verify-test-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${ext}`);
54
- try {
55
- fs.writeFileSync(testFile, script, 'utf8');
56
- let stdout = '';
57
- let stderr = '';
58
- let exitCode = 0;
59
- let timedOut = false;
60
- try {
61
- const isWindows = process.platform === 'win32';
62
- let runnerBin;
63
- let runnerArgs;
64
- if (runner === 'tsx') {
65
- runnerBin = 'npx';
66
- runnerArgs = ['tsx', testFile];
67
- }
68
- else if (runner === 'bun' && isWindows) {
69
- runnerBin = 'npx';
70
- runnerArgs = ['bun', testFile];
71
- }
72
- else {
73
- runnerBin = runner;
74
- runnerArgs = [testFile];
75
- }
76
- stdout = (0, child_process_1.execFileSync)(runnerBin, runnerArgs, {
77
- cwd: workspaceRoot,
78
- timeout: TIMEOUT_MS,
79
- encoding: 'utf8',
80
- stdio: ['pipe', 'pipe', 'pipe'],
81
- env: { ...process.env, NODE_ENV: 'test' },
82
- shell: isWindows,
83
- });
84
- }
85
- catch (err) {
86
- stdout = err.stdout || '';
87
- stderr = err.stderr || '';
88
- exitCode = err.status ?? 1;
89
- if (err.signal === 'SIGTERM')
90
- timedOut = true;
91
- }
92
- const output = (stdout + '\n' + stderr).trim();
93
- if (timedOut) {
94
- return { verdict: 'timeout', output: 'Test timed out after 30s', exitCode: -1 };
95
- }
96
- if (PASS_PATTERN.test(output)) {
97
- return { verdict: 'pass', output, exitCode };
98
- }
99
- if (FAIL_PATTERN.test(output)) {
100
- return { verdict: 'fail', output, exitCode };
101
- }
102
- if (exitCode === 0) {
103
- 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 };
104
58
  }
105
- return { verdict: 'error', output, exitCode };
106
59
  }
107
- catch (err) {
108
- 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
+ };
109
68
  }
110
- 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') {
111
72
  try {
112
- fs.unlinkSync(testFile);
73
+ (0, effectMock_1.createEffectMock)(workspaceRoot);
113
74
  }
114
75
  catch { }
115
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
+ };
116
137
  }
117
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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"}
@@ -1,8 +1,18 @@
1
- export type ProjectRuntime = 'bun' | 'node' | 'deno';
1
+ export type ProjectRuntime = 'bun' | 'node' | 'deno' | 'python';
2
+ export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun' | 'pip' | 'poetry' | 'uv' | null;
3
+ export type Framework = 'electron' | 'next' | 'remix' | 'nuxt' | 'react-native' | 'express' | 'fastify' | 'nestjs' | 'koa' | 'hapi' | 'flask' | 'fastapi' | 'django' | 'react' | 'vue' | 'svelte' | 'cloudflare-workers' | null;
4
+ export type TestabilityTier = 1 | 2 | 3 | 4;
2
5
  export interface RuntimeInfo {
3
6
  runtime: ProjectRuntime;
4
7
  runner: string;
8
+ packageManager: PackageManager;
9
+ framework: Framework;
10
+ frameworkVersion: string | null;
11
+ testabilityTier: TestabilityTier;
12
+ canRunLocally: boolean;
13
+ skipReason?: string;
5
14
  hasBunLock: boolean;
15
+ depsInstalled: boolean;
6
16
  }
7
- export declare function detectRuntime(workspaceRoot: string): RuntimeInfo;
17
+ export declare function detectRuntime(workspaceRoot: string, filePath?: string): RuntimeInfo;
8
18
  export declare function computeRelativeImportPath(testFileDir: string, targetFilePath: string): string;
@@ -37,22 +37,259 @@ exports.detectRuntime = detectRuntime;
37
37
  exports.computeRelativeImportPath = computeRelativeImportPath;
38
38
  const fs = __importStar(require("fs"));
39
39
  const path = __importStar(require("path"));
40
- function detectRuntime(workspaceRoot) {
41
- const hasBunLock = fs.existsSync(path.join(workspaceRoot, 'bun.lockb')) ||
42
- fs.existsSync(path.join(workspaceRoot, 'bun.lock')) ||
43
- fs.existsSync(path.join(workspaceRoot, 'bunfig.toml'));
44
- if (hasBunLock) {
45
- return { runtime: 'bun', runner: 'bun', hasBunLock: true };
40
+ const child_process_1 = require("child_process");
41
+ const JS_FRAMEWORK_RULES = [
42
+ { dep: 'react-native', framework: 'react-native', tier: 4 },
43
+ { dep: '@cloudflare/workers-types', framework: 'cloudflare-workers', tier: 4 },
44
+ { dep: 'wrangler', framework: 'cloudflare-workers', tier: 4 },
45
+ { dep: 'electron', framework: 'electron', tier: 2 },
46
+ { dep: 'next', framework: 'next', tier: 2 },
47
+ { dep: '@remix-run/node', framework: 'remix', tier: 2 },
48
+ { dep: 'remix', framework: 'remix', tier: 2 },
49
+ { dep: 'nuxt', framework: 'nuxt', tier: 2 },
50
+ { dep: '@nestjs/core', framework: 'nestjs', tier: 1 },
51
+ { dep: 'fastify', framework: 'fastify', tier: 1 },
52
+ { dep: 'express', framework: 'express', tier: 1 },
53
+ { dep: 'koa', framework: 'koa', tier: 1 },
54
+ { dep: '@hapi/hapi', framework: 'hapi', tier: 1 },
55
+ { dep: 'svelte', framework: 'svelte', tier: 3 },
56
+ { dep: 'vue', framework: 'vue', tier: 3 },
57
+ { dep: 'react', framework: 'react', tier: 3 },
58
+ ];
59
+ const PY_FRAMEWORK_RULES = [
60
+ { dep: 'fastapi', framework: 'fastapi', tier: 1 },
61
+ { dep: 'flask', framework: 'flask', tier: 1 },
62
+ { dep: 'django', framework: 'django', tier: 1 },
63
+ ];
64
+ const TIER_SKIP_REASONS = {
65
+ 4: 'Framework requires a runtime that cannot be invoked locally (Metro/worker runtime). Set canTest: false.',
66
+ };
67
+ const probeCache = new Map();
68
+ function probe(bin) {
69
+ if (probeCache.has(bin))
70
+ return probeCache.get(bin);
71
+ let ok = false;
72
+ try {
73
+ const r = (0, child_process_1.spawnSync)(bin, ['--version'], {
74
+ stdio: 'ignore',
75
+ shell: process.platform === 'win32',
76
+ timeout: 4000,
77
+ });
78
+ ok = r.status === 0;
46
79
  }
47
- if (fs.existsSync(path.join(workspaceRoot, 'deno.json')) ||
48
- fs.existsSync(path.join(workspaceRoot, 'deno.jsonc'))) {
49
- return { runtime: 'deno', runner: 'deno', hasBunLock: false };
80
+ catch {
81
+ ok = false;
50
82
  }
51
- return { runtime: 'node', runner: 'tsx', hasBunLock: false };
83
+ probeCache.set(bin, ok);
84
+ return ok;
85
+ }
86
+ function readJson(file) {
87
+ try {
88
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
89
+ }
90
+ catch {
91
+ return null;
92
+ }
93
+ }
94
+ function exists(...files) {
95
+ return files.some(f => fs.existsSync(f));
96
+ }
97
+ function findNearest(startDir, root, candidates) {
98
+ let dir = startDir;
99
+ const rootAbs = path.resolve(root);
100
+ while (true) {
101
+ for (const c of candidates) {
102
+ const p = path.join(dir, c);
103
+ if (fs.existsSync(p))
104
+ return { dir, file: p };
105
+ }
106
+ const parent = path.dirname(dir);
107
+ if (parent === dir || !dir.startsWith(rootAbs))
108
+ break;
109
+ dir = parent;
110
+ }
111
+ return null;
112
+ }
113
+ function detectJsFramework(pkg) {
114
+ if (!pkg)
115
+ return { framework: null, version: null, tier: 1 };
116
+ const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
117
+ for (const rule of JS_FRAMEWORK_RULES) {
118
+ if (deps[rule.dep]) {
119
+ return { framework: rule.framework, version: deps[rule.dep] || null, tier: rule.tier };
120
+ }
121
+ }
122
+ return { framework: null, version: null, tier: 1 };
123
+ }
124
+ function detectPyFramework(startDir, root) {
125
+ const reqs = findNearest(startDir, root, ['requirements.txt', 'pyproject.toml', 'setup.py', 'Pipfile']);
126
+ if (!reqs)
127
+ return { framework: null, version: null, tier: 1 };
128
+ let text = '';
129
+ try {
130
+ text = fs.readFileSync(reqs.file, 'utf8');
131
+ }
132
+ catch {
133
+ return { framework: null, version: null, tier: 1 };
134
+ }
135
+ const lower = text.toLowerCase();
136
+ for (const rule of PY_FRAMEWORK_RULES) {
137
+ const re = new RegExp(`^\\s*${rule.dep}(\\s*[=><~!]|\\s*$)`, 'im');
138
+ if (re.test(lower)) {
139
+ const verMatch = lower.match(new RegExp(`${rule.dep}\\s*[=><~!]*\\s*([0-9][0-9a-zA-Z.\\-]*)`, 'im'));
140
+ return { framework: rule.framework, version: verMatch ? verMatch[1] : null, tier: rule.tier };
141
+ }
142
+ }
143
+ return { framework: null, version: null, tier: 1 };
144
+ }
145
+ function resolveJsRunner(runtime, pkgManager) {
146
+ if (runtime === 'bun')
147
+ return probe('bun') ? 'bun' : 'tsx';
148
+ if (runtime === 'deno')
149
+ return probe('deno') ? 'deno' : 'tsx';
150
+ if (pkgManager === 'pnpm' && probe('pnpm'))
151
+ return 'pnpm-tsx';
152
+ if (pkgManager === 'yarn' && probe('yarn'))
153
+ return 'yarn-tsx';
154
+ return 'tsx';
155
+ }
156
+ function resolvePythonRunner() {
157
+ if (probe('python3'))
158
+ return { runner: 'python3', installed: true };
159
+ if (probe('python'))
160
+ return { runner: 'python', installed: true };
161
+ return { runner: 'python3', installed: false };
162
+ }
163
+ function detectPackageManager(pkg, nearest) {
164
+ if (pkg?.packageManager) {
165
+ const pm = String(pkg.packageManager).toLowerCase();
166
+ if (pm.startsWith('bun'))
167
+ return 'bun';
168
+ if (pm.startsWith('pnpm'))
169
+ return 'pnpm';
170
+ if (pm.startsWith('yarn'))
171
+ return 'yarn';
172
+ if (pm.startsWith('npm'))
173
+ return 'npm';
174
+ }
175
+ if (nearest) {
176
+ const dir = nearest.dir;
177
+ if (exists(path.join(dir, 'bun.lockb'), path.join(dir, 'bun.lock')))
178
+ return 'bun';
179
+ if (exists(path.join(dir, 'pnpm-lock.yaml')))
180
+ return 'pnpm';
181
+ if (exists(path.join(dir, 'yarn.lock')))
182
+ return 'yarn';
183
+ if (exists(path.join(dir, 'package-lock.json')))
184
+ return 'npm';
185
+ }
186
+ return 'npm';
187
+ }
188
+ function detectRuntime(workspaceRoot, filePath) {
189
+ const rootAbs = path.resolve(workspaceRoot);
190
+ const isPythonFile = filePath ? /\.p(yi?|yx)$/i.test(filePath) : false;
191
+ if (isPythonFile) {
192
+ const startDir = filePath
193
+ ? path.resolve(rootAbs, path.dirname(filePath))
194
+ : rootAbs;
195
+ const py = resolvePythonRunner();
196
+ const { framework, version, tier } = detectPyFramework(startDir, rootAbs);
197
+ const pkgMan = (() => {
198
+ if (exists(path.join(startDir, 'poetry.lock')))
199
+ return 'poetry';
200
+ if (exists(path.join(startDir, 'uv.lock')))
201
+ return 'uv';
202
+ if (exists(path.join(startDir, 'Pipfile')))
203
+ return 'pip';
204
+ if (exists(path.join(startDir, 'requirements.txt'), path.join(startDir, 'pyproject.toml')))
205
+ return 'pip';
206
+ return null;
207
+ })();
208
+ const canRun = py.installed && tier !== 4;
209
+ return {
210
+ runtime: 'python',
211
+ runner: py.runner,
212
+ packageManager: pkgMan,
213
+ framework,
214
+ frameworkVersion: version,
215
+ testabilityTier: tier,
216
+ canRunLocally: canRun,
217
+ skipReason: !py.installed
218
+ ? 'Python interpreter not found in PATH. Install python3 to run local exploit tests.'
219
+ : tier === 4 ? TIER_SKIP_REASONS[4] : undefined,
220
+ hasBunLock: false,
221
+ depsInstalled: exists(path.join(startDir, '__pycache__')) || exists(path.join(startDir, '.venv'), path.join(startDir, 'venv')),
222
+ };
223
+ }
224
+ const startDir = filePath
225
+ ? path.resolve(rootAbs, path.dirname(filePath))
226
+ : rootAbs;
227
+ const nearestPkg = findNearest(startDir, rootAbs, ['package.json']);
228
+ const pkg = nearestPkg ? readJson(nearestPkg.file) : null;
229
+ const hasBunLock = exists(path.join(rootAbs, 'bun.lockb'), path.join(rootAbs, 'bun.lock'), path.join(rootAbs, 'bunfig.toml'));
230
+ let runtime = 'node';
231
+ const nearestLock = findNearest(startDir, rootAbs, [
232
+ 'bun.lockb', 'bun.lock', 'bunfig.toml',
233
+ 'deno.json', 'deno.jsonc',
234
+ 'package-lock.json', 'pnpm-lock.yaml', 'yarn.lock',
235
+ ]);
236
+ if (pkg?.packageManager && String(pkg.packageManager).toLowerCase().startsWith('bun')) {
237
+ runtime = 'bun';
238
+ }
239
+ else if (pkg?.engines?.bun) {
240
+ runtime = 'bun';
241
+ }
242
+ else if (hasBunLock) {
243
+ runtime = 'bun';
244
+ }
245
+ else if (pkg?.packageManager && String(pkg.packageManager).toLowerCase().startsWith('deno')) {
246
+ runtime = 'deno';
247
+ }
248
+ else if (exists(path.join(rootAbs, 'deno.json'), path.join(rootAbs, 'deno.jsonc'))) {
249
+ runtime = 'deno';
250
+ }
251
+ else if (nearestLock?.file.endsWith('deno.json') || nearestLock?.file.endsWith('deno.jsonc')) {
252
+ runtime = 'deno';
253
+ }
254
+ else {
255
+ runtime = 'node';
256
+ }
257
+ const packageManager = detectPackageManager(pkg, nearestLock);
258
+ const { framework, version, tier } = detectJsFramework(pkg);
259
+ const runner = resolveJsRunner(runtime, packageManager);
260
+ const canRun = tier !== 4;
261
+ const depsInstalled = (() => {
262
+ const searchDirs = [startDir, rootAbs];
263
+ for (const d of searchDirs) {
264
+ if (exists(path.join(d, 'node_modules')))
265
+ return true;
266
+ }
267
+ if (nearestPkg) {
268
+ if (exists(path.join(nearestPkg.dir, 'node_modules')))
269
+ return true;
270
+ }
271
+ return false;
272
+ })();
273
+ return {
274
+ runtime,
275
+ runner,
276
+ packageManager,
277
+ framework,
278
+ frameworkVersion: version,
279
+ testabilityTier: tier,
280
+ canRunLocally: canRun,
281
+ skipReason: tier === 4 ? TIER_SKIP_REASONS[4] : undefined,
282
+ hasBunLock,
283
+ depsInstalled,
284
+ };
52
285
  }
53
286
  function computeRelativeImportPath(testFileDir, targetFilePath) {
54
287
  const rel = path.relative(testFileDir, targetFilePath);
55
288
  const normalized = rel.replace(/\\/g, '/');
289
+ if (/\.p(yi?|yx)$/i.test(targetFilePath)) {
290
+ const fromRoot = path.relative(path.dirname(testFileDir), targetFilePath).replace(/\\/g, '/');
291
+ return fromRoot.startsWith('.') ? fromRoot : `./${fromRoot}`;
292
+ }
56
293
  const withoutExt = normalized.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/, '');
57
294
  return withoutExt.startsWith('.') ? withoutExt : `./${withoutExt}`;
58
295
  }
@@ -1 +1 @@
1
- {"version":3,"file":"runtimeDetect.js","sourceRoot":"","sources":["../../src/utils/runtimeDetect.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,sCAeC;AAED,8DAKC;AAjCD,uCAAyB;AACzB,2CAA6B;AAU7B,SAAgB,aAAa,CAAC,aAAqB;IAC/C,MAAM,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;QACnE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;QACnD,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC;IAE3D,IAAI,UAAU,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;IAC/D,CAAC;IAED,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;QACpD,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC;QACxD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;IAClE,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AACjE,CAAC;AAED,SAAgB,yBAAyB,CAAC,WAAmB,EAAE,cAAsB;IACjF,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC;IACxE,OAAO,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;AACvE,CAAC"}
1
+ {"version":3,"file":"runtimeDetect.js","sourceRoot":"","sources":["../../src/utils/runtimeDetect.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>;