@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
@@ -0,0 +1,162 @@
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
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createEffectMock = createEffectMock;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const EFFECT_MOCK_JS = `const E = {
40
+ sync: (fn) => ({ _tag: "Sync", fn }),
41
+ die: (msg) => { throw new Error(typeof msg === "string" ? msg : JSON.stringify(msg)); },
42
+ gen: (generatorFn) => ({
43
+ _tag: "Gen",
44
+ run() {
45
+ const gen = generatorFn();
46
+ let result = gen.next();
47
+ while (!result.done) {
48
+ const y = result.value;
49
+ if (y && y._tag === "Sync") result = gen.next(y.fn());
50
+ else if (y && y._tag === "Die") throw new Error(y.msg);
51
+ else if (y && y._tag === "Succeed") result = gen.next(y.v);
52
+ else if (y && y._tag === "Fail") throw y.e;
53
+ else result = gen.next(y);
54
+ }
55
+ return result.value;
56
+ }
57
+ }),
58
+ succeed: (v) => ({ _tag: "Succeed", v }),
59
+ fail: (e) => ({ _tag: "Fail", e }),
60
+ runSync: (e) => e && e._tag === "Gen" ? e.run() : e && e._tag === "Sync" ? e.fn() : e,
61
+ runPromise: async (e) => e && e._tag === "Gen" ? e.run() : e && e._tag === "Sync" ? e.fn() : e,
62
+ map: (e, fn) => e && e._tag === "Sync" ? { _tag: "Sync", fn: () => fn(e.fn()) } : e,
63
+ flatMap: (e, fn) => e && e._tag === "Sync" ? { _tag: "Sync", fn: () => { const r = e.fn(); return fn(r); } } : e,
64
+ catchAll: (e, fn) => e,
65
+ try_: (fn) => ({ _tag: "Sync", fn: () => { try { return fn(); } catch (e) { return e; } } }),
66
+ };
67
+ export const Effect = E;
68
+ export const Layer = {
69
+ effect: (tag, genEffect) => {
70
+ const result = genEffect && genEffect._tag === "Gen" ? genEffect.run() : genEffect;
71
+ return { _tag: "Layer", tag, gen: genEffect, ...result };
72
+ },
73
+ succeed: (val) => ({ _tag: "Layer", val }),
74
+ fail: (e) => ({ _tag: "Layer", e }),
75
+ empty: { _tag: "Layer" },
76
+ build: (layer) => layer,
77
+ toRuntime: (layer) => layer,
78
+ provide: (effect, layer) => effect,
79
+ };
80
+ export const Context = {
81
+ Tag: (id) => class { static _tag = id; },
82
+ make: (tag, val) => ({ [tag]: val }),
83
+ get: (tag) => ({ _tag: "Sync", fn: () => tag }),
84
+ };
85
+ export const Schema = {
86
+ TaggedErrorClass: () => () => class extends Error {
87
+ constructor(props) { super(props?.message || ""); Object.assign(this, props); }
88
+ },
89
+ String: { _tag: "String" },
90
+ Number: { _tag: "Number" },
91
+ Boolean: { _tag: "Boolean" },
92
+ optional: (s) => s,
93
+ Defect: { _tag: "Defect" },
94
+ Struct: (fields) => ({ _tag: "Struct", fields }),
95
+ Array: (item) => ({ _tag: "Array", item }),
96
+ decodeUnknownSync: (schema) => (val) => val,
97
+ encodeSync: (schema) => (val) => val,
98
+ };
99
+ export const ServiceMap = {
100
+ Service: () => () => class {
101
+ static _tag = "mock-service";
102
+ static key = "mock-service";
103
+ },
104
+ };
105
+ export const pipe = (val, ...fns) => fns.reduce((v, fn) => fn(v), val);
106
+ export const Option = {
107
+ some: (v) => ({ _tag: "Some", value: v }),
108
+ none: { _tag: "None" },
109
+ isSome: (o) => o && o._tag === "Some",
110
+ isNone: (o) => !o || o._tag === "None",
111
+ getOrElse: (o, fn) => o && o._tag === "Some" ? o.value : fn(),
112
+ map: (o, fn) => o && o._tag === "Some" ? { _tag: "Some", value: fn(o.value) } : o,
113
+ };
114
+ export const Either = {
115
+ left: (e) => ({ _tag: "Left", left: e }),
116
+ right: (v) => ({ _tag: "Right", right: v }),
117
+ isRight: (e) => e && e._tag === "Right",
118
+ isLeft: (e) => e && e._tag === "Left",
119
+ getOrElse: (e, fn) => e && e._tag === "Right" ? e.right : fn(),
120
+ map: (e, fn) => e && e._tag === "Right" ? { _tag: "Right", right: fn(e.right) } : e,
121
+ };
122
+ export const Cause = {
123
+ die: (msg) => ({ _tag: "Die", msg }),
124
+ fail: (e) => ({ _tag: "Fail", e }),
125
+ toString: (c) => JSON.stringify(c),
126
+ };
127
+ export const Stream = {
128
+ fromIterable: (items) => ({ _tag: "Stream", items }),
129
+ run: (stream) => stream,
130
+ };
131
+ export const SubscriptionRef = {
132
+ make: (val) => ({ _tag: "SubscriptionRef", ref: { value: val } }),
133
+ get: (sr) => ({ _tag: "Sync", fn: () => sr.ref.value }),
134
+ set: (sr, val) => ({ _tag: "Sync", fn: () => { sr.ref.value = val; } }),
135
+ };
136
+ export const Ref = {
137
+ make: (val) => ({ value: val }),
138
+ get: (r) => ({ _tag: "Sync", fn: () => r.value }),
139
+ set: (r, val) => ({ _tag: "Sync", fn: () => { r.value = val; } }),
140
+ update: (r, fn) => ({ _tag: "Sync", fn: () => { r.value = fn(r.value); } }),
141
+ };
142
+ export const Fiber = {
143
+ run: (effect) => ({ _tag: "Fiber", effect }),
144
+ join: (fiber) => fiber.effect,
145
+ };
146
+ export const Runtime = {
147
+ defaultRuntime: { runSync: E.runSync, runPromise: E.runPromise },
148
+ };
149
+ `;
150
+ const EFFECT_PKG_JSON = JSON.stringify({
151
+ name: "effect",
152
+ version: "0.0.0-mock",
153
+ main: "index.js",
154
+ type: "module",
155
+ });
156
+ function createEffectMock(workspaceRoot) {
157
+ const mockDir = path.join(workspaceRoot, 'node_modules', 'effect');
158
+ fs.mkdirSync(mockDir, { recursive: true });
159
+ fs.writeFileSync(path.join(mockDir, 'package.json'), EFFECT_PKG_JSON, 'utf8');
160
+ fs.writeFileSync(path.join(mockDir, 'index.js'), EFFECT_MOCK_JS, 'utf8');
161
+ }
162
+ //# sourceMappingURL=effectMock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effectMock.js","sourceRoot":"","sources":["../../src/utils/effectMock.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0HA,4CAKC;AA/HD,uCAAyB;AACzB,2CAA6B;AAE7B,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8GtB,CAAC;AAEF,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC;IACnC,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,YAAY;IACrB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,QAAQ;CACjB,CAAC,CAAC;AAEH,SAAgB,gBAAgB,CAAC,aAAqB;IAClD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,cAAc,EAAE,QAAQ,CAAC,CAAC;IACnE,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;IAC9E,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;AAC7E,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Git context — safe, read-only git blame and history extraction for the
3
+ * agent scan's git_blame and git_history tools.
4
+ *
5
+ * Security rules (enforced here, not by the caller):
6
+ * - execFile only, no shell
7
+ * - argument arrays, never string concatenation
8
+ * - `--` before every file path (prevents option injection)
9
+ * - workspace confinement via resolveWorkspacePath
10
+ * - 20 commits maximum (hard cap)
11
+ * - output truncated to 8KB and redacted (emails, secrets)
12
+ * - non-git workspaces return a clear "not a git repo" message
13
+ *
14
+ * The agent is told that history is CONTEXT, never proof that code is safe.
15
+ */
16
+ export declare function getGitBlame(workspaceRoot: string, filePath: string, startLine?: number, endLine?: number): Promise<string>;
17
+ export declare function getGitHistory(workspaceRoot: string, filePath?: string, functionName?: string, limit?: number): Promise<string>;
18
+ export interface GitChangedFilesResult {
19
+ ok: boolean;
20
+ files: string[];
21
+ baseRef: string;
22
+ headRef: string;
23
+ error?: string;
24
+ }
25
+ export declare function getGitChangedFiles(workspaceRoot: string, baseRef: string, headRef?: string): Promise<GitChangedFilesResult>;
26
+ export declare function formatGitChangedFiles(workspaceRoot: string, baseRef: string, headRef?: string): Promise<string>;
@@ -0,0 +1,317 @@
1
+ "use strict";
2
+ /**
3
+ * Git context — safe, read-only git blame and history extraction for the
4
+ * agent scan's git_blame and git_history tools.
5
+ *
6
+ * Security rules (enforced here, not by the caller):
7
+ * - execFile only, no shell
8
+ * - argument arrays, never string concatenation
9
+ * - `--` before every file path (prevents option injection)
10
+ * - workspace confinement via resolveWorkspacePath
11
+ * - 20 commits maximum (hard cap)
12
+ * - output truncated to 8KB and redacted (emails, secrets)
13
+ * - non-git workspaces return a clear "not a git repo" message
14
+ *
15
+ * The agent is told that history is CONTEXT, never proof that code is safe.
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.getGitBlame = getGitBlame;
52
+ exports.getGitHistory = getGitHistory;
53
+ exports.getGitChangedFiles = getGitChangedFiles;
54
+ exports.formatGitChangedFiles = formatGitChangedFiles;
55
+ const path = __importStar(require("path"));
56
+ const child_process_1 = require("child_process");
57
+ const files_1 = require("./files");
58
+ const MAX_COMMITS = 20;
59
+ const MAX_OUTPUT_BYTES = 8192;
60
+ const GIT_TIMEOUT_MS = 10_000;
61
+ function execGit(args, workspaceRoot) {
62
+ return new Promise((resolve) => {
63
+ (0, child_process_1.execFile)('git', args, {
64
+ cwd: workspaceRoot,
65
+ timeout: GIT_TIMEOUT_MS,
66
+ maxBuffer: MAX_OUTPUT_BYTES,
67
+ encoding: 'utf8',
68
+ windowsHide: true,
69
+ }, (err, stdout, stderr) => {
70
+ if (err) {
71
+ resolve({ ok: false, output: '', error: err.message || String(err) });
72
+ return;
73
+ }
74
+ resolve({ ok: true, output: stdout || stderr });
75
+ });
76
+ });
77
+ }
78
+ function isGitRepo(workspaceRoot) {
79
+ return new Promise((resolve) => {
80
+ (0, child_process_1.execFile)('git', ['rev-parse', '--is-inside-work-tree'], {
81
+ cwd: workspaceRoot,
82
+ timeout: 3000,
83
+ windowsHide: true,
84
+ }, (err, stdout) => {
85
+ resolve(!err && stdout.trim() === 'true');
86
+ });
87
+ });
88
+ }
89
+ /** Redact email addresses and obvious secret patterns from git output. */
90
+ function redactGitOutput(text) {
91
+ return text
92
+ .replace(/<[^>]+@[^>]+>/g, '<redacted>') // author emails <foo@bar.com>
93
+ .replace(/\b[\w.+-]+@[\w-]+\.[\w.-]+\b/g, 'redacted@email') // bare emails
94
+ .replace(/(sk-[\w]{20,})/gi, 'sk-REDACTED') // OpenAI keys
95
+ .replace(/(AKIA[\w]{16})/g, 'AKIA-REDACTED') // AWS keys
96
+ .replace(/(ghp_[\w]{36})/g, 'ghp-REDACTED') // GitHub PATs
97
+ .replace(/(xox[baprs]-[\w-]+)/g, 'xox-REDACTED'); // Slack tokens
98
+ }
99
+ function truncate(text, max = MAX_OUTPUT_BYTES) {
100
+ if (text.length <= max)
101
+ return text;
102
+ return text.slice(0, max) + '\n… [truncated]';
103
+ }
104
+ async function getGitBlame(workspaceRoot, filePath, startLine, endLine) {
105
+ const isGit = await isGitRepo(workspaceRoot);
106
+ if (!isGit) {
107
+ return `Not a git repository — git_blame unavailable.`;
108
+ }
109
+ let absPath;
110
+ try {
111
+ absPath = (0, files_1.resolveWorkspacePath)(workspaceRoot, filePath);
112
+ }
113
+ catch (e) {
114
+ return `Error: ${e.message}`;
115
+ }
116
+ const relPath = path.relative(workspaceRoot, absPath).replace(/\\/g, '/');
117
+ const range = startLine && endLine ? `-L ${startLine},${endLine}` : null;
118
+ const args = ['blame', '--porcelain', '--'];
119
+ if (range)
120
+ args.splice(1, 0, ...range.split(' '));
121
+ args.push(relPath);
122
+ const result = await execGit(args, workspaceRoot);
123
+ if (!result.ok) {
124
+ return `git blame failed: ${result.error || 'unknown error'}. The file may not be tracked by git.`;
125
+ }
126
+ const lines = result.output.split('\n');
127
+ const blameEntries = [];
128
+ let current = null;
129
+ for (const line of lines) {
130
+ if (line.startsWith('\t')) {
131
+ if (current) {
132
+ current.line = line.slice(1);
133
+ blameEntries.push(current);
134
+ current = null;
135
+ }
136
+ continue;
137
+ }
138
+ const match = line.match(/^([0-9a-f]{8,40}) (\d+)\s/);
139
+ if (match && !current) {
140
+ current = { hash: match[1].slice(0, 8), author: '', date: '', summary: '', line: '' };
141
+ }
142
+ if (line.startsWith('author ') && current)
143
+ current.author = redactGitOutput(line.slice(7));
144
+ if (line.startsWith('author-mail ') && current)
145
+ current.author = `${current.author} ${redactGitOutput(line.slice(12))}`;
146
+ if (line.startsWith('committer-time ') && current) {
147
+ const ts = parseInt(line.slice(15), 10);
148
+ if (!isNaN(ts))
149
+ current.date = new Date(ts * 1000).toISOString().slice(0, 10);
150
+ }
151
+ if (line.startsWith('summary ') && current)
152
+ current.summary = redactGitOutput(line.slice(8));
153
+ }
154
+ if (blameEntries.length === 0) {
155
+ return `No blame data for ${relPath}.`;
156
+ }
157
+ const out = [`Git blame for ${relPath} (${blameEntries.length} line(s)):`];
158
+ for (const e of blameEntries.slice(0, 20)) {
159
+ out.push(` ${e.hash} ${e.date} ${e.author}`);
160
+ out.push(` ${e.summary}`);
161
+ out.push(` L: ${e.line}`);
162
+ }
163
+ return truncate(out.join('\n'));
164
+ }
165
+ async function getGitHistory(workspaceRoot, filePath, functionName, limit = 10) {
166
+ const isGit = await isGitRepo(workspaceRoot);
167
+ if (!isGit) {
168
+ return `Not a git repository — git_history unavailable.`;
169
+ }
170
+ const maxLimit = Math.min(limit, MAX_COMMITS);
171
+ const args = ['log', `--max-count=${maxLimit}`, '--format=%h|%ad|%an|%s', '--date=short'];
172
+ if (filePath) {
173
+ let absPath;
174
+ try {
175
+ absPath = (0, files_1.resolveWorkspacePath)(workspaceRoot, filePath);
176
+ }
177
+ catch (e) {
178
+ return `Error: ${e.message}`;
179
+ }
180
+ const relPath = path.relative(workspaceRoot, absPath).replace(/\\/g, '/');
181
+ args.push('--', relPath);
182
+ }
183
+ else {
184
+ args.push('--');
185
+ }
186
+ if (functionName) {
187
+ args.splice(2, 0, `-S${functionName}`);
188
+ }
189
+ const result = await execGit(args, workspaceRoot);
190
+ if (!result.ok) {
191
+ return `git log failed: ${result.error || 'unknown error'}.`;
192
+ }
193
+ const lines = result.output.trim().split('\n').filter(Boolean);
194
+ if (lines.length === 0) {
195
+ return filePath
196
+ ? `No commit history for ${filePath}.`
197
+ : `No commit history found.`;
198
+ }
199
+ const out = [`Git history (${lines.length} commit(s))${filePath ? ` for ${filePath}` : ''}:`];
200
+ for (const line of lines) {
201
+ const parts = line.split('|');
202
+ if (parts.length >= 4) {
203
+ const [hash, date, author, summary] = parts;
204
+ out.push(` ${hash} ${date} ${redactGitOutput(author)}`);
205
+ out.push(` ${redactGitOutput(summary)}`);
206
+ }
207
+ }
208
+ return truncate(out.join('\n'));
209
+ }
210
+ // ── Git diff (changed files) ────────────────────────────────────────────────
211
+ //
212
+ // Returns the list of files changed between a base ref and HEAD (or between
213
+ // two refs). Used by the agent scan's diff-aware blast radius scoping: only
214
+ // files that changed (and their blast radius) need to be scanned.
215
+ //
216
+ // Security:
217
+ // - baseRef/headRef validated against a strict regex (no shell injection)
218
+ // - execFile only, no shell
219
+ // - argument arrays, `--` separator not needed for refs (git treats them
220
+ // as positional args to `diff --name-only`)
221
+ // - output truncated, redacted, 10s timeout
222
+ // - non-git workspaces return a clear message
223
+ const REF_PATTERN = /^[a-zA-Z0-9._~^/-]{1,100}$/;
224
+ const MAX_CHANGED_FILES = 500;
225
+ function validateRef(ref) {
226
+ if (!ref || ref.length === 0)
227
+ return null;
228
+ if (!REF_PATTERN.test(ref))
229
+ return null;
230
+ if (ref.includes('..'))
231
+ return null; // reject range operators
232
+ return ref;
233
+ }
234
+ async function getGitChangedFiles(workspaceRoot, baseRef, headRef) {
235
+ const isGit = await isGitRepo(workspaceRoot);
236
+ if (!isGit) {
237
+ return {
238
+ ok: false,
239
+ files: [],
240
+ baseRef,
241
+ headRef: headRef || 'HEAD',
242
+ error: 'Not a git repository — git_diff unavailable.',
243
+ };
244
+ }
245
+ const base = validateRef(baseRef);
246
+ if (!base) {
247
+ return {
248
+ ok: false,
249
+ files: [],
250
+ baseRef,
251
+ headRef: headRef || 'HEAD',
252
+ error: `Invalid base ref: "${baseRef}". Refs must match /^[a-zA-Z0-9._\\/-]{1,100}$/ and not contain "..".`,
253
+ };
254
+ }
255
+ const head = headRef ? validateRef(headRef) : 'HEAD';
256
+ if (headRef && !head) {
257
+ return {
258
+ ok: false,
259
+ files: [],
260
+ baseRef: base,
261
+ headRef: headRef,
262
+ error: `Invalid head ref: "${headRef}".`,
263
+ };
264
+ }
265
+ const args = ['diff', '--name-only', '--no-renames'];
266
+ if (base === 'HEAD' && !headRef) {
267
+ args.push('--cached');
268
+ }
269
+ else {
270
+ args.push(`${base}...${head}`);
271
+ }
272
+ const result = await execGit(args, workspaceRoot);
273
+ if (!result.ok) {
274
+ return {
275
+ ok: false,
276
+ files: [],
277
+ baseRef: base,
278
+ headRef: head || 'HEAD',
279
+ error: `git diff failed: ${result.error || 'unknown error'}. The ref "${base}" may not exist.`,
280
+ };
281
+ }
282
+ const files = result.output
283
+ .trim()
284
+ .split('\n')
285
+ .filter(Boolean)
286
+ .map(f => f.replace(/\\/g, '/'))
287
+ .filter(f => !f.startsWith(' '));
288
+ const capped = files.slice(0, MAX_CHANGED_FILES);
289
+ const truncated = files.length > MAX_CHANGED_FILES;
290
+ return {
291
+ ok: true,
292
+ files: capped,
293
+ baseRef: base,
294
+ headRef: head || 'HEAD',
295
+ error: truncated ? `Truncated to ${MAX_CHANGED_FILES} files (${files.length} total changed).` : undefined,
296
+ };
297
+ }
298
+ async function formatGitChangedFiles(workspaceRoot, baseRef, headRef) {
299
+ const result = await getGitChangedFiles(workspaceRoot, baseRef, headRef);
300
+ if (!result.ok) {
301
+ return result.error || 'Failed to get changed files.';
302
+ }
303
+ if (result.files.length === 0) {
304
+ return `No files changed between ${result.baseRef} and ${result.headRef}.`;
305
+ }
306
+ const out = [
307
+ `Changed files (${result.files.length}) between ${result.baseRef} and ${result.headRef}:`,
308
+ ];
309
+ for (const f of result.files) {
310
+ out.push(` ${f}`);
311
+ }
312
+ if (result.error) {
313
+ out.push(`\nNote: ${result.error}`);
314
+ }
315
+ return truncate(out.join('\n'));
316
+ }
317
+ //# sourceMappingURL=gitContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitContext.js","sourceRoot":"","sources":["../../src/utils/gitContext.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,61 @@
1
+ /**
2
+ * Local test runner — drives execution of LLM-generated verification tests
3
+ * through the verification sandbox.
4
+ *
5
+ * SECURITY MODEL (post-rewrite):
6
+ * 1. `checkTestSafety()` runs first as defense-in-depth. If it blocks,
7
+ * we return early without spawning anything.
8
+ * 2. `detectSandbox()` returns the best available real isolation backend
9
+ * (Docker preferred, Deno as a JS/TS-only fallback). If neither is
10
+ * available, this runner returns `sandbox-unavailable` — it does NOT
11
+ * fall back to executing the script with host privileges.
12
+ * 3. The sandbox backend executes the script with no network, a
13
+ * read-only workspace, a tmpfs /tmp, capped CPU/memory/pids, and a
14
+ * scrubbed env (only NODE_ENV and PATH). The verdict is parsed from
15
+ * stdout/stderr against `/PASS:/` and `/FAIL:/` markers.
16
+ *
17
+ * The previous implementation spread the full `process.env` into the
18
+ * child and ran via `execFileSync` with no isolation. That allowed
19
+ * prompt-injected content in scanned source to ride into the
20
+ * verify-generate prompt and produce a test that exfiltrated secrets.
21
+ */
22
+ import { type SandboxBackend } from './verificationSandbox';
1
23
  export interface LocalTestResult {
2
- verdict: 'pass' | 'fail' | 'error' | 'timeout';
24
+ verdict: 'pass' | 'fail' | 'error' | 'timeout' | 'blocked' | 'sandbox-unavailable' | 'cancelled';
3
25
  output: string;
4
26
  exitCode: number;
27
+ /** Name of the backend that executed the test (e.g. "docker", "deno"). Empty when blocked or unavailable. */
28
+ backend?: string;
5
29
  }
6
- export declare function runLocalTest(script: string, runner: string, workspaceRoot: string): Promise<LocalTestResult>;
30
+ /**
31
+ * The message shown when no isolation backend is available. Exported so the
32
+ * agent-scan tool can reuse it in its top-level `verifyHint` (instead of
33
+ * every finding carrying the full text in its `provenReason`).
34
+ *
35
+ * Why this matters: without a sandbox, the verify loop returns INCONCLUSIVE
36
+ * for every high/medium finding. The headline differentiator of Pipeline 2
37
+ * ("exploit-verified, not just LLM-believed") is offline. The user needs to
38
+ * know — in one place, with a copy-pasteable install path — what to do.
39
+ */
40
+ export declare const SANDBOX_UNAVAILABLE_MESSAGE: string;
41
+ export declare function runLocalTest(script: string, runner: string, workspaceRoot: string, options?: {
42
+ setupScript?: string | null;
43
+ timeoutMs?: number;
44
+ signal?: AbortSignal;
45
+ /** Test-only: inject a sandbox backend. Production code leaves this unset. */
46
+ sandboxBackend?: SandboxBackend;
47
+ }): Promise<LocalTestResult>;
48
+ /**
49
+ * Run a validated test command (npm test, pytest, etc.) inside the sandbox.
50
+ * Uses command mode — no script file is written; the executable + args are
51
+ * passed directly to the sandbox backend. The sandbox enforces network=none,
52
+ * read-only workspace, and resource limits.
53
+ *
54
+ * Returns the same LocalTestResult shape as runLocalTest, with exit-code-based
55
+ * verdicts (0 = pass, nonzero = fail).
56
+ */
57
+ export declare function runTestCommand(executable: string, args: string[], workspaceRoot: string, options?: {
58
+ timeoutMs?: number;
59
+ signal?: AbortSignal;
60
+ sandboxBackend?: SandboxBackend;
61
+ }): Promise<LocalTestResult>;