@securecode-ai/mcp 0.1.0 → 0.2.0
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.
- package/README.md +5 -3
- package/dist/api/client.d.ts +4 -0
- package/dist/api/client.js +49 -0
- package/dist/api/client.js.map +1 -1
- package/dist/api/types.d.ts +40 -0
- package/dist/index.js +64 -7
- package/dist/index.js.map +1 -1
- package/dist/poc/httpPocExecutor.d.ts +20 -0
- package/dist/poc/httpPocExecutor.js +247 -0
- package/dist/poc/httpPocExecutor.js.map +1 -0
- package/dist/poc/lightpandaExecutor.d.ts +41 -0
- package/dist/poc/lightpandaExecutor.js +263 -0
- package/dist/poc/lightpandaExecutor.js.map +1 -0
- package/dist/poc/pocExecutor.d.ts +46 -0
- package/dist/poc/pocExecutor.js +74 -0
- package/dist/poc/pocExecutor.js.map +1 -0
- package/dist/poc/pocRouter.d.ts +20 -0
- package/dist/poc/pocRouter.js +40 -0
- package/dist/poc/pocRouter.js.map +1 -0
- package/dist/poc/pocTypes.d.ts +54 -0
- package/dist/poc/pocTypes.js +16 -0
- package/dist/poc/pocTypes.js.map +1 -0
- package/dist/project-map/fixTester.d.ts +55 -0
- package/dist/project-map/fixTester.js +338 -0
- package/dist/project-map/fixTester.js.map +1 -0
- package/dist/project-map/guardEvaluator.d.ts +40 -0
- package/dist/project-map/guardEvaluator.js +216 -0
- package/dist/project-map/guardEvaluator.js.map +1 -0
- package/dist/project-map/guardPatterns.d.ts +43 -0
- package/dist/project-map/guardPatterns.js +173 -0
- package/dist/project-map/guardPatterns.js.map +1 -0
- package/dist/project-map/sanitizers.d.ts +34 -0
- package/dist/project-map/sanitizers.js +76 -0
- package/dist/project-map/sanitizers.js.map +1 -0
- package/dist/project-map/sinkFinder.d.ts +48 -0
- package/dist/project-map/sinkFinder.js +340 -0
- package/dist/project-map/sinkFinder.js.map +1 -0
- package/dist/project-map/sinkRegistry.d.ts +60 -0
- package/dist/project-map/sinkRegistry.js +246 -0
- package/dist/project-map/sinkRegistry.js.map +1 -0
- package/dist/project-map/taintSources.d.ts +30 -0
- package/dist/project-map/taintSources.js +77 -0
- package/dist/project-map/taintSources.js.map +1 -0
- package/dist/project-map/taintTracker.d.ts +42 -0
- package/dist/project-map/taintTracker.js +571 -0
- package/dist/project-map/taintTracker.js.map +1 -0
- package/dist/tools/scan.js +44 -0
- package/dist/tools/scan.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Phase F — Lightpanda POC executor.
|
|
4
|
+
*
|
|
5
|
+
* Runs POCs that need a real browser engine (DOM-based XSS, client-side
|
|
6
|
+
* validation bypass) via Lightpanda's headless browser. Generates a
|
|
7
|
+
* PandaScript, runs it with `lightpanda agent <script.js>` (no LLM, no
|
|
8
|
+
* API key — deterministic replay), and parses the JSON output.
|
|
9
|
+
*
|
|
10
|
+
* Lightpanda is optional: if the binary is not on PATH, the executor
|
|
11
|
+
* returns a "not verified" result with install instructions. The
|
|
12
|
+
* existing SandboxRunner handles HTTP-based POCs independently.
|
|
13
|
+
*
|
|
14
|
+
* Install: curl -fsSL https://pkg.lightpanda.io/install.sh | bash
|
|
15
|
+
* Docs: https://lightpanda.io/docs
|
|
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.isLightpandaAvailable = isLightpandaAvailable;
|
|
52
|
+
exports._resetAvailabilityCache = _resetAvailabilityCache;
|
|
53
|
+
exports.generatePandaScript = generatePandaScript;
|
|
54
|
+
exports.executeWithLightpanda = executeWithLightpanda;
|
|
55
|
+
const child_process_1 = require("child_process");
|
|
56
|
+
const fs = __importStar(require("fs"));
|
|
57
|
+
const path = __importStar(require("path"));
|
|
58
|
+
const os = __importStar(require("os"));
|
|
59
|
+
// ── Binary detection ────────────────────────────────────────────────────────
|
|
60
|
+
let _available = null;
|
|
61
|
+
/**
|
|
62
|
+
* Check if the Lightpanda binary is on PATH. Memoized — the check runs
|
|
63
|
+
* execSync which is expensive, so we cache the result for the process
|
|
64
|
+
* lifetime.
|
|
65
|
+
*/
|
|
66
|
+
function isLightpandaAvailable() {
|
|
67
|
+
if (_available !== null)
|
|
68
|
+
return _available;
|
|
69
|
+
try {
|
|
70
|
+
(0, child_process_1.execSync)('lightpanda --version', { stdio: 'ignore', timeout: 5000 });
|
|
71
|
+
_available = true;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
_available = false;
|
|
75
|
+
}
|
|
76
|
+
return _available;
|
|
77
|
+
}
|
|
78
|
+
/** Reset the availability cache (for tests). */
|
|
79
|
+
function _resetAvailabilityCache() {
|
|
80
|
+
_available = null;
|
|
81
|
+
}
|
|
82
|
+
// ── PandaScript generation ──────────────────────────────────────────────────
|
|
83
|
+
/**
|
|
84
|
+
* Generate a PandaScript for the given POC request.
|
|
85
|
+
*
|
|
86
|
+
* The script uses Lightpanda's native page API (goto, fill, click, extract)
|
|
87
|
+
* — no LLM at runtime. The last expression auto-prints as JSON.
|
|
88
|
+
*/
|
|
89
|
+
function generatePandaScript(req) {
|
|
90
|
+
const baseUrl = req.endpoint.baseUrl || 'http://127.0.0.1:3000';
|
|
91
|
+
const fullPath = req.endpoint.path.startsWith('/')
|
|
92
|
+
? req.endpoint.path
|
|
93
|
+
: '/' + req.endpoint.path;
|
|
94
|
+
const url = baseUrl + fullPath;
|
|
95
|
+
const payload = req.payload || '<script>alert(1)</script>';
|
|
96
|
+
// XSS: navigate to the endpoint with the payload, check if it appears
|
|
97
|
+
// unescaped in the rendered DOM.
|
|
98
|
+
if (req.vulnType === 'xss') {
|
|
99
|
+
const injectionPoint = req.injectionPoint || 'query';
|
|
100
|
+
const paramName = req.paramName || 'q';
|
|
101
|
+
if (injectionPoint === 'query') {
|
|
102
|
+
// Query parameter injection: navigate directly to the URL with payload
|
|
103
|
+
const injectUrl = `${url}${url.includes('?') ? '&' : '?'}${paramName}=${encodeURIComponent(payload)}`;
|
|
104
|
+
return [
|
|
105
|
+
`// PandaScript — XSS POC (query injection)`,
|
|
106
|
+
`// Generated by SecureCode Phase F`,
|
|
107
|
+
`const page = new Page();`,
|
|
108
|
+
`await page.goto(${JSON.stringify(injectUrl)});`,
|
|
109
|
+
`const result = page.extract([{ selector: 'body', fields: { content: '' } }]);`,
|
|
110
|
+
`const bodyContent = result[0]?.content || '';`,
|
|
111
|
+
`const payload = ${JSON.stringify(payload)};`,
|
|
112
|
+
`const exploited = bodyContent.includes(payload);`,
|
|
113
|
+
`return { exploited, evidence: exploited ? 'Payload found unescaped in rendered DOM' : 'Payload not found in DOM (may be sanitized)' };`,
|
|
114
|
+
].join('\n');
|
|
115
|
+
}
|
|
116
|
+
if (injectionPoint === 'body') {
|
|
117
|
+
// Body injection: fill a form field and submit
|
|
118
|
+
return [
|
|
119
|
+
`// PandaScript — XSS POC (body injection)`,
|
|
120
|
+
`// Generated by SecureCode Phase F`,
|
|
121
|
+
`const page = new Page();`,
|
|
122
|
+
`await page.goto(${JSON.stringify(url)});`,
|
|
123
|
+
`await page.fill('input[name=${JSON.stringify(paramName)}], input[type="text"], textarea', ${JSON.stringify(payload)});`,
|
|
124
|
+
`await page.click('button[type="submit"], input[type="submit"], button');`,
|
|
125
|
+
`const result = page.extract([{ selector: 'body', fields: { content: '' } }]);`,
|
|
126
|
+
`const bodyContent = result[0]?.content || '';`,
|
|
127
|
+
`const payload = ${JSON.stringify(payload)};`,
|
|
128
|
+
`const exploited = bodyContent.includes(payload);`,
|
|
129
|
+
`return { exploited, evidence: exploited ? 'Payload found unescaped in rendered DOM after form submission' : 'Payload not found in DOM (may be sanitized or form selector mismatch)' };`,
|
|
130
|
+
].join('\n');
|
|
131
|
+
}
|
|
132
|
+
// Default: navigate directly and check
|
|
133
|
+
return [
|
|
134
|
+
`// PandaScript — XSS POC (direct navigation)`,
|
|
135
|
+
`const page = new Page();`,
|
|
136
|
+
`await page.goto(${JSON.stringify(url)});`,
|
|
137
|
+
`const result = page.extract([{ selector: 'body', fields: { content: '' } }]);`,
|
|
138
|
+
`const bodyContent = result[0]?.content || '';`,
|
|
139
|
+
`const payload = ${JSON.stringify(payload)};`,
|
|
140
|
+
`const exploited = bodyContent.includes(payload);`,
|
|
141
|
+
`return { exploited, evidence: exploited ? 'Payload found in DOM' : 'Payload not found in DOM' };`,
|
|
142
|
+
].join('\n');
|
|
143
|
+
}
|
|
144
|
+
// Open redirect: navigate and check the final URL
|
|
145
|
+
if (req.vulnType === 'open_redirect') {
|
|
146
|
+
const paramName = req.paramName || 'url';
|
|
147
|
+
const redirectUrl = `${url}${url.includes('?') ? '&' : '?'}${paramName}=${encodeURIComponent(req.payload || 'https://evil.com')}`;
|
|
148
|
+
return [
|
|
149
|
+
`// PandaScript — Open Redirect POC`,
|
|
150
|
+
`const page = new Page();`,
|
|
151
|
+
`await page.goto(${JSON.stringify(redirectUrl)});`,
|
|
152
|
+
`const finalUrl = page.getUrl();`,
|
|
153
|
+
`const target = ${JSON.stringify(req.payload || 'https://evil.com')};`,
|
|
154
|
+
`const exploited = finalUrl.includes(target);`,
|
|
155
|
+
`return { exploited, evidence: exploited ? 'Redirected to ' + finalUrl : 'Did not redirect to target (stayed at ' + finalUrl + ')' };`,
|
|
156
|
+
].join('\n');
|
|
157
|
+
}
|
|
158
|
+
// Generic fallback: navigate and extract page content
|
|
159
|
+
return [
|
|
160
|
+
`// PandaScript — Generic POC`,
|
|
161
|
+
`const page = new Page();`,
|
|
162
|
+
`await page.goto(${JSON.stringify(url)});`,
|
|
163
|
+
`const result = page.extract([{ selector: 'body', fields: { content: '' } }]);`,
|
|
164
|
+
`return { exploited: false, evidence: 'No specific POC pattern for ${req.vulnType}; page content: ' + (result[0]?.content || '').slice(0, 500) };`,
|
|
165
|
+
].join('\n');
|
|
166
|
+
}
|
|
167
|
+
// ── Execution ───────────────────────────────────────────────────────────────
|
|
168
|
+
/**
|
|
169
|
+
* Execute a POC using Lightpanda.
|
|
170
|
+
*
|
|
171
|
+
* Generates a PandaScript, writes it to a temp file, runs
|
|
172
|
+
* `lightpanda agent <script.js>` (no LLM, deterministic), and parses the
|
|
173
|
+
* JSON output.
|
|
174
|
+
*
|
|
175
|
+
* Returns a "not verified" result when Lightpanda is not installed.
|
|
176
|
+
*/
|
|
177
|
+
async function executeWithLightpanda(req) {
|
|
178
|
+
if (!isLightpandaAvailable()) {
|
|
179
|
+
return {
|
|
180
|
+
exploitable: false,
|
|
181
|
+
timedOut: false,
|
|
182
|
+
evidence: 'Lightpanda binary not found on PATH. Install: curl -fsSL https://pkg.lightpanda.io/install.sh | bash',
|
|
183
|
+
backend: 'none',
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
const script = generatePandaScript(req);
|
|
187
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'securecode-poc-'));
|
|
188
|
+
const scriptPath = path.join(tmpDir, 'poc.js');
|
|
189
|
+
try {
|
|
190
|
+
fs.writeFileSync(scriptPath, script, 'utf8');
|
|
191
|
+
// Run the PandaScript with Lightpanda (no LLM, no API key)
|
|
192
|
+
const result = await new Promise((resolve) => {
|
|
193
|
+
const child = (0, child_process_1.spawn)('lightpanda', ['agent', scriptPath], {
|
|
194
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
195
|
+
shell: true,
|
|
196
|
+
timeout: 10_000, // 10s timeout
|
|
197
|
+
});
|
|
198
|
+
let stdout = '';
|
|
199
|
+
let stderr = '';
|
|
200
|
+
let timedOut = false;
|
|
201
|
+
child.stdout?.on('data', (chunk) => { stdout += chunk.toString(); });
|
|
202
|
+
child.stderr?.on('data', (chunk) => { stderr += chunk.toString(); });
|
|
203
|
+
child.on('close', (code) => {
|
|
204
|
+
if (timedOut)
|
|
205
|
+
return; // timeout handler already resolved
|
|
206
|
+
try {
|
|
207
|
+
// Lightpanda agent prints the last expression as JSON to stdout
|
|
208
|
+
const output = stdout.trim();
|
|
209
|
+
const parsed = JSON.parse(output);
|
|
210
|
+
resolve({
|
|
211
|
+
exploitable: Boolean(parsed.exploited),
|
|
212
|
+
output: parsed.evidence || output,
|
|
213
|
+
timedOut: false,
|
|
214
|
+
evidence: parsed.evidence || 'POC executed via Lightpanda',
|
|
215
|
+
pocScript: script,
|
|
216
|
+
backend: 'lightpanda',
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
resolve({
|
|
221
|
+
exploitable: false,
|
|
222
|
+
output: stdout.slice(0, 500),
|
|
223
|
+
error: stderr.slice(0, 500) || 'Failed to parse Lightpanda output',
|
|
224
|
+
timedOut: false,
|
|
225
|
+
evidence: 'Lightpanda ran but the output was not parseable JSON',
|
|
226
|
+
pocScript: script,
|
|
227
|
+
backend: 'lightpanda',
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
child.on('error', (err) => {
|
|
232
|
+
resolve({
|
|
233
|
+
exploitable: false,
|
|
234
|
+
error: err.message,
|
|
235
|
+
timedOut: false,
|
|
236
|
+
evidence: `Lightpanda failed to start: ${err.message}`,
|
|
237
|
+
pocScript: script,
|
|
238
|
+
backend: 'lightpanda',
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
const timer = setTimeout(() => {
|
|
242
|
+
timedOut = true;
|
|
243
|
+
child.kill('SIGKILL');
|
|
244
|
+
resolve({
|
|
245
|
+
exploitable: false,
|
|
246
|
+
timedOut: true,
|
|
247
|
+
evidence: 'POC timed out after 10s',
|
|
248
|
+
pocScript: script,
|
|
249
|
+
backend: 'lightpanda',
|
|
250
|
+
});
|
|
251
|
+
}, 10_000);
|
|
252
|
+
timer.unref?.();
|
|
253
|
+
});
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
256
|
+
finally {
|
|
257
|
+
try {
|
|
258
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
259
|
+
}
|
|
260
|
+
catch { /* best-effort */ }
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=lightpandaExecutor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lightpandaExecutor.js","sourceRoot":"","sources":["../../src/poc/lightpandaExecutor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase F — POC Executor (main entry point).
|
|
3
|
+
*
|
|
4
|
+
* Verifies whether a Juror VULNERABLE verdict is actually exploitable by
|
|
5
|
+
* running the POC against the live application. Routes to the appropriate
|
|
6
|
+
* backend:
|
|
7
|
+
*
|
|
8
|
+
* - DOM vulns (XSS) → Lightpanda (real browser engine, DOM rendering)
|
|
9
|
+
* - HTTP vulns (SQLi, SSRF, redirect) → HTTP executor (raw HTTP)
|
|
10
|
+
* - Non-web vulns (cmd injection, proto pollution) → none (already
|
|
11
|
+
* proven by the taint tracker / guard evaluator)
|
|
12
|
+
*
|
|
13
|
+
* Lightpanda is optional: if the binary is not installed, DOM POCs return
|
|
14
|
+
* a "not verified" result with install instructions. The existing
|
|
15
|
+
* SandboxRunner handles complex attack scenarios independently.
|
|
16
|
+
*
|
|
17
|
+
* No `isolated-vm`: command injection and prototype pollution are already
|
|
18
|
+
* proven deterministically by the taint tracker (Phase C). The HTTP
|
|
19
|
+
* executor covers server-side vulns. Lightpanda covers DOM vulns. Nothing
|
|
20
|
+
* else needs a sandbox.
|
|
21
|
+
*/
|
|
22
|
+
import type { PocRequest, PocResult } from './pocTypes';
|
|
23
|
+
export type { PocRequest, PocResult, PocEndpoint } from './pocTypes';
|
|
24
|
+
export { routePoc } from './pocRouter';
|
|
25
|
+
export { isLightpandaAvailable } from './lightpandaExecutor';
|
|
26
|
+
export { executeWithLightpanda } from './lightpandaExecutor';
|
|
27
|
+
export { executeWithHttp } from './httpPocExecutor';
|
|
28
|
+
/**
|
|
29
|
+
* Execute a POC against the live application.
|
|
30
|
+
*
|
|
31
|
+
* Routes to the appropriate backend based on the vulnerability type:
|
|
32
|
+
* - XSS → Lightpanda (if available)
|
|
33
|
+
* - SQLi, SSRF, redirect → HTTP executor
|
|
34
|
+
* - Others → none (deterministic analysis already covers them)
|
|
35
|
+
*
|
|
36
|
+
* @param req the POC request
|
|
37
|
+
* @returns the execution result
|
|
38
|
+
*/
|
|
39
|
+
export declare function executePoc(req: PocRequest): Promise<PocResult>;
|
|
40
|
+
/**
|
|
41
|
+
* Execute multiple POCs in parallel.
|
|
42
|
+
*
|
|
43
|
+
* @param requests array of POC requests
|
|
44
|
+
* @returns array of results (same order as input)
|
|
45
|
+
*/
|
|
46
|
+
export declare function executePocs(requests: PocRequest[]): Promise<PocResult[]>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Phase F — POC Executor (main entry point).
|
|
4
|
+
*
|
|
5
|
+
* Verifies whether a Juror VULNERABLE verdict is actually exploitable by
|
|
6
|
+
* running the POC against the live application. Routes to the appropriate
|
|
7
|
+
* backend:
|
|
8
|
+
*
|
|
9
|
+
* - DOM vulns (XSS) → Lightpanda (real browser engine, DOM rendering)
|
|
10
|
+
* - HTTP vulns (SQLi, SSRF, redirect) → HTTP executor (raw HTTP)
|
|
11
|
+
* - Non-web vulns (cmd injection, proto pollution) → none (already
|
|
12
|
+
* proven by the taint tracker / guard evaluator)
|
|
13
|
+
*
|
|
14
|
+
* Lightpanda is optional: if the binary is not installed, DOM POCs return
|
|
15
|
+
* a "not verified" result with install instructions. The existing
|
|
16
|
+
* SandboxRunner handles complex attack scenarios independently.
|
|
17
|
+
*
|
|
18
|
+
* No `isolated-vm`: command injection and prototype pollution are already
|
|
19
|
+
* proven deterministically by the taint tracker (Phase C). The HTTP
|
|
20
|
+
* executor covers server-side vulns. Lightpanda covers DOM vulns. Nothing
|
|
21
|
+
* else needs a sandbox.
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.executeWithHttp = exports.executeWithLightpanda = exports.isLightpandaAvailable = exports.routePoc = void 0;
|
|
25
|
+
exports.executePoc = executePoc;
|
|
26
|
+
exports.executePocs = executePocs;
|
|
27
|
+
const pocRouter_1 = require("./pocRouter");
|
|
28
|
+
const lightpandaExecutor_1 = require("./lightpandaExecutor");
|
|
29
|
+
const httpPocExecutor_1 = require("./httpPocExecutor");
|
|
30
|
+
var pocRouter_2 = require("./pocRouter");
|
|
31
|
+
Object.defineProperty(exports, "routePoc", { enumerable: true, get: function () { return pocRouter_2.routePoc; } });
|
|
32
|
+
var lightpandaExecutor_2 = require("./lightpandaExecutor");
|
|
33
|
+
Object.defineProperty(exports, "isLightpandaAvailable", { enumerable: true, get: function () { return lightpandaExecutor_2.isLightpandaAvailable; } });
|
|
34
|
+
var lightpandaExecutor_3 = require("./lightpandaExecutor");
|
|
35
|
+
Object.defineProperty(exports, "executeWithLightpanda", { enumerable: true, get: function () { return lightpandaExecutor_3.executeWithLightpanda; } });
|
|
36
|
+
var httpPocExecutor_2 = require("./httpPocExecutor");
|
|
37
|
+
Object.defineProperty(exports, "executeWithHttp", { enumerable: true, get: function () { return httpPocExecutor_2.executeWithHttp; } });
|
|
38
|
+
/**
|
|
39
|
+
* Execute a POC against the live application.
|
|
40
|
+
*
|
|
41
|
+
* Routes to the appropriate backend based on the vulnerability type:
|
|
42
|
+
* - XSS → Lightpanda (if available)
|
|
43
|
+
* - SQLi, SSRF, redirect → HTTP executor
|
|
44
|
+
* - Others → none (deterministic analysis already covers them)
|
|
45
|
+
*
|
|
46
|
+
* @param req the POC request
|
|
47
|
+
* @returns the execution result
|
|
48
|
+
*/
|
|
49
|
+
async function executePoc(req) {
|
|
50
|
+
const backend = (0, pocRouter_1.routePoc)(req.vulnType);
|
|
51
|
+
switch (backend) {
|
|
52
|
+
case 'lightpanda':
|
|
53
|
+
return (0, lightpandaExecutor_1.executeWithLightpanda)(req);
|
|
54
|
+
case 'http':
|
|
55
|
+
return (0, httpPocExecutor_1.executeWithHttp)(req);
|
|
56
|
+
case 'none':
|
|
57
|
+
return {
|
|
58
|
+
exploitable: false,
|
|
59
|
+
timedOut: false,
|
|
60
|
+
evidence: `POC verification not applicable for ${req.vulnType} — already proven by deterministic analysis (taint tracker / guard evaluator)`,
|
|
61
|
+
backend: 'none',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Execute multiple POCs in parallel.
|
|
67
|
+
*
|
|
68
|
+
* @param requests array of POC requests
|
|
69
|
+
* @returns array of results (same order as input)
|
|
70
|
+
*/
|
|
71
|
+
async function executePocs(requests) {
|
|
72
|
+
return Promise.all(requests.map(req => executePoc(req)));
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=pocExecutor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pocExecutor.js","sourceRoot":"","sources":["../../src/poc/pocExecutor.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AAyBH,gCAkBC;AAQD,kCAEC;AAlDD,2CAAuC;AACvC,6DAAoF;AACpF,uDAAoD;AAIpD,yCAAuC;AAA9B,qGAAA,QAAQ,OAAA;AACjB,2DAA6D;AAApD,2HAAA,qBAAqB,OAAA;AAC9B,2DAA6D;AAApD,2HAAA,qBAAqB,OAAA;AAC9B,qDAAoD;AAA3C,kHAAA,eAAe,OAAA;AAExB;;;;;;;;;;GAUG;AACI,KAAK,UAAU,UAAU,CAAC,GAAe;IAC5C,MAAM,OAAO,GAAG,IAAA,oBAAQ,EAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEvC,QAAQ,OAAO,EAAE,CAAC;QACd,KAAK,YAAY;YACb,OAAO,IAAA,0CAAqB,EAAC,GAAG,CAAC,CAAC;QAEtC,KAAK,MAAM;YACP,OAAO,IAAA,iCAAe,EAAC,GAAG,CAAC,CAAC;QAEhC,KAAK,MAAM;YACP,OAAO;gBACH,WAAW,EAAE,KAAK;gBAClB,QAAQ,EAAE,KAAK;gBACf,QAAQ,EAAE,uCAAuC,GAAG,CAAC,QAAQ,+EAA+E;gBAC5I,OAAO,EAAE,MAAM;aAClB,CAAC;IACV,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,WAAW,CAAC,QAAsB;IACpD,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase F — POC router.
|
|
3
|
+
*
|
|
4
|
+
* Decides which backend handles a POC based on the vulnerability type.
|
|
5
|
+
*
|
|
6
|
+
* - DOM vulns (XSS) → Lightpanda (needs a real browser to render JS/DOM)
|
|
7
|
+
* - HTTP vulns (SQLi, SSRF, redirect) → HTTP executor (raw HTTP suffices)
|
|
8
|
+
* - Non-web vulns (command injection, proto pollution, crypto) → none
|
|
9
|
+
* (already proven deterministically by the taint tracker / guard evaluator)
|
|
10
|
+
*/
|
|
11
|
+
/** Which backend should handle this POC. */
|
|
12
|
+
export type PocBackend = 'lightpanda' | 'http' | 'none';
|
|
13
|
+
/**
|
|
14
|
+
* Route a POC to the appropriate backend based on the vulnerability type.
|
|
15
|
+
*
|
|
16
|
+
* Returns 'none' for vulnerability types that are already covered by
|
|
17
|
+
* deterministic analysis (taint tracker, guard evaluator) and don't
|
|
18
|
+
* benefit from runtime POC verification.
|
|
19
|
+
*/
|
|
20
|
+
export declare function routePoc(vulnType: string): PocBackend;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Phase F — POC router.
|
|
4
|
+
*
|
|
5
|
+
* Decides which backend handles a POC based on the vulnerability type.
|
|
6
|
+
*
|
|
7
|
+
* - DOM vulns (XSS) → Lightpanda (needs a real browser to render JS/DOM)
|
|
8
|
+
* - HTTP vulns (SQLi, SSRF, redirect) → HTTP executor (raw HTTP suffices)
|
|
9
|
+
* - Non-web vulns (command injection, proto pollution, crypto) → none
|
|
10
|
+
* (already proven deterministically by the taint tracker / guard evaluator)
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.routePoc = routePoc;
|
|
14
|
+
/** Vulnerability types that need a real browser (DOM rendering). */
|
|
15
|
+
const DOM_VULN_TYPES = new Set([
|
|
16
|
+
'xss',
|
|
17
|
+
]);
|
|
18
|
+
/** Vulnerability types that can be verified via raw HTTP. */
|
|
19
|
+
const HTTP_VULN_TYPES = new Set([
|
|
20
|
+
'sql_injection',
|
|
21
|
+
'nosql_injection',
|
|
22
|
+
'ssrf',
|
|
23
|
+
'open_redirect',
|
|
24
|
+
'broken_access_control',
|
|
25
|
+
]);
|
|
26
|
+
/**
|
|
27
|
+
* Route a POC to the appropriate backend based on the vulnerability type.
|
|
28
|
+
*
|
|
29
|
+
* Returns 'none' for vulnerability types that are already covered by
|
|
30
|
+
* deterministic analysis (taint tracker, guard evaluator) and don't
|
|
31
|
+
* benefit from runtime POC verification.
|
|
32
|
+
*/
|
|
33
|
+
function routePoc(vulnType) {
|
|
34
|
+
if (DOM_VULN_TYPES.has(vulnType))
|
|
35
|
+
return 'lightpanda';
|
|
36
|
+
if (HTTP_VULN_TYPES.has(vulnType))
|
|
37
|
+
return 'http';
|
|
38
|
+
return 'none';
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=pocRouter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pocRouter.js","sourceRoot":"","sources":["../../src/poc/pocRouter.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;AA0BH,4BAIC;AAzBD,oEAAoE;AACpE,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC3B,KAAK;CACR,CAAC,CAAC;AAEH,6DAA6D;AAC7D,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC5B,eAAe;IACf,iBAAiB;IACjB,MAAM;IACN,eAAe;IACf,uBAAuB;CAC1B,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,SAAgB,QAAQ,CAAC,QAAgB;IACrC,IAAI,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO,YAAY,CAAC;IACtD,IAAI,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO,MAAM,CAAC;IACjD,OAAO,MAAM,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase F — POC Executor types.
|
|
3
|
+
*
|
|
4
|
+
* The POC executor verifies whether a Juror VULNERABLE verdict is actually
|
|
5
|
+
* exploitable by running the POC against the live application. It routes
|
|
6
|
+
* to either Lightpanda (DOM-based vulns that need a real browser) or a
|
|
7
|
+
* simple HTTP executor (server-side vulns where raw HTTP suffices).
|
|
8
|
+
*
|
|
9
|
+
* No `isolated-vm` — command injection and prototype pollution are already
|
|
10
|
+
* proven deterministically by the taint tracker (Phase C), and the existing
|
|
11
|
+
* SandboxRunner handles complex attack scenarios. This executor is a thin
|
|
12
|
+
* verification layer for the Juror's POC claims.
|
|
13
|
+
*/
|
|
14
|
+
/** The target endpoint for the POC. */
|
|
15
|
+
export interface PocEndpoint {
|
|
16
|
+
method: string;
|
|
17
|
+
path: string;
|
|
18
|
+
/** Base URL of the running app, e.g. http://127.0.0.1:3000 */
|
|
19
|
+
baseUrl?: string;
|
|
20
|
+
}
|
|
21
|
+
/** A request to execute a POC. */
|
|
22
|
+
export interface PocRequest {
|
|
23
|
+
/** Canonical vulnerability type: xss, sql_injection, open_redirect, etc. */
|
|
24
|
+
vulnType: string;
|
|
25
|
+
/** The POC description from the Juror's `attack_example`. */
|
|
26
|
+
poc: string;
|
|
27
|
+
/** The target endpoint. */
|
|
28
|
+
endpoint: PocEndpoint;
|
|
29
|
+
/** The attack payload to inject (extracted from the POC or provided directly). */
|
|
30
|
+
payload?: string;
|
|
31
|
+
/** What a successful exploit looks like (from the Juror). */
|
|
32
|
+
expectedBehavior?: string;
|
|
33
|
+
/** Where to inject the payload: 'query', 'body', 'path', 'header'. */
|
|
34
|
+
injectionPoint?: 'query' | 'body' | 'path' | 'header';
|
|
35
|
+
/** Parameter name for the injection (e.g. 'q' for ?q=payload). */
|
|
36
|
+
paramName?: string;
|
|
37
|
+
}
|
|
38
|
+
/** The result of running a POC. */
|
|
39
|
+
export interface PocResult {
|
|
40
|
+
/** True if the exploit was confirmed. */
|
|
41
|
+
exploitable: boolean;
|
|
42
|
+
/** What the executor observed. */
|
|
43
|
+
output?: string;
|
|
44
|
+
/** Error message when the executor itself failed. */
|
|
45
|
+
error?: string;
|
|
46
|
+
/** True when the POC timed out. */
|
|
47
|
+
timedOut: boolean;
|
|
48
|
+
/** Why this proves/disproves exploitability. */
|
|
49
|
+
evidence: string;
|
|
50
|
+
/** Replayable PandaScript (when Lightpanda was used). */
|
|
51
|
+
pocScript?: string;
|
|
52
|
+
/** Which backend was used. */
|
|
53
|
+
backend: 'lightpanda' | 'http' | 'none';
|
|
54
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Phase F — POC Executor types.
|
|
4
|
+
*
|
|
5
|
+
* The POC executor verifies whether a Juror VULNERABLE verdict is actually
|
|
6
|
+
* exploitable by running the POC against the live application. It routes
|
|
7
|
+
* to either Lightpanda (DOM-based vulns that need a real browser) or a
|
|
8
|
+
* simple HTTP executor (server-side vulns where raw HTTP suffices).
|
|
9
|
+
*
|
|
10
|
+
* No `isolated-vm` — command injection and prototype pollution are already
|
|
11
|
+
* proven deterministically by the taint tracker (Phase C), and the existing
|
|
12
|
+
* SandboxRunner handles complex attack scenarios. This executor is a thin
|
|
13
|
+
* verification layer for the Juror's POC claims.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
//# sourceMappingURL=pocTypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pocTypes.js","sourceRoot":"","sources":["../../src/poc/pocTypes.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase H — Fix Regression Tester.
|
|
3
|
+
*
|
|
4
|
+
* Verifies that a fix doesn't break existing behavior or introduce new
|
|
5
|
+
* vulnerabilities by running a differential analysis on the original and
|
|
6
|
+
* fixed code.
|
|
7
|
+
*
|
|
8
|
+
* Algorithm:
|
|
9
|
+
* 1. Syntax check: parse the fixed code — if it doesn't parse, syntaxValid = false
|
|
10
|
+
* 2. Differential analysis: run the AST Sink Finder (Phase B) + Taint Tracker
|
|
11
|
+
* (Phase C) on both original and fixed code
|
|
12
|
+
* - Original had a tainted sink + fixed doesn't → fix is effective
|
|
13
|
+
* - Fixed code has a new tainted sink → newVulnerabilities
|
|
14
|
+
* - Fixed code has a new sink not in original → newVulnerabilities
|
|
15
|
+
* 3. Functional regression: check if the fix changed the code structure
|
|
16
|
+
* in ways that could break behavior (removed functions, changed signatures)
|
|
17
|
+
*
|
|
18
|
+
* No runtime execution needed — the POC Executor (Phase F) handles that.
|
|
19
|
+
* The fix tester is purely static: it compares the AST analysis results.
|
|
20
|
+
*/
|
|
21
|
+
import type { SinkLanguage } from './sinkRegistry';
|
|
22
|
+
export interface FixTestResult {
|
|
23
|
+
/** True if the fix passes all checks (syntax valid, no new vulns, effective). */
|
|
24
|
+
passes: boolean;
|
|
25
|
+
/** True if the fixed code parses without syntax errors. */
|
|
26
|
+
syntaxValid: boolean;
|
|
27
|
+
/** True if the fix actually removed the original vulnerability. */
|
|
28
|
+
fixEffective: boolean;
|
|
29
|
+
/** New vulnerabilities introduced by the fix. */
|
|
30
|
+
newVulnerabilities: string[];
|
|
31
|
+
/** Behavioral regressions detected (removed functions, changed signatures). */
|
|
32
|
+
regressions: string[];
|
|
33
|
+
/** Individual test results. */
|
|
34
|
+
tests: {
|
|
35
|
+
name: string;
|
|
36
|
+
passed: boolean;
|
|
37
|
+
error?: string;
|
|
38
|
+
}[];
|
|
39
|
+
}
|
|
40
|
+
export interface FixTestOptions {
|
|
41
|
+
/** The canonical vulnerability type being fixed (e.g. 'sql_injection'). */
|
|
42
|
+
vulnType?: string;
|
|
43
|
+
/** The line of the original vulnerability. */
|
|
44
|
+
vulnLine?: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Test a fix by comparing the original and fixed code statically.
|
|
48
|
+
*
|
|
49
|
+
* @param originalCode the original source code
|
|
50
|
+
* @param fixedCode the fixed source code
|
|
51
|
+
* @param language the source language
|
|
52
|
+
* @param options optional test options (vulnType, vulnLine)
|
|
53
|
+
* @returns the test result
|
|
54
|
+
*/
|
|
55
|
+
export declare function testFix(originalCode: string, fixedCode: string, language: SinkLanguage, options?: FixTestOptions): Promise<FixTestResult>;
|