@pensar/apex 2.0.1 → 2.0.2-canary.9e4e15cf
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/build/{agent-x7n47c84.js → agent-1jp62njk.js} +9 -9
- package/build/{agent-6nhperp2.js → agent-1zfxfgfr.js} +9 -7
- package/build/agent-ssm6x6qs.js +19 -0
- package/build/{apps-2ac4vt09.js → apps-2qd57k2z.js} +20 -15
- package/build/{auth-bmt98hz0.js → auth-bwb51krx.js} +15 -15
- package/build/authentication-3p84dzrr.js +19 -0
- package/build/blackboxAgent-dn68r23n.js +19 -0
- package/build/{blackboxPentest-xngbtdxb.js → blackboxPentest-txe2h6h0.js} +13 -13
- package/build/{cli-0yptvbbm.js → cli-0t1j4jh4.js} +9 -8
- package/build/{cli-fxtbkw2f.js → cli-3n78e7hs.js} +3 -3
- package/build/{cli-hk03x6fq.js → cli-8pw332mm.js} +2 -1
- package/build/{cli-z1dapp7v.js → cli-dk63pna5.js} +48 -11
- package/build/{cli-mfzkhttr.js → cli-e450tvx3.js} +11 -9
- package/build/{cli-f93g10xk.js → cli-jd0bfde5.js} +2 -2
- package/build/{cli-w2st266h.js → cli-jh6k2m9z.js} +31 -2
- package/build/{cli-88bhxzr1.js → cli-kj5vjbnd.js} +1 -1
- package/build/{cli-eptabm2j.js → cli-kxpba6jy.js} +1 -1
- package/build/{cli-1f5zzrxj.js → cli-nc2yvszh.js} +1 -1
- package/build/{cli-8g5cwvbm.js → cli-p904s2yj.js} +1 -1
- package/build/{cli-fa7nrded.js → cli-ppq4kh08.js} +3 -3
- package/build/{cli-zpdmnz8c.js → cli-qdh225p7.js} +353 -227
- package/build/{cli-cc13ydyx.js → cli-w1nb1y6h.js} +1 -1
- package/build/{cli-pyzw545d.js → cli-xcr4rax4.js} +23 -5
- package/build/{cli-ddtmgbqv.js → cli-za4t23gh.js} +2 -2
- package/build/cli.js +44 -39
- package/build/{config-j0gfjhrm.js → config-6s6jsd2a.js} +3 -3
- package/build/{doctor-zn8ms7gs.js → doctor-yh7zdmgt.js} +6 -6
- package/build/{fixes-d8ytvyzn.js → fixes-0xebnr67.js} +15 -15
- package/build/{index-528cyewc.js → index-k3f1hxpe.js} +17 -17
- package/build/{index-3cbcjqw1.js → index-kjky8ack.js} +9 -9
- package/build/{index-hjvqqkem.js → index-qfveae0v.js} +4 -4
- package/build/{index-a1sy2zak.js → index-ss31xhpj.js} +2 -2
- package/build/{index-9d2es97h.js → index-t3rffyf8.js} +3 -3
- package/build/{index-2t2cg8x0.js → index-w81kvhhz.js} +8 -8
- package/build/{index-k6ttkac6.js → index-zgr0dv9e.js} +6 -6
- package/build/{issues-17kdjtdg.js → issues-zjybm91e.js} +15 -15
- package/build/{logs-r4rjar4m.js → logs-t0vtg96a.js} +15 -15
- package/build/{offesecAgent-azd8ahkm.js → offesecAgent-kfjetqzw.js} +8 -8
- package/build/pentest-043y2x03.js +28 -0
- package/build/{pentests-npjb5q1h.js → pentests-h2mk21aq.js} +15 -15
- package/build/{targetedPentest-m24wvscc.js → targetedPentest-m6k9nde8.js} +9 -9
- package/build/targets-pknexde1.js +113 -0
- package/build/threatModel-mb9340cz.js +26 -0
- package/build/{uninstall-7pm6zcah.js → uninstall-bnamn9pn.js} +1 -1
- package/build/{upload-wg0vxmk0.js → upload-xrbxx4hz.js} +6 -6
- package/build/{utils-gd1y4t26.js → utils-6e1wgez0.js} +5 -5
- package/package.json +9 -8
- package/build/agent-4g69jwmq.js +0 -19
- package/build/authentication-c0aj9zaz.js +0 -19
- package/build/blackboxAgent-sgph70e4.js +0 -19
- package/build/pentest-2vsjf0j8.js +0 -28
- package/build/threatModel-7akmfzzm.js +0 -26
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
detectOSAndEnhancePrompt
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-w1nb1y6h.js";
|
|
4
4
|
import {
|
|
5
5
|
parseTargetUrl
|
|
6
6
|
} from "./cli-c8131c4q.js";
|
|
@@ -26,14 +26,14 @@ import {
|
|
|
26
26
|
scopedLogger,
|
|
27
27
|
streamResponse,
|
|
28
28
|
write
|
|
29
|
-
} from "./cli-
|
|
29
|
+
} from "./cli-dk63pna5.js";
|
|
30
30
|
import {
|
|
31
31
|
ensureValidToken,
|
|
32
32
|
getPensarApiUrl,
|
|
33
33
|
init_auth,
|
|
34
34
|
init_constants,
|
|
35
35
|
signGatewayRequest
|
|
36
|
-
} from "./cli-
|
|
36
|
+
} from "./cli-p904s2yj.js";
|
|
37
37
|
import {
|
|
38
38
|
_enum,
|
|
39
39
|
_null,
|
|
@@ -64,7 +64,7 @@ import {
|
|
|
64
64
|
import {
|
|
65
65
|
config,
|
|
66
66
|
init_config
|
|
67
|
-
} from "./cli-
|
|
67
|
+
} from "./cli-kxpba6jy.js";
|
|
68
68
|
import {
|
|
69
69
|
__commonJS,
|
|
70
70
|
__require,
|
|
@@ -42486,8 +42486,8 @@ var require_core3 = __commonJS((exports) => {
|
|
|
42486
42486
|
function many1(p) {
|
|
42487
42487
|
return ab(p, many(p), (head, tail) => [head, ...tail]);
|
|
42488
42488
|
}
|
|
42489
|
-
function ab(pa, pb,
|
|
42490
|
-
return (data, i) => mapOuter(pa(data, i), (ma) => mapInner(pb(data, ma.position), (vb, j) =>
|
|
42489
|
+
function ab(pa, pb, join14) {
|
|
42490
|
+
return (data, i) => mapOuter(pa(data, i), (ma) => mapInner(pb(data, ma.position), (vb, j) => join14(ma.value, vb, data, i, j)));
|
|
42491
42491
|
}
|
|
42492
42492
|
function left(pa, pb) {
|
|
42493
42493
|
return ab(pa, pb, (va) => va);
|
|
@@ -42495,8 +42495,8 @@ var require_core3 = __commonJS((exports) => {
|
|
|
42495
42495
|
function right(pa, pb) {
|
|
42496
42496
|
return ab(pa, pb, (va, vb) => vb);
|
|
42497
42497
|
}
|
|
42498
|
-
function abc(pa, pb, pc,
|
|
42499
|
-
return (data, i) => mapOuter(pa(data, i), (ma) => mapOuter(pb(data, ma.position), (mb) => mapInner(pc(data, mb.position), (vc, j) =>
|
|
42498
|
+
function abc(pa, pb, pc, join14) {
|
|
42499
|
+
return (data, i) => mapOuter(pa(data, i), (ma) => mapOuter(pb(data, ma.position), (mb) => mapInner(pc(data, mb.position), (vc, j) => join14(ma.value, mb.value, vc, data, i, j))));
|
|
42500
42500
|
}
|
|
42501
42501
|
function middle(pa, pb, pc) {
|
|
42502
42502
|
return abc(pa, pb, pc, (ra, rb) => rb);
|
|
@@ -71179,7 +71179,7 @@ var require_thread_stream = __commonJS((exports, module) => {
|
|
|
71179
71179
|
var { version } = require_package5();
|
|
71180
71180
|
var { EventEmitter: EventEmitter2 } = __require("events");
|
|
71181
71181
|
var { Worker } = __require("worker_threads");
|
|
71182
|
-
var { join:
|
|
71182
|
+
var { join: join14 } = __require("path");
|
|
71183
71183
|
var { pathToFileURL } = __require("url");
|
|
71184
71184
|
var { wait } = require_wait();
|
|
71185
71185
|
var {
|
|
@@ -71215,7 +71215,7 @@ var require_thread_stream = __commonJS((exports, module) => {
|
|
|
71215
71215
|
function createWorker(stream, opts) {
|
|
71216
71216
|
const { filename, workerData } = opts;
|
|
71217
71217
|
const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
|
|
71218
|
-
const toExecute = bundlerOverrides["thread-stream-worker"] ||
|
|
71218
|
+
const toExecute = bundlerOverrides["thread-stream-worker"] || join14(__dirname, "lib", "worker.js");
|
|
71219
71219
|
const worker = new Worker(toExecute, {
|
|
71220
71220
|
...opts.workerOpts,
|
|
71221
71221
|
trackUnmanagedFds: false,
|
|
@@ -71601,10 +71601,10 @@ var require_thread_stream = __commonJS((exports, module) => {
|
|
|
71601
71601
|
// node_modules/pino/lib/transport.js
|
|
71602
71602
|
var require_transport = __commonJS((exports, module) => {
|
|
71603
71603
|
var __dirname = "/home/runner/work/apex/apex/node_modules/pino/lib";
|
|
71604
|
-
var { createRequire:
|
|
71604
|
+
var { createRequire: createRequire3 } = __require("module");
|
|
71605
71605
|
var { existsSync: existsSync9 } = __require("node:fs");
|
|
71606
71606
|
var getCallers = require_caller();
|
|
71607
|
-
var { join:
|
|
71607
|
+
var { join: join14, isAbsolute: isAbsolute2, sep } = __require("node:path");
|
|
71608
71608
|
var { fileURLToPath } = __require("node:url");
|
|
71609
71609
|
var sleep = require_atomic_sleep();
|
|
71610
71610
|
var onExit = require_on_exit_leak_free();
|
|
@@ -71757,7 +71757,7 @@ var require_transport = __commonJS((exports, module) => {
|
|
|
71757
71757
|
throw new Error("only one of target or targets can be specified");
|
|
71758
71758
|
}
|
|
71759
71759
|
if (targets) {
|
|
71760
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
71760
|
+
target = bundlerOverrides["pino-worker"] || join14(__dirname, "worker.js");
|
|
71761
71761
|
options.targets = targets.filter((dest) => dest.target).map((dest) => {
|
|
71762
71762
|
return {
|
|
71763
71763
|
...dest,
|
|
@@ -71774,7 +71774,7 @@ var require_transport = __commonJS((exports, module) => {
|
|
|
71774
71774
|
});
|
|
71775
71775
|
});
|
|
71776
71776
|
} else if (pipeline2) {
|
|
71777
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
71777
|
+
target = bundlerOverrides["pino-worker"] || join14(__dirname, "worker.js");
|
|
71778
71778
|
options.pipelines = [pipeline2.map((dest) => {
|
|
71779
71779
|
return {
|
|
71780
71780
|
...dest,
|
|
@@ -71797,13 +71797,13 @@ var require_transport = __commonJS((exports, module) => {
|
|
|
71797
71797
|
return origin;
|
|
71798
71798
|
}
|
|
71799
71799
|
if (origin === "pino/file") {
|
|
71800
|
-
return
|
|
71800
|
+
return join14(__dirname, "..", "file.js");
|
|
71801
71801
|
}
|
|
71802
71802
|
let fixTarget2;
|
|
71803
71803
|
for (const filePath of callers) {
|
|
71804
71804
|
try {
|
|
71805
71805
|
const context = filePath === "node:repl" ? process.cwd() + sep : filePath;
|
|
71806
|
-
fixTarget2 =
|
|
71806
|
+
fixTarget2 = createRequire3(context).resolve(origin);
|
|
71807
71807
|
break;
|
|
71808
71808
|
} catch (err) {
|
|
71809
71809
|
continue;
|
|
@@ -72726,7 +72726,7 @@ var require_safe_stable_stringify = __commonJS((exports, module) => {
|
|
|
72726
72726
|
return circularValue;
|
|
72727
72727
|
}
|
|
72728
72728
|
let res = "";
|
|
72729
|
-
let
|
|
72729
|
+
let join14 = ",";
|
|
72730
72730
|
const originalIndentation = indentation;
|
|
72731
72731
|
if (Array.isArray(value)) {
|
|
72732
72732
|
if (value.length === 0) {
|
|
@@ -72740,7 +72740,7 @@ var require_safe_stable_stringify = __commonJS((exports, module) => {
|
|
|
72740
72740
|
indentation += spacer;
|
|
72741
72741
|
res += `
|
|
72742
72742
|
${indentation}`;
|
|
72743
|
-
|
|
72743
|
+
join14 = `,
|
|
72744
72744
|
${indentation}`;
|
|
72745
72745
|
}
|
|
72746
72746
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -72748,13 +72748,13 @@ ${indentation}`;
|
|
|
72748
72748
|
for (;i < maximumValuesToStringify - 1; i++) {
|
|
72749
72749
|
const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
72750
72750
|
res += tmp2 !== undefined ? tmp2 : "null";
|
|
72751
|
-
res +=
|
|
72751
|
+
res += join14;
|
|
72752
72752
|
}
|
|
72753
72753
|
const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
72754
72754
|
res += tmp !== undefined ? tmp : "null";
|
|
72755
72755
|
if (value.length - 1 > maximumBreadth) {
|
|
72756
72756
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
72757
|
-
res += `${
|
|
72757
|
+
res += `${join14}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
72758
72758
|
}
|
|
72759
72759
|
if (spacer !== "") {
|
|
72760
72760
|
res += `
|
|
@@ -72775,7 +72775,7 @@ ${originalIndentation}`;
|
|
|
72775
72775
|
let separator = "";
|
|
72776
72776
|
if (spacer !== "") {
|
|
72777
72777
|
indentation += spacer;
|
|
72778
|
-
|
|
72778
|
+
join14 = `,
|
|
72779
72779
|
${indentation}`;
|
|
72780
72780
|
whitespace = " ";
|
|
72781
72781
|
}
|
|
@@ -72789,13 +72789,13 @@ ${indentation}`;
|
|
|
72789
72789
|
const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
|
|
72790
72790
|
if (tmp !== undefined) {
|
|
72791
72791
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
72792
|
-
separator =
|
|
72792
|
+
separator = join14;
|
|
72793
72793
|
}
|
|
72794
72794
|
}
|
|
72795
72795
|
if (keyLength > maximumBreadth) {
|
|
72796
72796
|
const removedKeys = keyLength - maximumBreadth;
|
|
72797
72797
|
res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
|
|
72798
|
-
separator =
|
|
72798
|
+
separator = join14;
|
|
72799
72799
|
}
|
|
72800
72800
|
if (spacer !== "" && separator.length > 1) {
|
|
72801
72801
|
res = `
|
|
@@ -72835,7 +72835,7 @@ ${originalIndentation}`;
|
|
|
72835
72835
|
}
|
|
72836
72836
|
const originalIndentation = indentation;
|
|
72837
72837
|
let res = "";
|
|
72838
|
-
let
|
|
72838
|
+
let join14 = ",";
|
|
72839
72839
|
if (Array.isArray(value)) {
|
|
72840
72840
|
if (value.length === 0) {
|
|
72841
72841
|
return "[]";
|
|
@@ -72848,7 +72848,7 @@ ${originalIndentation}`;
|
|
|
72848
72848
|
indentation += spacer;
|
|
72849
72849
|
res += `
|
|
72850
72850
|
${indentation}`;
|
|
72851
|
-
|
|
72851
|
+
join14 = `,
|
|
72852
72852
|
${indentation}`;
|
|
72853
72853
|
}
|
|
72854
72854
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -72856,13 +72856,13 @@ ${indentation}`;
|
|
|
72856
72856
|
for (;i < maximumValuesToStringify - 1; i++) {
|
|
72857
72857
|
const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
72858
72858
|
res += tmp2 !== undefined ? tmp2 : "null";
|
|
72859
|
-
res +=
|
|
72859
|
+
res += join14;
|
|
72860
72860
|
}
|
|
72861
72861
|
const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
72862
72862
|
res += tmp !== undefined ? tmp : "null";
|
|
72863
72863
|
if (value.length - 1 > maximumBreadth) {
|
|
72864
72864
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
72865
|
-
res += `${
|
|
72865
|
+
res += `${join14}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
72866
72866
|
}
|
|
72867
72867
|
if (spacer !== "") {
|
|
72868
72868
|
res += `
|
|
@@ -72875,7 +72875,7 @@ ${originalIndentation}`;
|
|
|
72875
72875
|
let whitespace = "";
|
|
72876
72876
|
if (spacer !== "") {
|
|
72877
72877
|
indentation += spacer;
|
|
72878
|
-
|
|
72878
|
+
join14 = `,
|
|
72879
72879
|
${indentation}`;
|
|
72880
72880
|
whitespace = " ";
|
|
72881
72881
|
}
|
|
@@ -72884,7 +72884,7 @@ ${indentation}`;
|
|
|
72884
72884
|
const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
|
|
72885
72885
|
if (tmp !== undefined) {
|
|
72886
72886
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
72887
|
-
separator =
|
|
72887
|
+
separator = join14;
|
|
72888
72888
|
}
|
|
72889
72889
|
}
|
|
72890
72890
|
if (spacer !== "" && separator.length > 1) {
|
|
@@ -72941,20 +72941,20 @@ ${originalIndentation}`;
|
|
|
72941
72941
|
indentation += spacer;
|
|
72942
72942
|
let res2 = `
|
|
72943
72943
|
${indentation}`;
|
|
72944
|
-
const
|
|
72944
|
+
const join15 = `,
|
|
72945
72945
|
${indentation}`;
|
|
72946
72946
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
72947
72947
|
let i = 0;
|
|
72948
72948
|
for (;i < maximumValuesToStringify - 1; i++) {
|
|
72949
72949
|
const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
72950
72950
|
res2 += tmp2 !== undefined ? tmp2 : "null";
|
|
72951
|
-
res2 +=
|
|
72951
|
+
res2 += join15;
|
|
72952
72952
|
}
|
|
72953
72953
|
const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
72954
72954
|
res2 += tmp !== undefined ? tmp : "null";
|
|
72955
72955
|
if (value.length - 1 > maximumBreadth) {
|
|
72956
72956
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
72957
|
-
res2 += `${
|
|
72957
|
+
res2 += `${join15}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
72958
72958
|
}
|
|
72959
72959
|
res2 += `
|
|
72960
72960
|
${originalIndentation}`;
|
|
@@ -72970,16 +72970,16 @@ ${originalIndentation}`;
|
|
|
72970
72970
|
return '"[Object]"';
|
|
72971
72971
|
}
|
|
72972
72972
|
indentation += spacer;
|
|
72973
|
-
const
|
|
72973
|
+
const join14 = `,
|
|
72974
72974
|
${indentation}`;
|
|
72975
72975
|
let res = "";
|
|
72976
72976
|
let separator = "";
|
|
72977
72977
|
let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
|
|
72978
72978
|
if (isTypedArrayWithEntries(value)) {
|
|
72979
|
-
res += stringifyTypedArray(value,
|
|
72979
|
+
res += stringifyTypedArray(value, join14, maximumBreadth);
|
|
72980
72980
|
keys = keys.slice(value.length);
|
|
72981
72981
|
maximumPropertiesToStringify -= value.length;
|
|
72982
|
-
separator =
|
|
72982
|
+
separator = join14;
|
|
72983
72983
|
}
|
|
72984
72984
|
if (deterministic) {
|
|
72985
72985
|
keys = sort(keys, comparator);
|
|
@@ -72990,13 +72990,13 @@ ${indentation}`;
|
|
|
72990
72990
|
const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
|
|
72991
72991
|
if (tmp !== undefined) {
|
|
72992
72992
|
res += `${separator}${strEscape(key2)}: ${tmp}`;
|
|
72993
|
-
separator =
|
|
72993
|
+
separator = join14;
|
|
72994
72994
|
}
|
|
72995
72995
|
}
|
|
72996
72996
|
if (keyLength > maximumBreadth) {
|
|
72997
72997
|
const removedKeys = keyLength - maximumBreadth;
|
|
72998
72998
|
res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
|
|
72999
|
-
separator =
|
|
72999
|
+
separator = join14;
|
|
73000
73000
|
}
|
|
73001
73001
|
if (separator !== "") {
|
|
73002
73002
|
res = `
|
|
@@ -109378,8 +109378,46 @@ function isElectron() {
|
|
|
109378
109378
|
init_dist();
|
|
109379
109379
|
init_zod();
|
|
109380
109380
|
import { existsSync as existsSync2, mkdirSync, writeFileSync as writeFileSync2 } from "fs";
|
|
109381
|
-
import { createRequire } from "module";
|
|
109382
|
-
import { dirname, join as
|
|
109381
|
+
import { createRequire as createRequire2 } from "module";
|
|
109382
|
+
import { dirname as dirname2, join as join4 } from "path";
|
|
109383
|
+
|
|
109384
|
+
// src/core/agents/offSecAgent/tools/camoufox.ts
|
|
109385
|
+
import { execFile } from "node:child_process";
|
|
109386
|
+
import { createRequire } from "node:module";
|
|
109387
|
+
import { dirname, join as join3 } from "node:path";
|
|
109388
|
+
import { promisify } from "node:util";
|
|
109389
|
+
var execFileAsync = promisify(execFile);
|
|
109390
|
+
var CAMOUFOX_OPTIONS = {
|
|
109391
|
+
humanize: true,
|
|
109392
|
+
block_webrtc: true
|
|
109393
|
+
};
|
|
109394
|
+
async function resolveCamoufoxLaunchOptions(headless) {
|
|
109395
|
+
const { launchOptions: camoufoxLaunchOptions } = await import("camoufox-js");
|
|
109396
|
+
return await camoufoxLaunchOptions({
|
|
109397
|
+
...CAMOUFOX_OPTIONS,
|
|
109398
|
+
headless
|
|
109399
|
+
});
|
|
109400
|
+
}
|
|
109401
|
+
var ensurePromise = null;
|
|
109402
|
+
function ensureCamoufox(log) {
|
|
109403
|
+
if (!ensurePromise) {
|
|
109404
|
+
ensurePromise = (async () => {
|
|
109405
|
+
log?.("Provisioning Camoufox browser (first run downloads ~150MB; cached after)…");
|
|
109406
|
+
const require_ = createRequire(import.meta.url);
|
|
109407
|
+
const pkgPath = require_.resolve("camoufox-js/package.json");
|
|
109408
|
+
const fetchBin = join3(dirname(pkgPath), "dist", "__main__.js");
|
|
109409
|
+
await execFileAsync("node", [fetchBin, "fetch"], {
|
|
109410
|
+
timeout: 300000
|
|
109411
|
+
});
|
|
109412
|
+
})().catch((err) => {
|
|
109413
|
+
ensurePromise = null;
|
|
109414
|
+
throw err;
|
|
109415
|
+
});
|
|
109416
|
+
}
|
|
109417
|
+
return ensurePromise;
|
|
109418
|
+
}
|
|
109419
|
+
|
|
109420
|
+
// src/core/agents/offSecAgent/tools/playwrightMcp.ts
|
|
109383
109421
|
var BrowserNavigateInput = exports_external.object({
|
|
109384
109422
|
url: exports_external.string().describe("Full URL to navigate to"),
|
|
109385
109423
|
toolCallDescription: exports_external.string().describe("Why you are navigating to this URL")
|
|
@@ -109495,6 +109533,7 @@ class PlaywrightMcpSession {
|
|
|
109495
109533
|
viewportSize;
|
|
109496
109534
|
extraHttpHeaders;
|
|
109497
109535
|
mcpConfigPath = null;
|
|
109536
|
+
cachedCamouOptions = null;
|
|
109498
109537
|
constructor(options = {}) {
|
|
109499
109538
|
const { headless, userAgent, viewportSize, extraHttpHeaders } = options;
|
|
109500
109539
|
this.headless = headless ?? defaultHeadless;
|
|
@@ -109504,14 +109543,26 @@ class PlaywrightMcpSession {
|
|
|
109504
109543
|
this.extraHttpHeaders = headerSource && Object.keys(headerSource).length > 0 ? { ...headerSource } : undefined;
|
|
109505
109544
|
}
|
|
109506
109545
|
resetState() {
|
|
109546
|
+
this.cleanupConfigFile();
|
|
109507
109547
|
this.mcpClient = null;
|
|
109508
109548
|
this.mcpTransport = null;
|
|
109509
109549
|
this.mcpProcess = null;
|
|
109510
109550
|
this.connectionPromise = null;
|
|
109511
109551
|
this.disconnecting = false;
|
|
109512
109552
|
}
|
|
109513
|
-
|
|
109514
|
-
const
|
|
109553
|
+
cleanupConfigFile() {
|
|
109554
|
+
const configPath = this.mcpConfigPath;
|
|
109555
|
+
if (!configPath)
|
|
109556
|
+
return;
|
|
109557
|
+
this.mcpConfigPath = null;
|
|
109558
|
+
(async () => {
|
|
109559
|
+
try {
|
|
109560
|
+
const fsp = await import("fs/promises");
|
|
109561
|
+
await fsp.unlink(configPath);
|
|
109562
|
+
} catch {}
|
|
109563
|
+
})();
|
|
109564
|
+
}
|
|
109565
|
+
forceKillProcess(proc = this.mcpProcess) {
|
|
109515
109566
|
if (!proc || proc.exitCode !== null)
|
|
109516
109567
|
return;
|
|
109517
109568
|
try {
|
|
@@ -109539,41 +109590,40 @@ class PlaywrightMcpSession {
|
|
|
109539
109590
|
}
|
|
109540
109591
|
this.connectionPromise = (async () => {
|
|
109541
109592
|
try {
|
|
109542
|
-
const require_ =
|
|
109593
|
+
const require_ = createRequire2(import.meta.url);
|
|
109543
109594
|
const mcpPkgJsonPath = require_.resolve("@playwright/mcp/package.json");
|
|
109544
|
-
const cliPath =
|
|
109595
|
+
const cliPath = join4(dirname2(mcpPkgJsonPath), "cli.js");
|
|
109545
109596
|
const args = [cliPath, "--isolated"];
|
|
109546
|
-
|
|
109547
|
-
|
|
109548
|
-
|
|
109549
|
-
|
|
109550
|
-
|
|
109551
|
-
|
|
109552
|
-
|
|
109553
|
-
|
|
109554
|
-
|
|
109555
|
-
|
|
109556
|
-
|
|
109557
|
-
|
|
109558
|
-
|
|
109559
|
-
|
|
109560
|
-
|
|
109561
|
-
}
|
|
109562
|
-
|
|
109563
|
-
|
|
109564
|
-
|
|
109565
|
-
|
|
109566
|
-
|
|
109567
|
-
|
|
109568
|
-
|
|
109569
|
-
}
|
|
109570
|
-
|
|
109571
|
-
args.push("--no-sandbox");
|
|
109572
|
-
}
|
|
109597
|
+
await ensureCamoufox();
|
|
109598
|
+
if (!this.cachedCamouOptions) {
|
|
109599
|
+
this.cachedCamouOptions = await resolveCamoufoxLaunchOptions(this.headless);
|
|
109600
|
+
}
|
|
109601
|
+
const camou = this.cachedCamouOptions;
|
|
109602
|
+
const os = await import("os");
|
|
109603
|
+
const fsp = await import("fs/promises");
|
|
109604
|
+
const cfg = {
|
|
109605
|
+
browser: {
|
|
109606
|
+
browserName: "firefox",
|
|
109607
|
+
launchOptions: {
|
|
109608
|
+
executablePath: camou.executablePath,
|
|
109609
|
+
args: camou.args,
|
|
109610
|
+
firefoxUserPrefs: camou.firefoxUserPrefs,
|
|
109611
|
+
headless: camou.headless
|
|
109612
|
+
},
|
|
109613
|
+
...this.extraHttpHeaders ? { contextOptions: { extraHTTPHeaders: this.extraHttpHeaders } } : {}
|
|
109614
|
+
}
|
|
109615
|
+
};
|
|
109616
|
+
this.mcpConfigPath = join4(os.tmpdir(), `pensar-mcp-${process.pid}-${Date.now()}.json`);
|
|
109617
|
+
await fsp.writeFile(this.mcpConfigPath, JSON.stringify(cfg), {
|
|
109618
|
+
encoding: "utf-8",
|
|
109619
|
+
mode: 384
|
|
109620
|
+
});
|
|
109621
|
+
args.push("--config", this.mcpConfigPath);
|
|
109573
109622
|
const transport = new StdioClientTransport({
|
|
109574
109623
|
command: "node",
|
|
109575
109624
|
args,
|
|
109576
|
-
stderr: "pipe"
|
|
109625
|
+
stderr: "pipe",
|
|
109626
|
+
env: Object.fromEntries(Object.entries(camou.env).map(([k, v]) => [k, String(v)]))
|
|
109577
109627
|
});
|
|
109578
109628
|
const client = new Client({
|
|
109579
109629
|
name: "apex-browser-agent",
|
|
@@ -109607,29 +109657,28 @@ class PlaywrightMcpSession {
|
|
|
109607
109657
|
this.disconnecting = true;
|
|
109608
109658
|
const transport = this.mcpTransport;
|
|
109609
109659
|
const client = this.mcpClient;
|
|
109660
|
+
const proc = this.mcpProcess;
|
|
109610
109661
|
this.resetState();
|
|
109611
109662
|
this.disconnecting = true;
|
|
109612
|
-
|
|
109613
|
-
|
|
109614
|
-
|
|
109615
|
-
|
|
109616
|
-
}
|
|
109617
|
-
if (transport) {
|
|
109618
|
-
try {
|
|
109619
|
-
await transport.close();
|
|
109620
|
-
} catch {}
|
|
109621
|
-
}
|
|
109622
|
-
this.forceKillProcess();
|
|
109623
|
-
if (this.mcpConfigPath) {
|
|
109624
|
-
const configPath = this.mcpConfigPath;
|
|
109625
|
-
this.mcpConfigPath = null;
|
|
109663
|
+
this.forceKillProcess(proc);
|
|
109664
|
+
const CLOSE_TIMEOUT_MS = 5000;
|
|
109665
|
+
let closeTimer;
|
|
109666
|
+
await Promise.race([
|
|
109626
109667
|
(async () => {
|
|
109627
109668
|
try {
|
|
109628
|
-
|
|
109629
|
-
await fsp.unlink(configPath);
|
|
109669
|
+
await client?.close();
|
|
109630
109670
|
} catch {}
|
|
109631
|
-
|
|
109632
|
-
|
|
109671
|
+
try {
|
|
109672
|
+
await transport?.close();
|
|
109673
|
+
} catch {}
|
|
109674
|
+
})(),
|
|
109675
|
+
new Promise((resolve) => {
|
|
109676
|
+
closeTimer = setTimeout(resolve, CLOSE_TIMEOUT_MS);
|
|
109677
|
+
})
|
|
109678
|
+
]);
|
|
109679
|
+
if (closeTimer)
|
|
109680
|
+
clearTimeout(closeTimer);
|
|
109681
|
+
this.cleanupConfigFile();
|
|
109633
109682
|
this.disconnecting = false;
|
|
109634
109683
|
}
|
|
109635
109684
|
isConnected() {
|
|
@@ -109953,8 +110002,8 @@ Target base URL: ${targetUrl}`,
|
|
|
109953
110002
|
if (base64Data) {
|
|
109954
110003
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
109955
110004
|
const screenshotFilename = `${filename}_${timestamp}.png`;
|
|
109956
|
-
const screenshotPath =
|
|
109957
|
-
const dir =
|
|
110005
|
+
const screenshotPath = join4(evidenceDir, screenshotFilename);
|
|
110006
|
+
const dir = dirname2(screenshotPath);
|
|
109958
110007
|
if (!existsSync2(dir)) {
|
|
109959
110008
|
mkdirSync(dir, { recursive: true });
|
|
109960
110009
|
}
|
|
@@ -110168,17 +110217,19 @@ The returned cookies can be formatted as a Cookie header for use with http_reque
|
|
|
110168
110217
|
init_dist();
|
|
110169
110218
|
init_zod();
|
|
110170
110219
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
110171
|
-
import { dirname as
|
|
110220
|
+
import { dirname as dirname3, join as join5 } from "path";
|
|
110172
110221
|
var SANDBOX_PW_DIR = "/opt/sandbox-playwright";
|
|
110173
110222
|
var SANDBOX_EVIDENCE_DIR = "/tmp/evidence";
|
|
110174
110223
|
var SANDBOX_REFS_FILE = "/tmp/pw-refs.json";
|
|
110175
110224
|
var SANDBOX_URL_FILE = "/tmp/pw-current-url";
|
|
110176
110225
|
var SANDBOX_CONSOLE_FILE = "/tmp/pw-console-log.json";
|
|
110226
|
+
var SANDBOX_CAMOU_CACHE = "/tmp/pw-camou-opts.json";
|
|
110177
110227
|
var RESULT_START = "__PW_RESULT__";
|
|
110178
110228
|
var RESULT_END = "__PW_END__";
|
|
110179
110229
|
var installationCache = new WeakMap;
|
|
110230
|
+
var browserSetupCache = new WeakMap;
|
|
110180
110231
|
async function checkSandboxPlaywright(sandbox) {
|
|
110181
|
-
const script = `try{require("playwright");console.log("OK")}catch(e){process.exit(1)}`;
|
|
110232
|
+
const script = `(async()=>{try{const{launchPath}=await import("camoufox-js/dist/pkgman.js");require("playwright-core");if(!require("fs").existsSync(launchPath()))process.exit(1);console.log("OK")}catch(e){process.exit(1)}})()`;
|
|
110182
110233
|
const b64 = Buffer.from(script).toString("base64");
|
|
110183
110234
|
await sandbox.execute(`mkdir -p ${SANDBOX_PW_DIR} && echo "${b64}" | base64 -d > ${SANDBOX_PW_DIR}/pw_check.js`, { timeout: 10 });
|
|
110184
110235
|
const result = await sandbox.execute(`node ${SANDBOX_PW_DIR}/pw_check.js`, {
|
|
@@ -110189,35 +110240,33 @@ async function checkSandboxPlaywright(sandbox) {
|
|
|
110189
110240
|
async function installSandboxPlaywright(sandbox) {
|
|
110190
110241
|
await sandbox.execute(`mkdir -p ${SANDBOX_PW_DIR}`, { timeout: 10 });
|
|
110191
110242
|
const isAlpine = (await sandbox.execute("which apk", { timeout: 5 })).success;
|
|
110243
|
+
if (isAlpine) {
|
|
110244
|
+
throw new Error("Camoufox requires a glibc-based sandbox image (Debian/Ubuntu); Alpine/musl is unsupported.");
|
|
110245
|
+
}
|
|
110192
110246
|
const initResult = await sandbox.execute(`cd ${SANDBOX_PW_DIR} && npm init -y --silent 2>/dev/null`, { timeout: 30 });
|
|
110193
110247
|
if (!initResult.success) {
|
|
110194
110248
|
throw new Error(`Failed to init npm project in sandbox: ${initResult.stderr || initResult.stdout}`);
|
|
110195
110249
|
}
|
|
110196
|
-
const
|
|
110197
|
-
const installResult = await sandbox.execute(npmInstallCmd, { timeout: 300 });
|
|
110250
|
+
const installResult = await sandbox.execute(`cd ${SANDBOX_PW_DIR} && npm install camoufox-js@0.11.1 playwright-core@1.53.1 2>&1`, { timeout: 300 });
|
|
110198
110251
|
if (!installResult.success) {
|
|
110199
|
-
throw new Error(`Failed to install
|
|
110252
|
+
throw new Error(`Failed to install camoufox-js in sandbox: ${installResult.stderr || installResult.stdout}`);
|
|
110200
110253
|
}
|
|
110201
|
-
|
|
110202
|
-
|
|
110203
|
-
|
|
110204
|
-
|
|
110205
|
-
|
|
110206
|
-
|
|
110207
|
-
await sandbox.execute(`
|
|
110208
|
-
|
|
110209
|
-
|
|
110210
|
-
|
|
110211
|
-
|
|
110212
|
-
break;
|
|
110213
|
-
if (attempt < 3) {
|
|
110214
|
-
await new Promise((r) => setTimeout(r, 3000));
|
|
110215
|
-
}
|
|
110216
|
-
}
|
|
110217
|
-
if (!browserResult.success) {
|
|
110218
|
-
throw new Error(`Failed to install Chromium in sandbox: ${browserResult.stderr || browserResult.stdout}`);
|
|
110254
|
+
const depsResult = await sandbox.execute(`rm -f /etc/apt/sources.list.d/yarn.list /etc/apt/sources.list.d/yarn.sources 2>/dev/null; cd ${SANDBOX_PW_DIR} && npx playwright@1.53.1 install-deps firefox 2>&1`, { timeout: 300 });
|
|
110255
|
+
if (!depsResult.success) {
|
|
110256
|
+
throw new Error(`Failed to install Firefox system deps in sandbox: ${depsResult.stderr || depsResult.stdout}`);
|
|
110257
|
+
}
|
|
110258
|
+
let fetchResult;
|
|
110259
|
+
for (let attempt = 1;attempt <= 3; attempt++) {
|
|
110260
|
+
fetchResult = await sandbox.execute(`cd ${SANDBOX_PW_DIR} && node ./node_modules/camoufox-js/dist/__main__.js fetch 2>&1`, { timeout: 300 });
|
|
110261
|
+
if (fetchResult.success)
|
|
110262
|
+
break;
|
|
110263
|
+
if (attempt < 3) {
|
|
110264
|
+
await new Promise((r) => setTimeout(r, 3000));
|
|
110219
110265
|
}
|
|
110220
110266
|
}
|
|
110267
|
+
if (!fetchResult.success) {
|
|
110268
|
+
throw new Error(`Failed to fetch Camoufox in sandbox: ${fetchResult.stderr || fetchResult.stdout}`);
|
|
110269
|
+
}
|
|
110221
110270
|
}
|
|
110222
110271
|
async function ensureSandboxPlaywright(sandbox) {
|
|
110223
110272
|
let cached = installationCache.get(sandbox);
|
|
@@ -110238,42 +110287,59 @@ async function ensureSandboxPlaywright(sandbox) {
|
|
|
110238
110287
|
}
|
|
110239
110288
|
}
|
|
110240
110289
|
async function ensureSandboxBrowser(sandbox) {
|
|
110241
|
-
await sandbox.execute(`mkdir -p ${SANDBOX_EVIDENCE_DIR} /tmp/pw-user-data`, {
|
|
110242
|
-
timeout: 5
|
|
110243
|
-
});
|
|
110290
|
+
await sandbox.execute(`rm -rf /tmp/pw-user-data ${SANDBOX_CAMOU_CACHE}; mkdir -p ${SANDBOX_EVIDENCE_DIR} /tmp/pw-user-data`, { timeout: 5 });
|
|
110244
110291
|
}
|
|
110245
110292
|
async function ensureSandboxReady(sandbox) {
|
|
110246
110293
|
await ensureSandboxPlaywright(sandbox);
|
|
110247
|
-
|
|
110294
|
+
let cached = browserSetupCache.get(sandbox);
|
|
110295
|
+
if (!cached) {
|
|
110296
|
+
cached = ensureSandboxBrowser(sandbox);
|
|
110297
|
+
browserSetupCache.set(sandbox, cached);
|
|
110298
|
+
try {
|
|
110299
|
+
await cached;
|
|
110300
|
+
} catch (error) {
|
|
110301
|
+
browserSetupCache.delete(sandbox);
|
|
110302
|
+
throw error;
|
|
110303
|
+
}
|
|
110304
|
+
} else {
|
|
110305
|
+
await cached;
|
|
110306
|
+
}
|
|
110248
110307
|
}
|
|
110249
110308
|
async function runPlaywrightScript(sandbox, body, timeout = 60, extraHttpHeaders) {
|
|
110250
110309
|
const headersJson = extraHttpHeaders && Object.keys(extraHttpHeaders).length > 0 ? JSON.stringify(extraHttpHeaders) : "null";
|
|
110251
110310
|
const script = `
|
|
110252
|
-
const {
|
|
110311
|
+
const { firefox } = require('playwright-core');
|
|
110253
110312
|
const fs = require('fs');
|
|
110254
110313
|
|
|
110255
110314
|
(async () => {
|
|
110315
|
+
const { launchOptions } = await import('camoufox-js');
|
|
110256
110316
|
function resolve(value) {
|
|
110257
110317
|
process.stdout.write('${RESULT_START}' + JSON.stringify(value) + '${RESULT_END}');
|
|
110258
110318
|
}
|
|
110259
110319
|
|
|
110260
|
-
// Prefer system Chromium (Alpine apk install) over Playwright's bundled binary.
|
|
110261
|
-
let executablePath;
|
|
110262
|
-
for (const p of ['/usr/bin/chromium-browser', '/usr/bin/chromium']) {
|
|
110263
|
-
try { fs.accessSync(p, fs.constants.X_OK); executablePath = p; break; } catch {}
|
|
110264
|
-
}
|
|
110265
|
-
|
|
110266
110320
|
// Resolved per script invocation so /headers mutations take effect
|
|
110267
110321
|
// on the next browser tool call.
|
|
110268
110322
|
const __extraHeaders = ${headersJson};
|
|
110269
110323
|
|
|
110324
|
+
// Use the sandbox's virtual display if one is present — Camoufox is far less
|
|
110325
|
+
// detectable headful. Falls back to plain headless, which is still fully
|
|
110326
|
+
// fingerprint-spoofed (just a weaker stealth posture, never vanilla Chromium).
|
|
110327
|
+
const __headless = process.env.DISPLAY ? false : true;
|
|
110328
|
+
// Resolve Camoufox options once per sandbox session and cache to disk so
|
|
110329
|
+
// every tool call presents the same fingerprint on the shared profile dir.
|
|
110330
|
+
let __camou;
|
|
110331
|
+
try {
|
|
110332
|
+
__camou = JSON.parse(fs.readFileSync('${SANDBOX_CAMOU_CACHE}', 'utf-8'));
|
|
110333
|
+
} catch {
|
|
110334
|
+
__camou = await launchOptions({ ...${JSON.stringify(CAMOUFOX_OPTIONS)}, headless: __headless });
|
|
110335
|
+
fs.writeFileSync('${SANDBOX_CAMOU_CACHE}', JSON.stringify(__camou));
|
|
110336
|
+
}
|
|
110337
|
+
|
|
110270
110338
|
let context;
|
|
110271
110339
|
const __consoleMessages = [];
|
|
110272
110340
|
try {
|
|
110273
|
-
context = await
|
|
110274
|
-
|
|
110275
|
-
...(executablePath ? { executablePath } : {}),
|
|
110276
|
-
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-gpu'],
|
|
110341
|
+
context = await firefox.launchPersistentContext('/tmp/pw-user-data', {
|
|
110342
|
+
...__camou,
|
|
110277
110343
|
...(__extraHeaders ? { extraHTTPHeaders: __extraHeaders } : {}),
|
|
110278
110344
|
});
|
|
110279
110345
|
const pages = context.pages();
|
|
@@ -110363,7 +110429,7 @@ var BrowserGetCookiesInput2 = exports_external.object({
|
|
|
110363
110429
|
});
|
|
110364
110430
|
function createSandboxBrowserTools(ctx) {
|
|
110365
110431
|
const sandbox = ctx.sandbox;
|
|
110366
|
-
const evidenceDir =
|
|
110432
|
+
const evidenceDir = join5(ctx.session.rootPath, "evidence");
|
|
110367
110433
|
const targetUrl = ctx.target ?? "";
|
|
110368
110434
|
if (!existsSync3(evidenceDir)) {
|
|
110369
110435
|
mkdirSync2(evidenceDir, { recursive: true });
|
|
@@ -110375,9 +110441,13 @@ function createSandboxBrowserTools(ctx) {
|
|
|
110375
110441
|
}
|
|
110376
110442
|
return setupPromise;
|
|
110377
110443
|
}
|
|
110444
|
+
let scriptQueue = Promise.resolve();
|
|
110378
110445
|
function runScript(body, timeout = 60) {
|
|
110379
110446
|
const resolved = targetUrl ? resolveEffectiveHeaders(resolverSessionFromCtx(ctx), targetUrl) : ctx.session.config?.headers;
|
|
110380
|
-
|
|
110447
|
+
const headers = stripBrowserManagedHeaders(resolved);
|
|
110448
|
+
const next = scriptQueue.then(() => runPlaywrightScript(sandbox, body, timeout, headers));
|
|
110449
|
+
scriptQueue = next.then(() => {}, () => {});
|
|
110450
|
+
return next;
|
|
110381
110451
|
}
|
|
110382
110452
|
const browser_navigate = tool({
|
|
110383
110453
|
description: `Navigate the browser to a URL to load and render a page.
|
|
@@ -110428,8 +110498,8 @@ Use this to document:
|
|
|
110428
110498
|
resolve({ success: true, data: b64, sandboxPath: ${JSON.stringify(sandboxPath)} });
|
|
110429
110499
|
`, 30);
|
|
110430
110500
|
if (result.success && result.data) {
|
|
110431
|
-
const localPath =
|
|
110432
|
-
const dir =
|
|
110501
|
+
const localPath = join5(evidenceDir, screenshotFilename);
|
|
110502
|
+
const dir = dirname3(localPath);
|
|
110433
110503
|
if (!existsSync3(dir)) {
|
|
110434
110504
|
mkdirSync2(dir, { recursive: true });
|
|
110435
110505
|
}
|
|
@@ -110806,7 +110876,7 @@ The returned cookies can be formatted as a Cookie header for use with http_reque
|
|
|
110806
110876
|
// src/core/agents/offSecAgent/tools/browserTools.ts
|
|
110807
110877
|
init_dist();
|
|
110808
110878
|
init_zod();
|
|
110809
|
-
import { join as
|
|
110879
|
+
import { join as join6 } from "path";
|
|
110810
110880
|
var BROWSER_TOOL_NAMES = [
|
|
110811
110881
|
"browser_navigate",
|
|
110812
110882
|
"browser_snapshot",
|
|
@@ -110818,7 +110888,7 @@ var BROWSER_TOOL_NAMES = [
|
|
|
110818
110888
|
"browser_get_cookies"
|
|
110819
110889
|
];
|
|
110820
110890
|
function createBrowserToolset(ctx) {
|
|
110821
|
-
const tools = ctx.sandbox ? createSandboxBrowserTools(ctx) : createBrowserTools(ctx.target ?? "",
|
|
110891
|
+
const tools = ctx.sandbox ? createSandboxBrowserTools(ctx) : createBrowserTools(ctx.target ?? "", join6(ctx.session.rootPath, "evidence"), "operator", undefined, ctx.abortSignal, undefined, undefined, undefined, ctx.browserSession);
|
|
110822
110892
|
if (!ctx.credentialManager) {
|
|
110823
110893
|
return tools;
|
|
110824
110894
|
}
|
|
@@ -110944,7 +111014,7 @@ init_zod();
|
|
|
110944
111014
|
init_structured();
|
|
110945
111015
|
init_lazyLogger();
|
|
110946
111016
|
import { existsSync as existsSync4, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
110947
|
-
import { join as
|
|
111017
|
+
import { join as join7 } from "path";
|
|
110948
111018
|
var log = scopedLogger(() => createLogger("complete_authentication"));
|
|
110949
111019
|
var AUTH_DIR = "auth";
|
|
110950
111020
|
var AUTH_DATA_FILENAME = "auth-data.json";
|
|
@@ -110988,11 +111058,11 @@ This tool marks the end of the authentication flow.`,
|
|
|
110988
111058
|
log.info(`Authentication complete: ${result.success ? "SUCCESS" : "FAILED"}`);
|
|
110989
111059
|
let authDataPath;
|
|
110990
111060
|
try {
|
|
110991
|
-
const authDir =
|
|
111061
|
+
const authDir = join7(ctx.session.rootPath, AUTH_DIR);
|
|
110992
111062
|
if (!existsSync4(authDir)) {
|
|
110993
111063
|
mkdirSync3(authDir, { recursive: true });
|
|
110994
111064
|
}
|
|
110995
|
-
authDataPath =
|
|
111065
|
+
authDataPath = join7(authDir, AUTH_DATA_FILENAME);
|
|
110996
111066
|
const authData = {
|
|
110997
111067
|
authenticated: result.success,
|
|
110998
111068
|
strategy: result.strategy || "unknown",
|
|
@@ -111209,7 +111279,7 @@ function crawlAuthenticated(ctx) {
|
|
|
111209
111279
|
init_dist();
|
|
111210
111280
|
init_zod();
|
|
111211
111281
|
import { writeFileSync as writeFileSync5 } from "fs";
|
|
111212
|
-
import { join as
|
|
111282
|
+
import { join as join8 } from "path";
|
|
111213
111283
|
function createAttackSurfaceReport(ctx) {
|
|
111214
111284
|
return tool({
|
|
111215
111285
|
description: `Provide attack surface analysis results to the orchestrator agent.
|
|
@@ -111235,7 +111305,7 @@ Call this at the END of your analysis with:
|
|
|
111235
111305
|
toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing")
|
|
111236
111306
|
}),
|
|
111237
111307
|
execute: async (results) => {
|
|
111238
|
-
const resultsPath =
|
|
111308
|
+
const resultsPath = join8(ctx.session.rootPath, "attack-surface-results.json");
|
|
111239
111309
|
writeFileSync5(resultsPath, JSON.stringify(results, null, 2));
|
|
111240
111310
|
return {
|
|
111241
111311
|
success: true,
|
|
@@ -111254,7 +111324,7 @@ init_structured();
|
|
|
111254
111324
|
init_lazyLogger();
|
|
111255
111325
|
import { existsSync as existsSync5 } from "fs";
|
|
111256
111326
|
import { mkdir, writeFile } from "fs/promises";
|
|
111257
|
-
import { dirname as
|
|
111327
|
+
import { dirname as dirname4, isAbsolute, resolve } from "path";
|
|
111258
111328
|
var log3 = scopedLogger(() => createLogger("create_file"));
|
|
111259
111329
|
var createFileInputSchema = exports_external.object({
|
|
111260
111330
|
path: exports_external.string().describe("Absolute or relative path for the new file"),
|
|
@@ -111298,7 +111368,7 @@ async function executeLocalCreate(filePath, content, overwrite) {
|
|
|
111298
111368
|
path: filePath
|
|
111299
111369
|
};
|
|
111300
111370
|
}
|
|
111301
|
-
const dir =
|
|
111371
|
+
const dir = dirname4(filePath);
|
|
111302
111372
|
log3.debug(`local: mkdir ${dir}`);
|
|
111303
111373
|
await mkdir(dir, { recursive: true });
|
|
111304
111374
|
log3.debug(`local: mkdir done, writing ${content.length} bytes`);
|
|
@@ -111332,7 +111402,7 @@ async function executeSandboxCreate(ctx, filePath, content, overwrite) {
|
|
|
111332
111402
|
};
|
|
111333
111403
|
}
|
|
111334
111404
|
}
|
|
111335
|
-
const dirPath =
|
|
111405
|
+
const dirPath = dirname4(filePath);
|
|
111336
111406
|
await ctx.sandbox.execute(`mkdir -p "${dirPath}"`);
|
|
111337
111407
|
const base64Content = Buffer.from(content).toString("base64");
|
|
111338
111408
|
const writeResult = await ctx.sandbox.execute(`echo "${base64Content}" | base64 -d > "${filePath}"`);
|
|
@@ -111363,16 +111433,16 @@ init_zod();
|
|
|
111363
111433
|
|
|
111364
111434
|
// src/core/tasks/index.ts
|
|
111365
111435
|
import { mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync, writeFileSync as writeFileSync6 } from "fs";
|
|
111366
|
-
import { join as
|
|
111436
|
+
import { join as join9 } from "path";
|
|
111367
111437
|
var HWM_FILENAME = "_hwm.json";
|
|
111368
111438
|
function ensureDir(dir) {
|
|
111369
111439
|
mkdirSync4(dir, { recursive: true });
|
|
111370
111440
|
}
|
|
111371
111441
|
function taskPath(tasksDir, id) {
|
|
111372
|
-
return
|
|
111442
|
+
return join9(tasksDir, `${id}.json`);
|
|
111373
111443
|
}
|
|
111374
111444
|
function hwmPath(tasksDir) {
|
|
111375
|
-
return
|
|
111445
|
+
return join9(tasksDir, HWM_FILENAME);
|
|
111376
111446
|
}
|
|
111377
111447
|
function readHighWaterMark(tasksDir) {
|
|
111378
111448
|
try {
|
|
@@ -111445,7 +111515,7 @@ function listTasks(tasksDir, filter) {
|
|
|
111445
111515
|
if (!file.endsWith(".json") || file === HWM_FILENAME)
|
|
111446
111516
|
continue;
|
|
111447
111517
|
try {
|
|
111448
|
-
const raw = readFileSync(
|
|
111518
|
+
const raw = readFileSync(join9(tasksDir, file), "utf-8");
|
|
111449
111519
|
const task = JSON.parse(raw);
|
|
111450
111520
|
if (filter?.status && task.status !== filter.status)
|
|
111451
111521
|
continue;
|
|
@@ -111543,7 +111613,7 @@ init_dist();
|
|
|
111543
111613
|
init_zod();
|
|
111544
111614
|
init_credentials();
|
|
111545
111615
|
import { writeFileSync as writeFileSync7 } from "fs";
|
|
111546
|
-
import { join as
|
|
111616
|
+
import { join as join10 } from "path";
|
|
111547
111617
|
init_structured();
|
|
111548
111618
|
init_lazyLogger();
|
|
111549
111619
|
var log4 = scopedLogger(() => createLogger("delegate_auth"));
|
|
@@ -111709,7 +111779,7 @@ When to use delegate_to_auth_subagent vs authenticate_session:
|
|
|
111709
111779
|
if (credentials) {
|
|
111710
111780
|
ctx.session.credentialManager.addFromAuthCredentials(credentials);
|
|
111711
111781
|
}
|
|
111712
|
-
const { runAuthenticationAgent } = await import("./authentication-
|
|
111782
|
+
const { runAuthenticationAgent } = await import("./authentication-3p84dzrr.js");
|
|
111713
111783
|
const localBus = new AgentEventBus;
|
|
111714
111784
|
AgentEventBus.attachChild(localBus, ctx.eventBus, subagentId);
|
|
111715
111785
|
const result = await runAuthenticationAgent({
|
|
@@ -111728,7 +111798,7 @@ When to use delegate_to_auth_subagent vs authenticate_session:
|
|
|
111728
111798
|
parentSubagentId: ctx.subagentId
|
|
111729
111799
|
});
|
|
111730
111800
|
if (result.success) {
|
|
111731
|
-
const sessionInfoPath =
|
|
111801
|
+
const sessionInfoPath = join10(ctx.session.rootPath, "session-info.json");
|
|
111732
111802
|
const sessionInfo = {
|
|
111733
111803
|
authenticated: true,
|
|
111734
111804
|
username: username || "via_subagent",
|
|
@@ -111923,7 +111993,7 @@ function detectBarrier(bodyLower, statusCode) {
|
|
|
111923
111993
|
init_dist();
|
|
111924
111994
|
init_zod();
|
|
111925
111995
|
import { existsSync as existsSync6, mkdirSync as mkdirSync5, writeFileSync as writeFileSync8 } from "fs";
|
|
111926
|
-
import { join as
|
|
111996
|
+
import { join as join11 } from "path";
|
|
111927
111997
|
function sanitizeName(name) {
|
|
111928
111998
|
return name.toLowerCase().replace(/[^a-z0-9-_.]/g, "_");
|
|
111929
111999
|
}
|
|
@@ -111962,7 +112032,7 @@ function validateDomainUrl(value) {
|
|
|
111962
112032
|
}
|
|
111963
112033
|
}
|
|
111964
112034
|
function documentApp(ctx) {
|
|
111965
|
-
const baseAppsPath =
|
|
112035
|
+
const baseAppsPath = join11(ctx.session.rootPath, "apps");
|
|
111966
112036
|
return tool({
|
|
111967
112037
|
description: `Document a discovered application during attack surface analysis.
|
|
111968
112038
|
|
|
@@ -112015,7 +112085,7 @@ Each application creates a JSON file in the apps directory for tracking and anal
|
|
|
112015
112085
|
const sanitizedName = sanitizeName(input.appName);
|
|
112016
112086
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
112017
112087
|
const filename = `app_${sanitizedName}_${timestamp}.json`;
|
|
112018
|
-
const filepath =
|
|
112088
|
+
const filepath = join11(baseAppsPath, filename);
|
|
112019
112089
|
const appRecord = {
|
|
112020
112090
|
...input,
|
|
112021
112091
|
discoveredAt: new Date().toISOString(),
|
|
@@ -112039,7 +112109,7 @@ Each application creates a JSON file in the apps directory for tracking and anal
|
|
|
112039
112109
|
init_dist();
|
|
112040
112110
|
init_zod();
|
|
112041
112111
|
import { existsSync as existsSync7, mkdirSync as mkdirSync6, writeFileSync as writeFileSync9 } from "fs";
|
|
112042
|
-
import { join as
|
|
112112
|
+
import { join as join12 } from "path";
|
|
112043
112113
|
|
|
112044
112114
|
// src/core/agents/specialized/attackSurface/blackboxRiskScoring.ts
|
|
112045
112115
|
var RISK_LEVEL_BASE_SCORE = {
|
|
@@ -112389,7 +112459,7 @@ async function generateThreatModelForEndpoint(ctx, input) {
|
|
|
112389
112459
|
return threatModelLimiter(async () => {
|
|
112390
112460
|
if (ctx.abortSignal?.aborted)
|
|
112391
112461
|
return null;
|
|
112392
|
-
const { CodeAgent } = await import("./agent-
|
|
112462
|
+
const { CodeAgent } = await import("./agent-ssm6x6qs.js");
|
|
112393
112463
|
const subagentId = `threat-model-${sanitize(input.appName)}-${sanitize(input.routePath)}`;
|
|
112394
112464
|
ctx.eventBus?.emit("subagent-spawn", {
|
|
112395
112465
|
subagentId,
|
|
@@ -112697,7 +112767,7 @@ var documentEndpointInputSchema = exports_external.object({
|
|
|
112697
112767
|
toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing")
|
|
112698
112768
|
});
|
|
112699
112769
|
function documentEndpoint(ctx) {
|
|
112700
|
-
const baseAssetsPath =
|
|
112770
|
+
const baseAssetsPath = join12(ctx.session.rootPath, "assets");
|
|
112701
112771
|
return tool({
|
|
112702
112772
|
description: `Document a discovered endpoint during attack surface analysis.
|
|
112703
112773
|
|
|
@@ -112743,14 +112813,14 @@ Each endpoint creates a JSON file in the assets directory for tracking and analy
|
|
|
112743
112813
|
message: `routePath "${input.routePath}" is a full URL. The domain is already stored on the parent application. ` + `Use a path or access pattern instead (e.g. "/api/users", "/{objectKey}?X-Amz-Signature={sig}", "arn:aws:s3:::bucket-name").`
|
|
112744
112814
|
};
|
|
112745
112815
|
}
|
|
112746
|
-
const targetDir =
|
|
112816
|
+
const targetDir = join12(baseAssetsPath, sanitizeName2(input.appName));
|
|
112747
112817
|
if (!existsSync7(targetDir)) {
|
|
112748
112818
|
mkdirSync6(targetDir, { recursive: true });
|
|
112749
112819
|
}
|
|
112750
112820
|
const sanitizedPath = sanitizeName2(input.routePath);
|
|
112751
112821
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
112752
112822
|
const filename = `asset_${sanitizedPath}_${timestamp}.json`;
|
|
112753
|
-
const filepath =
|
|
112823
|
+
const filepath = join12(targetDir, filename);
|
|
112754
112824
|
const heuristicRiskScore = computeBlackboxRiskScore(input.riskLevel, "endpoint", {
|
|
112755
112825
|
url: input.routePath,
|
|
112756
112826
|
method: input.method,
|
|
@@ -112828,7 +112898,7 @@ import {
|
|
|
112828
112898
|
unlinkSync,
|
|
112829
112899
|
writeFileSync as writeFileSync10
|
|
112830
112900
|
} from "fs";
|
|
112831
|
-
import { join as
|
|
112901
|
+
import { join as join13 } from "path";
|
|
112832
112902
|
|
|
112833
112903
|
// src/lib/cwe/types.ts
|
|
112834
112904
|
init_zod();
|
|
@@ -114063,6 +114133,30 @@ var CVSS_SCORER_SYSTEM_PROMPT = `You are a CVSS 4.0 scoring specialist. Your tas
|
|
|
114063
114133
|
- If production-like or confirmed unintentional: **E:A**
|
|
114064
114134
|
- Severity: typically **HIGH-CRITICAL** for real bypasses, **MEDIUM** for intentional test credentials in sandbox
|
|
114065
114135
|
|
|
114136
|
+
### Denial of Service / Resource Exhaustion (unbounded input, algorithmic complexity, amplification)
|
|
114137
|
+
- Typically: **AV:N, AC:L, AT:N, PR** varies (often **L** for authenticated endpoints), **UI:N**
|
|
114138
|
+
- **VC:N, VI:N** — DoS has no confidentiality/integrity impact unless separately demonstrated
|
|
114139
|
+
- **VA** must reflect what the evidence actually proves, not the worst case it implies:
|
|
114140
|
+
- **VA:L** when a single request degrades performance or ties up one worker temporarily (the typical demonstrated case). A slow response (e.g. several seconds) for one request is **VA:L**, not **VA:H**.
|
|
114141
|
+
- **VA:H** ONLY when the POC demonstrates a *sustained, service-wide* outage — e.g. proven worker-pool exhaustion at realistic concurrency, or the service staying unavailable to other users. Extrapolating "5-10 concurrent requests would exhaust the pool" is theoretical and does NOT justify **VA:H** unless the POC actually showed it.
|
|
114142
|
+
- **E:P** when only the resource-consumption gap was demonstrated; **E:A** only if an actual outage was produced and observed during testing.
|
|
114143
|
+
- Severity range: typically **LOW-MEDIUM**. Reserve **HIGH** for a demonstrated full outage with no easy mitigation.
|
|
114144
|
+
|
|
114145
|
+
### OAuth Flow Weaknesses (missing PKCE, weak/predictable state, state integrity)
|
|
114146
|
+
- These findings describe a *missing or weak control* in an auth flow. The impact (account/session takeover) is only realizable when chained with a *separate* capability: an authorization-code interception path (open redirect, referrer leakage, network MITM) or a forgeable/guessable state.
|
|
114147
|
+
- **Do NOT credit full VC:H/VI:H on the vulnerable system unless the interception/forgery chain was actually demonstrated end to end.** If only the absence of PKCE (or a missing signature) was shown, the direct impact on the vulnerable system is limited → prefer **VC:L/VI:L or N** and **E:P**, with **AC:H** and/or **AT:P** to reflect the required preconditions.
|
|
114148
|
+
- If a state parameter already binds to the initiating user (e.g. a server-side userId check on return), missing PKCE/signing is largely a **defense-in-depth / best-practice** gap → **LOW** (or informational when state is also unguessable and validated).
|
|
114149
|
+
- Severity range: typically **LOW** for "missing PKCE / unsigned state" in isolation; elevate only when a working interception or CSRF-via-state-forgery chain is demonstrated.
|
|
114150
|
+
|
|
114151
|
+
## Severity Calibration Principles
|
|
114152
|
+
|
|
114153
|
+
Apply these across every vulnerability class. They override the worst-case instinct.
|
|
114154
|
+
|
|
114155
|
+
- **Score what was demonstrated, not what could theoretically follow.** The CVSS reflects the impact the POC actually proved on the target, not the maximal impact the weakness might enable in a different configuration or when chained with an undiscovered bug.
|
|
114156
|
+
- **Chained / conditional exploitation:** when realizing impact depends on a *separate, undemonstrated* vulnerability or attacker-favorable precondition (interception position, a second bug, a guessed identifier), reflect that in the exploitability metrics (**AC:H**, **AT:P**, exploit maturity **E:P/U**) and do NOT assign full **VC:H/VI:H/VA:H** to the vulnerable system. A finding whose impact is entirely contingent on a missing precondition trends **LOW**.
|
|
114157
|
+
- **Security-boundary bypass without proven sensitive exposure:** when a test shows an access-control/authorization boundary was bypassed but the data actually returned is non-sensitive or same-tenant/expected-visible, score the *demonstrated* confidentiality impact (often **VC:L** or **VC:N**), not the boundary's theoretical worst case. Note explicitly in the reasoning what data was (and was not) exposed.
|
|
114158
|
+
- **Cross-tenant vs same-tenant matters:** confirmed cross-tenant/cross-user exposure of private data justifies **VC:H**; same-tenant data the identity could plausibly already see does not. If tenancy is unproven, say so and score conservatively.
|
|
114159
|
+
|
|
114066
114160
|
## Analysis Instructions
|
|
114067
114161
|
|
|
114068
114162
|
1. Read the finding description and evidence carefully
|
|
@@ -114070,8 +114164,8 @@ var CVSS_SCORER_SYSTEM_PROMPT = `You are a CVSS 4.0 scoring specialist. Your tas
|
|
|
114070
114164
|
3. Assess complexity based on whether special conditions were needed
|
|
114071
114165
|
4. Determine privileges based on authentication requirements
|
|
114072
114166
|
5. Evaluate user interaction based on exploit mechanics
|
|
114073
|
-
6. Assess impact on both the vulnerable system AND potential subsequent systems
|
|
114074
|
-
7.
|
|
114167
|
+
6. Assess impact on both the vulnerable system AND potential subsequent systems — score what the evidence proves, not the worst case it implies (see Severity Calibration Principles)
|
|
114168
|
+
7. Exploit Maturity (E): use **A (Attacked)** only when the POC demonstrated the actual security impact (data accessed, outage produced, session taken over). When the POC only proved the *gap* exists — a missing control, a slow response, a boundary bypass without confirmed sensitive exposure — use **P (POC)**. Do not default to **A** merely because a script ran and exited 0.
|
|
114075
114169
|
|
|
114076
114170
|
Always provide brief reasoning explaining your key decisions.
|
|
114077
114171
|
|
|
@@ -114103,6 +114197,8 @@ In addition to CVSS metrics, assign one or more CWE identifiers to the finding.
|
|
|
114103
114197
|
| Hardcoded Credentials | CWE-798 | CWE-259 (Hard-coded Password), CWE-321 (Hard-coded Crypto Key) |
|
|
114104
114198
|
| Captcha Bypass | CWE-804 | CWE-837 (Improper Enforcement of Single Access) |
|
|
114105
114199
|
| Missing Security Headers | CWE-1021 | CWE-693 (Protection Mechanism Failure), CWE-16 (Configuration) |
|
|
114200
|
+
| Denial of Service / Resource Exhaustion | CWE-400 | CWE-770 (Allocation Without Limits), CWE-1333 (Inefficient Regex) |
|
|
114201
|
+
| OAuth Flow Weakness (missing PKCE, weak state) | CWE-352 | CWE-345 (Insufficient Verification of Authenticity), CWE-1275 (Sensitive Cookie Weak Attributes) |
|
|
114106
114202
|
|
|
114107
114203
|
### CWE Assignment Rules
|
|
114108
114204
|
|
|
@@ -114239,7 +114335,7 @@ init_lazyLogger();
|
|
|
114239
114335
|
var log6 = scopedLogger(() => createLogger("FindingJudge"));
|
|
114240
114336
|
async function judgeFinding(input, ctx) {
|
|
114241
114337
|
try {
|
|
114242
|
-
const { FindingJudgeAgent } = await import("./agent-
|
|
114338
|
+
const { FindingJudgeAgent } = await import("./agent-1zfxfgfr.js");
|
|
114243
114339
|
const agent = new FindingJudgeAgent({
|
|
114244
114340
|
finding: input,
|
|
114245
114341
|
model: ctx.model,
|
|
@@ -114529,14 +114625,14 @@ CRITICAL RULES — READ BEFORE CALLING:
|
|
|
114529
114625
|
description: `POC execution output for ${filename}`
|
|
114530
114626
|
});
|
|
114531
114627
|
const timestamp = new Date().toISOString();
|
|
114532
|
-
const outputDir = isVulnerability ? session.findingsPath :
|
|
114628
|
+
const outputDir = isVulnerability ? session.findingsPath : join13(session.rootPath, "informational");
|
|
114533
114629
|
if (!isVulnerability) {
|
|
114534
114630
|
mkdirSync7(outputDir, { recursive: true });
|
|
114535
114631
|
}
|
|
114536
114632
|
let evidenceForPrompt = materializedEvidence;
|
|
114537
114633
|
if (materializedEvidence.length > EVIDENCE_FILE_THRESHOLD) {
|
|
114538
114634
|
const evidenceFilename = `${timestamp.split("T")[0]}-${slugify2(input.title, 40)}-evidence.txt`;
|
|
114539
|
-
const evidenceFilePath =
|
|
114635
|
+
const evidenceFilePath = join13(outputDir, evidenceFilename);
|
|
114540
114636
|
writeFileSync10(evidenceFilePath, materializedEvidence);
|
|
114541
114637
|
evidenceForPrompt = materializedEvidence.substring(0, EVIDENCE_FILE_THRESHOLD) + `
|
|
114542
114638
|
... [truncated — full output saved to ${evidenceFilename}]`;
|
|
@@ -114678,8 +114774,8 @@ CRITICAL RULES — READ BEFORE CALLING:
|
|
|
114678
114774
|
const findingId = `${timestamp.split("T")[0]}-${slugify2(finding.title, 50)}`;
|
|
114679
114775
|
const jsonFilename = `${findingId}.json`;
|
|
114680
114776
|
const mdFilename = `${findingId}.md`;
|
|
114681
|
-
const jsonPath =
|
|
114682
|
-
const mdPath =
|
|
114777
|
+
const jsonPath = join13(outputDir, jsonFilename);
|
|
114778
|
+
const mdPath = join13(outputDir, mdFilename);
|
|
114683
114779
|
try {
|
|
114684
114780
|
writeFileSync10(jsonPath, JSON.stringify(findingWithMeta, null, 2));
|
|
114685
114781
|
const cvssSection = cvssWarning ? `## CVSS 4.0 Assessment
|
|
@@ -114762,7 +114858,7 @@ ${finding.references}` : ""}
|
|
|
114762
114858
|
`;
|
|
114763
114859
|
writeFileSync10(mdPath, markdown);
|
|
114764
114860
|
if (isVulnerability) {
|
|
114765
|
-
const summaryPath =
|
|
114861
|
+
const summaryPath = join13(session.rootPath, "findings-summary.md");
|
|
114766
114862
|
const cweTag = cvssResult.cwes?.length ? ` (${cvssResult.cwes.map((c) => c.id).join(", ")})` : "";
|
|
114767
114863
|
const cvssTag = cvssWarning ? "(estimated)" : `(CVSS ${cvssResult.score})`;
|
|
114768
114864
|
const summaryEntry = `- [${finding.severity}] ${cvssTag}${cweTag} ${finding.title} - \`findings/${mdFilename}\`
|
|
@@ -114820,7 +114916,7 @@ async function executeLocalPoc(ctx, input) {
|
|
|
114820
114916
|
mkdirSync7(pocsPath, { recursive: true });
|
|
114821
114917
|
}
|
|
114822
114918
|
const { filename, pocContent } = preparePoc(input);
|
|
114823
|
-
const pocPath =
|
|
114919
|
+
const pocPath = join13(pocsPath, filename);
|
|
114824
114920
|
writeFileSync10(pocPath, pocContent);
|
|
114825
114921
|
chmodSync(pocPath, 493);
|
|
114826
114922
|
const { stdout, stderr, exitCode } = await runScript(POC_RUNNERS[input.pocType], pocPath, 60000, ctx.abortSignal);
|
|
@@ -114838,7 +114934,7 @@ async function executeSandboxPoc(ctx, input) {
|
|
|
114838
114934
|
if (!existsSync8(localPocsPath)) {
|
|
114839
114935
|
mkdirSync7(localPocsPath, { recursive: true });
|
|
114840
114936
|
}
|
|
114841
|
-
const localPocPath =
|
|
114937
|
+
const localPocPath = join13(localPocsPath, filename);
|
|
114842
114938
|
writeFileSync10(localPocPath, pocContent);
|
|
114843
114939
|
const sandboxPocPath = `/tmp/pocs/${filename}`;
|
|
114844
114940
|
const base64Content = Buffer.from(pocContent).toString("base64");
|
|
@@ -114871,10 +114967,10 @@ POC file has been deleted.`,
|
|
|
114871
114967
|
}
|
|
114872
114968
|
function cleanupPocFiles(ctx, filename) {
|
|
114873
114969
|
try {
|
|
114874
|
-
unlinkSync(
|
|
114970
|
+
unlinkSync(join13(ctx.session.pocsPath, filename));
|
|
114875
114971
|
} catch {}
|
|
114876
114972
|
try {
|
|
114877
|
-
unlinkSync(
|
|
114973
|
+
unlinkSync(join13(ctx.session.pocsPath, `${filename}.output.json`));
|
|
114878
114974
|
} catch {}
|
|
114879
114975
|
}
|
|
114880
114976
|
function sanitizeFilename(str) {
|
|
@@ -114935,7 +115031,7 @@ ${commentChar} Created: ${new Date().toISOString()}
|
|
|
114935
115031
|
}
|
|
114936
115032
|
function writePocOutputSidecar(pocsPath, filename, stdout, stderr, exitCode, description) {
|
|
114937
115033
|
try {
|
|
114938
|
-
const outputPath =
|
|
115034
|
+
const outputPath = join13(pocsPath, `${filename}.output.json`);
|
|
114939
115035
|
writeFileSync10(outputPath, JSON.stringify({
|
|
114940
115036
|
stdout,
|
|
114941
115037
|
stderr,
|
|
@@ -118250,7 +118346,7 @@ var SEND_EMAIL_TOOL_NAME = "send_email";
|
|
|
118250
118346
|
init_dist();
|
|
118251
118347
|
init_zod();
|
|
118252
118348
|
import { existsSync as existsSync9, mkdirSync as mkdirSync8, writeFileSync as writeFileSync11 } from "fs";
|
|
118253
|
-
import { join as
|
|
118349
|
+
import { join as join14 } from "path";
|
|
118254
118350
|
var MAX_INLINE = 50000;
|
|
118255
118351
|
var MS_TIMEOUT_THRESHOLD = 1e4;
|
|
118256
118352
|
var executeCommandInputSchema = exports_external.object({
|
|
@@ -118272,13 +118368,13 @@ function maybeSaveFullOutput(raw, ctx) {
|
|
|
118272
118368
|
if (raw.length <= MAX_INLINE) {
|
|
118273
118369
|
return { text: raw || "(no output)" };
|
|
118274
118370
|
}
|
|
118275
|
-
const outputDir =
|
|
118371
|
+
const outputDir = join14(ctx.session.logsPath, "cmd-output");
|
|
118276
118372
|
if (!existsSync9(outputDir)) {
|
|
118277
118373
|
mkdirSync8(outputDir, { recursive: true });
|
|
118278
118374
|
}
|
|
118279
118375
|
const ts = new Date().toISOString().replace(/[:.]/g, "-");
|
|
118280
118376
|
const filename = `output-${ts}.txt`;
|
|
118281
|
-
const filePath =
|
|
118377
|
+
const filePath = join14(outputDir, filename);
|
|
118282
118378
|
try {
|
|
118283
118379
|
writeFileSync11(filePath, raw);
|
|
118284
118380
|
} catch {
|
|
@@ -118765,7 +118861,7 @@ search with flags or a more specific directory if results are truncated.`,
|
|
|
118765
118861
|
init_dist();
|
|
118766
118862
|
init_zod();
|
|
118767
118863
|
import { existsSync as existsSync10, mkdirSync as mkdirSync9, writeFileSync as writeFileSync12 } from "fs";
|
|
118768
|
-
import { join as
|
|
118864
|
+
import { join as join15 } from "path";
|
|
118769
118865
|
var MAX_INLINE_BODY = 5000;
|
|
118770
118866
|
var httpRequestInputSchema = exports_external.object({
|
|
118771
118867
|
url: exports_external.string().describe("The URL to request"),
|
|
@@ -118779,13 +118875,13 @@ var httpRequestInputSchema = exports_external.object({
|
|
|
118779
118875
|
function maybeSaveBody(body, ctx) {
|
|
118780
118876
|
if (body.length <= MAX_INLINE_BODY)
|
|
118781
118877
|
return { text: body };
|
|
118782
|
-
const outputDir =
|
|
118878
|
+
const outputDir = join15(ctx.session.logsPath, "http-responses");
|
|
118783
118879
|
if (!existsSync10(outputDir)) {
|
|
118784
118880
|
mkdirSync9(outputDir, { recursive: true });
|
|
118785
118881
|
}
|
|
118786
118882
|
const ts = new Date().toISOString().replace(/[:.]/g, "-");
|
|
118787
118883
|
const filename = `response-${ts}.txt`;
|
|
118788
|
-
const filePath =
|
|
118884
|
+
const filePath = join15(outputDir, filename);
|
|
118789
118885
|
try {
|
|
118790
118886
|
writeFileSync12(filePath, body);
|
|
118791
118887
|
} catch {
|
|
@@ -119024,7 +119120,7 @@ async function executeSandboxHttpRequest(ctx, opts) {
|
|
|
119024
119120
|
init_dist();
|
|
119025
119121
|
init_zod();
|
|
119026
119122
|
import { readdir, stat } from "fs/promises";
|
|
119027
|
-
import { isAbsolute as isAbsolute2, join as
|
|
119123
|
+
import { isAbsolute as isAbsolute2, join as join16, relative, resolve as resolve2 } from "path";
|
|
119028
119124
|
var listFilesInputSchema = exports_external.object({
|
|
119029
119125
|
directory: exports_external.string().optional().describe("Absolute or relative path to the directory to list (defaults to current working directory)"),
|
|
119030
119126
|
recursive: exports_external.boolean().optional().describe("If true, list files recursively (default: false)"),
|
|
@@ -119044,7 +119140,7 @@ async function listRecursive(dir, maxEntries) {
|
|
|
119044
119140
|
}
|
|
119045
119141
|
for (const entry of entries) {
|
|
119046
119142
|
total++;
|
|
119047
|
-
const fullPath =
|
|
119143
|
+
const fullPath = join16(current, entry.name);
|
|
119048
119144
|
if (entry.isDirectory()) {
|
|
119049
119145
|
if (results.length < maxEntries)
|
|
119050
119146
|
results.push(`${fullPath}/`);
|
|
@@ -119107,7 +119203,7 @@ Each directory entry is suffixed with "/" for easy identification.`,
|
|
|
119107
119203
|
}
|
|
119108
119204
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
119109
119205
|
const fullPaths = entries.map((e) => {
|
|
119110
|
-
const name =
|
|
119206
|
+
const name = join16(dir, e.name);
|
|
119111
119207
|
return e.isDirectory() ? `${name}/` : name;
|
|
119112
119208
|
});
|
|
119113
119209
|
const capped = fullPaths.slice(0, MAX_NON_RECURSIVE);
|
|
@@ -119249,9 +119345,9 @@ import {
|
|
|
119249
119345
|
unlinkSync as unlinkSync2
|
|
119250
119346
|
} from "fs";
|
|
119251
119347
|
import { tmpdir } from "os";
|
|
119252
|
-
import { join as
|
|
119348
|
+
import { join as join17 } from "path";
|
|
119253
119349
|
var MAX_BUFFER = 5000000;
|
|
119254
|
-
var APEX_TMP_ROOT =
|
|
119350
|
+
var APEX_TMP_ROOT = join17(tmpdir(), `apex-shell-${process.pid}`);
|
|
119255
119351
|
try {
|
|
119256
119352
|
mkdirSync10(APEX_TMP_ROOT, { recursive: true });
|
|
119257
119353
|
} catch {}
|
|
@@ -119503,8 +119599,8 @@ class PersistentShell {
|
|
|
119503
119599
|
const marker = `__APEX_${nonceHex}__`;
|
|
119504
119600
|
const exitMarkerPrefix = `${marker}_EXIT_`;
|
|
119505
119601
|
const cutoverMarker = `${marker}_CUTOVER`;
|
|
119506
|
-
const outPath =
|
|
119507
|
-
const errPath =
|
|
119602
|
+
const outPath = join17(APEX_TMP_ROOT, `${nonceHex}.out`);
|
|
119603
|
+
const errPath = join17(APEX_TMP_ROOT, `${nonceHex}.err`);
|
|
119508
119604
|
const pending = {
|
|
119509
119605
|
streamedStdout: "",
|
|
119510
119606
|
authoritativeStdout: "",
|
|
@@ -119923,7 +120019,7 @@ Returns discovered endpoints and recommended login approach.`,
|
|
|
119923
120019
|
init_dist();
|
|
119924
120020
|
init_zod();
|
|
119925
120021
|
import { writeFileSync as writeFileSync13 } from "fs";
|
|
119926
|
-
import { join as
|
|
120022
|
+
import { join as join18 } from "path";
|
|
119927
120023
|
function provideComparisonResults(ctx) {
|
|
119928
120024
|
return tool({
|
|
119929
120025
|
description: `Provide the final comparison results with matched, missed, and extra findings.
|
|
@@ -119969,7 +120065,7 @@ Results will be saved to: comparison-results.json in the session directory.`,
|
|
|
119969
120065
|
recall,
|
|
119970
120066
|
precision
|
|
119971
120067
|
};
|
|
119972
|
-
const resultsPath =
|
|
120068
|
+
const resultsPath = join18(ctx.session.rootPath, "comparison-results.json");
|
|
119973
120069
|
writeFileSync13(resultsPath, JSON.stringify(result, null, 2));
|
|
119974
120070
|
return {
|
|
119975
120071
|
success: true,
|
|
@@ -120123,7 +120219,7 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
|
|
|
120123
120219
|
});
|
|
120124
120220
|
if (cwd) {
|
|
120125
120221
|
try {
|
|
120126
|
-
const { WhiteboxAttackSurfaceAgent } = await import("./index-
|
|
120222
|
+
const { WhiteboxAttackSurfaceAgent } = await import("./index-kjky8ack.js");
|
|
120127
120223
|
const localBus = new AgentEventBus;
|
|
120128
120224
|
AgentEventBus.attachChild(localBus, ctx.eventBus, subagentId);
|
|
120129
120225
|
const agent = new WhiteboxAttackSurfaceAgent({
|
|
@@ -120173,7 +120269,7 @@ should be passed directly to spawn_pentest_swarm for deep testing.`,
|
|
|
120173
120269
|
}
|
|
120174
120270
|
}
|
|
120175
120271
|
try {
|
|
120176
|
-
const { BlackboxAttackSurfaceAgent } = await import("./blackboxAgent-
|
|
120272
|
+
const { BlackboxAttackSurfaceAgent } = await import("./blackboxAgent-dn68r23n.js");
|
|
120177
120273
|
const localBus = new AgentEventBus;
|
|
120178
120274
|
AgentEventBus.attachChild(localBus, ctx.eventBus, subagentId);
|
|
120179
120275
|
const agent = new BlackboxAttackSurfaceAgent({
|
|
@@ -120251,7 +120347,7 @@ Omit \`cwd\` for blackbox mode (live target probing only).`,
|
|
|
120251
120347
|
toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing")
|
|
120252
120348
|
}),
|
|
120253
120349
|
execute: async ({ target, cwd }) => {
|
|
120254
|
-
const { runPentestWorkflow: workflow } = await import("./pentest-
|
|
120350
|
+
const { runPentestWorkflow: workflow } = await import("./pentest-043y2x03.js");
|
|
120255
120351
|
if (!ctx.model) {
|
|
120256
120352
|
return {
|
|
120257
120353
|
success: false,
|
|
@@ -120356,11 +120452,11 @@ init_zod();
|
|
|
120356
120452
|
|
|
120357
120453
|
// src/core/whitebox/adapters.ts
|
|
120358
120454
|
import { existsSync as existsSync12 } from "node:fs";
|
|
120359
|
-
import { join as
|
|
120455
|
+
import { join as join20 } from "node:path";
|
|
120360
120456
|
|
|
120361
120457
|
// src/core/whitebox/artifacts.ts
|
|
120362
120458
|
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
|
|
120363
|
-
import { basename as basename2, join as
|
|
120459
|
+
import { basename as basename2, join as join19 } from "node:path";
|
|
120364
120460
|
|
|
120365
120461
|
// src/core/whitebox/paths.ts
|
|
120366
120462
|
import { existsSync as existsSync11, realpathSync } from "node:fs";
|
|
@@ -120421,10 +120517,10 @@ function safeName(value) {
|
|
|
120421
120517
|
return value.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/\.{2,}/g, ".").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
120422
120518
|
}
|
|
120423
120519
|
function getWhiteboxLogsDir(session) {
|
|
120424
|
-
return
|
|
120520
|
+
return join19(session.logsPath, "whitebox");
|
|
120425
120521
|
}
|
|
120426
120522
|
function getWhiteboxScratchDir(session) {
|
|
120427
|
-
return
|
|
120523
|
+
return join19(session.scratchpadPath, "whitebox");
|
|
120428
120524
|
}
|
|
120429
120525
|
async function ensureWhiteboxDirs(session) {
|
|
120430
120526
|
await Promise.all([
|
|
@@ -120437,7 +120533,7 @@ async function writeWhiteboxArtifact(input) {
|
|
|
120437
120533
|
const baseDir = input.area === "scratchpad" ? getWhiteboxScratchDir(input.session) : getWhiteboxLogsDir(input.session);
|
|
120438
120534
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
120439
120535
|
const filename = `${timestamp}-${safeName(input.name)}${input.extension ?? ".txt"}`;
|
|
120440
|
-
const absolutePath =
|
|
120536
|
+
const absolutePath = join19(baseDir, filename);
|
|
120441
120537
|
await writeFile2(absolutePath, input.content, "utf-8");
|
|
120442
120538
|
const relativeRoot = input.area === "scratchpad" ? "scratchpad/whitebox" : "logs/whitebox";
|
|
120443
120539
|
return {
|
|
@@ -120679,7 +120775,7 @@ var WHITEBOX_SCAN_ADAPTERS = [
|
|
|
120679
120775
|
id: "npm-audit",
|
|
120680
120776
|
kind: "dependencies",
|
|
120681
120777
|
tool: "npm",
|
|
120682
|
-
detect: (profile) => hasTool(profile, "npm") && (profile.packageManagers.includes("npm") || existsSync12(
|
|
120778
|
+
detect: (profile) => hasTool(profile, "npm") && (profile.packageManagers.includes("npm") || existsSync12(join20(profile.rootPath, "package-lock.json"))),
|
|
120683
120779
|
buildCommand: () => ["npm", "audit", "--json"],
|
|
120684
120780
|
parseSummary: (raw) => simpleLineFindings("npm audit", raw)
|
|
120685
120781
|
},
|
|
@@ -120788,7 +120884,7 @@ ${raw.stderr}` : "");
|
|
|
120788
120884
|
// src/core/whitebox/candidates.ts
|
|
120789
120885
|
import { existsSync as existsSync13 } from "node:fs";
|
|
120790
120886
|
import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile3 } from "node:fs/promises";
|
|
120791
|
-
import { join as
|
|
120887
|
+
import { join as join21 } from "node:path";
|
|
120792
120888
|
var CANDIDATES_FILE = "candidates.json";
|
|
120793
120889
|
var writeLocks = new Map;
|
|
120794
120890
|
function withCandidateLock(session, fn) {
|
|
@@ -120815,10 +120911,10 @@ var ALLOWED_TRANSITIONS = {
|
|
|
120815
120911
|
deferred: ["hypothesis", "investigating"]
|
|
120816
120912
|
};
|
|
120817
120913
|
function candidatesDir(session) {
|
|
120818
|
-
return
|
|
120914
|
+
return join21(session.scratchpadPath, "whitebox");
|
|
120819
120915
|
}
|
|
120820
120916
|
function candidatesPath(session) {
|
|
120821
|
-
return
|
|
120917
|
+
return join21(candidatesDir(session), CANDIDATES_FILE);
|
|
120822
120918
|
}
|
|
120823
120919
|
function makeId2(title) {
|
|
120824
120920
|
const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 48);
|
|
@@ -121288,7 +121384,7 @@ import {
|
|
|
121288
121384
|
readSync as readSync2,
|
|
121289
121385
|
statSync as statSync3
|
|
121290
121386
|
} from "node:fs";
|
|
121291
|
-
import { join as
|
|
121387
|
+
import { join as join22 } from "node:path";
|
|
121292
121388
|
var MAX_JOB_LOG_INLINE = 40000;
|
|
121293
121389
|
var MAX_JOB_LOG_BYTES = 10 * 1024 * 1024;
|
|
121294
121390
|
var PRUNE_AFTER_MS = 60000;
|
|
@@ -121363,7 +121459,7 @@ function startWhiteboxJob(input) {
|
|
|
121363
121459
|
const logsDir = getWhiteboxLogsDir(input.session);
|
|
121364
121460
|
mkdirSync11(logsDir, { recursive: true });
|
|
121365
121461
|
const safeName2 = (input.name ?? "job").replace(/[^a-z0-9._-]+/gi, "-").replace(/\.{2,}/g, ".");
|
|
121366
|
-
const logPath =
|
|
121462
|
+
const logPath = join22(logsDir, `${id}-${safeName2}.log`);
|
|
121367
121463
|
const now = new Date().toISOString();
|
|
121368
121464
|
writeLog(logPath, `$ ${input.command}
|
|
121369
121465
|
|
|
@@ -121489,12 +121585,12 @@ function readWhiteboxJobLog(id, sessionId) {
|
|
|
121489
121585
|
};
|
|
121490
121586
|
}
|
|
121491
121587
|
// src/core/whitebox/repoProfile.ts
|
|
121492
|
-
import { execFile } from "node:child_process";
|
|
121588
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
121493
121589
|
import { existsSync as existsSync15, realpathSync as realpathSync2 } from "node:fs";
|
|
121494
121590
|
import { readdir as readdir2, readFile as readFile5, stat as stat2 } from "node:fs/promises";
|
|
121495
|
-
import { basename as basename3, extname as extname2, join as
|
|
121496
|
-
import { promisify } from "node:util";
|
|
121497
|
-
var
|
|
121591
|
+
import { basename as basename3, extname as extname2, join as join23, relative as relative3, resolve as resolve5 } from "node:path";
|
|
121592
|
+
import { promisify as promisify2 } from "node:util";
|
|
121593
|
+
var execFileAsync2 = promisify2(execFile2);
|
|
121498
121594
|
var MAX_PROFILE_FILES = 5000;
|
|
121499
121595
|
var LANGUAGE_BY_EXTENSION = {
|
|
121500
121596
|
".ts": "typescript",
|
|
@@ -121601,7 +121697,7 @@ async function walkFiles(rootPath) {
|
|
|
121601
121697
|
for (const entry of entries) {
|
|
121602
121698
|
if (files.length >= MAX_PROFILE_FILES)
|
|
121603
121699
|
return;
|
|
121604
|
-
const fullPath =
|
|
121700
|
+
const fullPath = join23(current, entry.name);
|
|
121605
121701
|
if (entry.isDirectory()) {
|
|
121606
121702
|
if (shouldSkipDir(entry.name))
|
|
121607
121703
|
continue;
|
|
@@ -121663,7 +121759,7 @@ function detectEntryHints(files) {
|
|
|
121663
121759
|
return hints.slice(0, 100);
|
|
121664
121760
|
}
|
|
121665
121761
|
async function readPackageScripts(rootPath) {
|
|
121666
|
-
const packageJsonPath =
|
|
121762
|
+
const packageJsonPath = join23(rootPath, "package.json");
|
|
121667
121763
|
if (!existsSync15(packageJsonPath)) {
|
|
121668
121764
|
return { buildCommands: [], testCommands: [], runCommands: [] };
|
|
121669
121765
|
}
|
|
@@ -121682,7 +121778,7 @@ async function readPackageScripts(rootPath) {
|
|
|
121682
121778
|
}
|
|
121683
121779
|
async function runGit(rootPath, args) {
|
|
121684
121780
|
try {
|
|
121685
|
-
const { stdout } = await
|
|
121781
|
+
const { stdout } = await execFileAsync2("git", args, {
|
|
121686
121782
|
cwd: rootPath,
|
|
121687
121783
|
timeout: 5000,
|
|
121688
121784
|
maxBuffer: 1024 * 1024
|
|
@@ -121695,7 +121791,7 @@ async function runGit(rootPath, args) {
|
|
|
121695
121791
|
async function detectTool(name) {
|
|
121696
121792
|
const cmd = process.platform === "win32" ? "where" : "which";
|
|
121697
121793
|
try {
|
|
121698
|
-
const { stdout } = await
|
|
121794
|
+
const { stdout } = await execFileAsync2(cmd, [name], {
|
|
121699
121795
|
timeout: 2000,
|
|
121700
121796
|
maxBuffer: 1024 * 64
|
|
121701
121797
|
});
|
|
@@ -121827,7 +121923,7 @@ Returns an array of results with the text output from each agent.`,
|
|
|
121827
121923
|
});
|
|
121828
121924
|
}
|
|
121829
121925
|
async function runSingleCodingAgent(ctx, codebasePath, objective, agentIndex, name) {
|
|
121830
|
-
const { CodeAgent } = await import("./agent-
|
|
121926
|
+
const { CodeAgent } = await import("./agent-ssm6x6qs.js");
|
|
121831
121927
|
const subagentId = `coding-agent-${agentIndex}`;
|
|
121832
121928
|
ctx.eventBus?.emit("subagent-spawn", {
|
|
121833
121929
|
subagentId,
|
|
@@ -121877,7 +121973,7 @@ init_ai();
|
|
|
121877
121973
|
init_structured();
|
|
121878
121974
|
init_lazyLogger();
|
|
121879
121975
|
import { existsSync as existsSync16, readdirSync as readdirSync3, readFileSync as readFileSync4 } from "fs";
|
|
121880
|
-
import { join as
|
|
121976
|
+
import { join as join24 } from "path";
|
|
121881
121977
|
var log9 = scopedLogger(() => createLogger("findings:registry"));
|
|
121882
121978
|
var VULN_CLASS_PATTERNS = [
|
|
121883
121979
|
[/sql\s*injection/i, "sql-injection"],
|
|
@@ -122000,6 +122096,15 @@ ${existingList}
|
|
|
122000
122096
|
|
|
122001
122097
|
Is the new finding a duplicate of any existing finding?`;
|
|
122002
122098
|
}
|
|
122099
|
+
var SEVERITY_RANK = {
|
|
122100
|
+
CRITICAL: 4,
|
|
122101
|
+
HIGH: 3,
|
|
122102
|
+
MEDIUM: 2,
|
|
122103
|
+
LOW: 1
|
|
122104
|
+
};
|
|
122105
|
+
function maxSeverity(severities) {
|
|
122106
|
+
return severities.reduce((acc, s) => SEVERITY_RANK[s] > SEVERITY_RANK[acc] ? s : acc, "LOW");
|
|
122107
|
+
}
|
|
122003
122108
|
var RootCauseGroupResultSchema = exports_external.object({
|
|
122004
122109
|
groups: exports_external.array(exports_external.object({
|
|
122005
122110
|
groupId: exports_external.string().describe("Short kebab-case identifier for the group"),
|
|
@@ -122060,7 +122165,7 @@ class FindingsRegistry {
|
|
|
122060
122165
|
log9.debug(`fromDirectory: path=${findingsPath}, jsonFiles=${files.length}`);
|
|
122061
122166
|
for (const file of files) {
|
|
122062
122167
|
try {
|
|
122063
|
-
const raw = readFileSync4(
|
|
122168
|
+
const raw = readFileSync4(join24(findingsPath, file), "utf-8");
|
|
122064
122169
|
const finding = JSON.parse(raw);
|
|
122065
122170
|
if (finding && typeof finding.title === "string" && typeof finding.endpoint === "string") {
|
|
122066
122171
|
registry.indexFinding(finding);
|
|
@@ -122204,18 +122309,32 @@ class FindingsRegistry {
|
|
|
122204
122309
|
const sanitised = [];
|
|
122205
122310
|
await new Promise((resolve6) => {
|
|
122206
122311
|
this.mutex = this.mutex.then(() => {
|
|
122312
|
+
const baseSeverities = snapshot.map((f) => f.severity);
|
|
122207
122313
|
for (const group of result.groups) {
|
|
122208
122314
|
const validIndices = group.findingIndices.filter((i) => i >= 0 && i < snapshot.length);
|
|
122209
122315
|
if (validIndices.length < 2)
|
|
122210
122316
|
continue;
|
|
122317
|
+
const normalizedSeverity = maxSeverity(validIndices.map((i) => baseSeverities[i]));
|
|
122318
|
+
const leadFindingIndex = validIndices.reduce((best, i) => {
|
|
122319
|
+
const aRank = SEVERITY_RANK[baseSeverities[i]];
|
|
122320
|
+
const bRank = SEVERITY_RANK[baseSeverities[best]];
|
|
122321
|
+
if (aRank !== bRank) {
|
|
122322
|
+
return aRank > bRank ? i : best;
|
|
122323
|
+
}
|
|
122324
|
+
return (snapshot[i].description?.length ?? 0) > (snapshot[best].description?.length ?? 0) ? i : best;
|
|
122325
|
+
}, validIndices[0]);
|
|
122211
122326
|
sanitised.push({
|
|
122212
122327
|
groupId: group.groupId,
|
|
122213
122328
|
findingIndices: validIndices,
|
|
122214
|
-
rootCause: group.rootCause
|
|
122329
|
+
rootCause: group.rootCause,
|
|
122330
|
+
normalizedSeverity,
|
|
122331
|
+
leadFindingIndex
|
|
122215
122332
|
});
|
|
122216
122333
|
for (const idx of validIndices) {
|
|
122217
122334
|
const finding = snapshot[idx];
|
|
122218
122335
|
finding.rootCauseGroup = group.groupId;
|
|
122336
|
+
finding.severity = normalizedSeverity;
|
|
122337
|
+
finding.rootCauseLead = idx === leadFindingIndex;
|
|
122219
122338
|
finding.relatedFindings = validIndices.filter((i) => i !== idx).map((i) => snapshot[i].title);
|
|
122220
122339
|
}
|
|
122221
122340
|
}
|
|
@@ -122251,13 +122370,13 @@ class FindingsRegistry {
|
|
|
122251
122370
|
|
|
122252
122371
|
// src/core/plan/index.ts
|
|
122253
122372
|
import { existsSync as existsSync17, readFileSync as readFileSync5 } from "fs";
|
|
122254
|
-
import { join as
|
|
122373
|
+
import { join as join25 } from "path";
|
|
122255
122374
|
var PLAN_FILENAME = "plan.md";
|
|
122256
122375
|
function planFilePath(sessionRootPath, subagentId) {
|
|
122257
122376
|
if (subagentId) {
|
|
122258
|
-
return
|
|
122377
|
+
return join25(sessionRootPath, "subagents", `${subagentId}-plan.md`);
|
|
122259
122378
|
}
|
|
122260
|
-
return
|
|
122379
|
+
return join25(sessionRootPath, PLAN_FILENAME);
|
|
122261
122380
|
}
|
|
122262
122381
|
function readPlan(sessionRootPath, subagentId) {
|
|
122263
122382
|
const path = planFilePath(sessionRootPath, subagentId);
|
|
@@ -122310,7 +122429,7 @@ Returns the worker's summary, objective results, and finding count — but NOT t
|
|
|
122310
122429
|
message: "spawn_pentest_agent requires a model in the tool context."
|
|
122311
122430
|
};
|
|
122312
122431
|
}
|
|
122313
|
-
const { TargetedPentestAgent } = await import("./agent-
|
|
122432
|
+
const { TargetedPentestAgent } = await import("./agent-1jp62njk.js");
|
|
122314
122433
|
const findingsRegistry = ctx.findingsRegistry ?? FindingsRegistry.fromDirectory(ctx.session.findingsPath, {
|
|
122315
122434
|
model: ctx.model,
|
|
122316
122435
|
authConfig: ctx.authConfig,
|
|
@@ -122464,7 +122583,7 @@ Pass every target you want tested — the swarm handles concurrency automaticall
|
|
|
122464
122583
|
toolCallDescription: exports_external.string().describe("A concise, human-readable description of what this tool call is doing")
|
|
122465
122584
|
}),
|
|
122466
122585
|
execute: async ({ targets }) => {
|
|
122467
|
-
const { runPentestSwarm, DEFAULT_CONCURRENCY: DEFAULT_CONCURRENCY2 } = await import("./pentest-
|
|
122586
|
+
const { runPentestSwarm, DEFAULT_CONCURRENCY: DEFAULT_CONCURRENCY2 } = await import("./pentest-043y2x03.js");
|
|
122468
122587
|
if (!ctx.model) {
|
|
122469
122588
|
return {
|
|
122470
122589
|
success: false,
|
|
@@ -123101,7 +123220,7 @@ init_zod();
|
|
|
123101
123220
|
init_structured();
|
|
123102
123221
|
import { mkdirSync as mkdirSync12 } from "fs";
|
|
123103
123222
|
import { writeFile as writeFile5 } from "fs/promises";
|
|
123104
|
-
import { dirname as
|
|
123223
|
+
import { dirname as dirname5 } from "path";
|
|
123105
123224
|
init_lazyLogger();
|
|
123106
123225
|
var log12 = scopedLogger(() => createLogger("write_plan"));
|
|
123107
123226
|
var writePlanInputSchema = exports_external.object({
|
|
@@ -123127,7 +123246,7 @@ Required plan sections:
|
|
|
123127
123246
|
execute: async ({ content }) => {
|
|
123128
123247
|
const scopeId = ctx.planSubagentId ?? ctx.subagentId;
|
|
123129
123248
|
const planPath = planFilePath(ctx.session.rootPath, scopeId);
|
|
123130
|
-
mkdirSync12(
|
|
123249
|
+
mkdirSync12(dirname5(planPath), { recursive: true });
|
|
123131
123250
|
log12.debug(`enter: contentLen=${content.length}, path=${planPath}`);
|
|
123132
123251
|
try {
|
|
123133
123252
|
await writeFile5(planPath, content, "utf-8");
|
|
@@ -124156,7 +124275,7 @@ var SKILL_TOOL_NAMES = ["read_skill"];
|
|
|
124156
124275
|
// src/core/agents/offSecAgent/trace.ts
|
|
124157
124276
|
import { createHash } from "crypto";
|
|
124158
124277
|
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync13 } from "fs";
|
|
124159
|
-
import { dirname as
|
|
124278
|
+
import { dirname as dirname6 } from "path";
|
|
124160
124279
|
var OUTPUT_PREVIEW_LIMIT = 2000;
|
|
124161
124280
|
var INPUT_PREVIEW_LIMIT = 1000;
|
|
124162
124281
|
var SYSTEM_PROMPT_HASH_PREFIX_LENGTH = 12;
|
|
@@ -124217,7 +124336,7 @@ class StepTraceWriter {
|
|
|
124217
124336
|
const now = Date.now();
|
|
124218
124337
|
this.agentStartTime = now;
|
|
124219
124338
|
this.lastStepTime = now;
|
|
124220
|
-
mkdirSync13(
|
|
124339
|
+
mkdirSync13(dirname6(this.tracePath), { recursive: true });
|
|
124221
124340
|
}
|
|
124222
124341
|
writeInit(data) {
|
|
124223
124342
|
const { systemPrompt, ...rest } = data;
|
|
@@ -124358,7 +124477,7 @@ init_dist();
|
|
|
124358
124477
|
init_ai();
|
|
124359
124478
|
import { existsSync as existsSync18, mkdirSync as mkdirSync14 } from "fs";
|
|
124360
124479
|
import { writeFile as writeFile6 } from "fs/promises";
|
|
124361
|
-
import { join as
|
|
124480
|
+
import { join as join26 } from "path";
|
|
124362
124481
|
init_structured();
|
|
124363
124482
|
init_observability();
|
|
124364
124483
|
|
|
@@ -124648,6 +124767,7 @@ class OffensiveSecurityAgent {
|
|
|
124648
124767
|
subagentId;
|
|
124649
124768
|
persistentShell;
|
|
124650
124769
|
browserSession;
|
|
124770
|
+
ownsBrowserSession;
|
|
124651
124771
|
abortSignal;
|
|
124652
124772
|
userPrompt;
|
|
124653
124773
|
_session;
|
|
@@ -124687,19 +124807,22 @@ class OffensiveSecurityAgent {
|
|
|
124687
124807
|
}
|
|
124688
124808
|
if (!input.sandbox) {
|
|
124689
124809
|
const sessionHeaders = input.target ? resolveEffectiveHeaders(input.session, input.target) : input.session.config?.headers;
|
|
124810
|
+
this.ownsBrowserSession = !input.browserSession;
|
|
124690
124811
|
this.browserSession = input.browserSession ?? new PlaywrightMcpSession({
|
|
124691
124812
|
extraHttpHeaders: stripBrowserManagedHeaders(sessionHeaders)
|
|
124692
124813
|
});
|
|
124814
|
+
} else {
|
|
124815
|
+
this.ownsBrowserSession = false;
|
|
124693
124816
|
}
|
|
124694
|
-
const messagesDir = input.messagesDir ?? (input.subagentId ?
|
|
124695
|
-
const tracePath = input.subagentId ?
|
|
124817
|
+
const messagesDir = input.messagesDir ?? (input.subagentId ? join26(input.session.rootPath, "subagents", input.subagentId) : input.session.rootPath);
|
|
124818
|
+
const tracePath = input.subagentId ? join26(input.session.rootPath, "subagents", `${input.subagentId}.trace.jsonl`) : join26(messagesDir, "trace.jsonl");
|
|
124696
124819
|
const traceWriter = new StepTraceWriter({
|
|
124697
124820
|
tracePath,
|
|
124698
124821
|
agentId: input.subagentId ?? null,
|
|
124699
124822
|
eventBus: this.eventBus
|
|
124700
124823
|
});
|
|
124701
124824
|
const taskDriven = input.session.config?.taskDriven ?? false;
|
|
124702
|
-
const tasksDir = input.tasksDir ?? (taskDriven ? input.subagentId ?
|
|
124825
|
+
const tasksDir = input.tasksDir ?? (taskDriven ? input.subagentId ? join26(input.session.rootPath, "subagents", `${input.subagentId}-tasks`) : join26(input.session.rootPath, "tasks") : undefined);
|
|
124703
124826
|
const credentialManager = input.credentialManager ?? input.session.credentialManager;
|
|
124704
124827
|
const builtinTools = createAllTools({
|
|
124705
124828
|
session: input.session,
|
|
@@ -124775,7 +124898,7 @@ class OffensiveSecurityAgent {
|
|
|
124775
124898
|
if (!existsSync18(messagesDir)) {
|
|
124776
124899
|
mkdirSync14(messagesDir, { recursive: true });
|
|
124777
124900
|
}
|
|
124778
|
-
const messagesPath =
|
|
124901
|
+
const messagesPath = join26(messagesDir, "messages.json");
|
|
124779
124902
|
const initialMessagesRef = {
|
|
124780
124903
|
current: input.messages ? [...input.messages] : [
|
|
124781
124904
|
{
|
|
@@ -124893,6 +125016,9 @@ class OffensiveSecurityAgent {
|
|
|
124893
125016
|
}
|
|
124894
125017
|
} finally {
|
|
124895
125018
|
this.persistentShell?.dispose();
|
|
125019
|
+
if (this.ownsBrowserSession && this.browserSession) {
|
|
125020
|
+
await this.browserSession.disconnect().catch(() => {});
|
|
125021
|
+
}
|
|
124896
125022
|
}
|
|
124897
125023
|
if (this.abortSignal?.aborted) {
|
|
124898
125024
|
throw new DOMException("Agent aborted by user", "AbortError");
|