@pensar/apex 1.8.0 → 1.8.2-canary.fb75c486
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 +11 -0
- package/build/agent-6dj1qm50.js +221 -0
- package/build/agent-6xr8vpgm.js +28 -0
- package/build/agent-x1htbpe3.js +22 -0
- package/build/apps-t0gmwc7z.js +446 -0
- package/build/{auth-dxjgy41e.js → auth-p4r1m7xq.js} +50 -13
- package/build/authentication-je2b0c3w.js +22 -0
- package/build/blackboxAgent-a4jnt0y5.js +22 -0
- package/build/{blackboxPentest-8ps4yvbk.js → blackboxPentest-b5741n3h.js} +19 -17
- package/build/{cli-y61d9433.js → cli-0tnv1vkp.js} +138 -38
- package/build/{cli-jg7r7y5n.js → cli-4xb21y6g.js} +30 -2
- package/build/{cli-k0tckznm.js → cli-6p7d2k55.js} +39701 -31695
- package/build/cli-87zakjb2.js +17 -0
- package/build/{authentication-e30mfzbe.js → cli-8frjr68r.js} +11 -18
- package/build/cli-8xknm7d9.js +204 -0
- package/build/cli-9egg9azd.js +22 -0
- package/build/cli-9fsre5pt.js +0 -0
- package/build/cli-abbka8n3.js +501 -0
- package/build/{cli-3y0dgy56.js → cli-c8131c4q.js} +2 -2
- package/build/cli-e08r86zk.js +24 -0
- package/build/{cli-0ghkg3w6.js → cli-e6rgwtpb.js} +19950 -18556
- package/build/cli-g5h24ny8.js +197 -0
- package/build/{cli-nr1cjfr9.js → cli-gtcd5c3f.js} +26 -7
- package/build/cli-k0730f59.js +52 -0
- package/build/{cli-tp1tqn3k.js → cli-mswm4k81.js} +1 -1
- package/build/{cli-m788e4f3.js → cli-q8dfq25x.js} +584 -33
- package/build/cli-rhry8mat.js +7213 -0
- package/build/{cli-g8t710ew.js → cli-ryy39d77.js} +253 -250
- package/build/cli-s1nckt4k.js +20 -0
- package/build/{cli-k4hrygff.js → cli-v9ds4jb8.js} +9 -5
- package/build/{cli-dqt80sw3.js → cli-w5990vr6.js} +199 -68
- package/build/{cli-3w2syxpv.js → cli-wfmdch3r.js} +102695 -104816
- package/build/cli.js +351 -280
- package/build/config-3bvtf3j8.js +188 -0
- package/build/{doctor-8tva8j99.js → doctor-2bkpddws.js} +1 -1
- package/build/{fixes-q5bhgxhc.js → fixes-60k3ts71.js} +23 -4
- package/build/{index-pfee23kv.js → index-0gp3x2r8.js} +19306 -18954
- package/build/index-861hkebg.js +12 -0
- package/build/{index-y5xpp21a.js → index-acc00eq4.js} +77 -108
- package/build/index-acdgrqa0.js +36 -0
- package/build/{index-e898mdyh.js → index-cfberehw.js} +4 -2
- package/build/{index-wfeb2gcc.js → index-hxn4rk8f.js} +9 -11
- package/build/{index-dw1xbhfn.js → index-vc29b21w.js} +161 -26
- package/build/index-vwt27stc.js +184 -0
- package/build/{issues-qbmdneej.js → issues-1bynat5q.js} +33 -9
- package/build/{logs-xm5vbymy.js → logs-e78vx2dy.js} +23 -4
- package/build/{main-3d7dfdvs.js → main-3zneyg7p.js} +93 -17
- package/build/{offesecAgent-re6kt2ff.js → offesecAgent-w9m0svwk.js} +14 -11
- package/build/parse-15kqmy2v.js +207 -0
- package/build/pentest-gpvqpvmd.js +31 -0
- package/build/{pentests-e3rj5845.js → pentests-nq7wa8yb.js} +36 -17
- package/build/{targetedPentest-fs0v570s.js → targetedPentest-fjxqn089.js} +15 -12
- package/build/threatModel-9yqx7d7x.js +29 -0
- package/build/{uninstall-qb2xbh2t.js → uninstall-9zbf4cwc.js} +6 -4
- package/build/{utils-jf52rmrb.js → utils-dh1t2r1e.js} +13 -10
- package/package.json +86 -88
- package/build/agent-4d8j2jsw.js +0 -278
- package/build/agent-z2s6h7n2.js +0 -19
- package/build/blackboxAgent-j9pczwym.js +0 -19
- package/build/cli-03z6pswp.js +0 -1423
- package/build/cli-0fy9j5dw.js +0 -61
- package/build/cli-asyas1xb.js +0 -110
- package/build/cli-dj1dgw2n.js +0 -190
- package/build/cli-q7r2sth7.js +0 -103
- package/build/cli-vkwch0bc.js +0 -1207
- package/build/cli-wr7g9qcr.js +0 -645
- package/build/index-bz6f8jry.js +0 -32
- package/build/pentest-mfm4hake.js +0 -29
- package/build/projects-qk22qcbt.js +0 -35
- package/build/threatModel-xfvc6cch.js +0 -67
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
ALL_TOOL_NAMES,
|
|
3
|
+
ASK_USER_QUESTIONS_TOOL_NAME,
|
|
4
|
+
OffensiveSecurityAgent,
|
|
5
|
+
SKILL_TOOL_NAMES,
|
|
6
|
+
buildBaseSystemPrompt,
|
|
7
|
+
sessions
|
|
8
|
+
} from "./cli-wfmdch3r.js";
|
|
9
|
+
import {
|
|
10
|
+
init_dist,
|
|
11
|
+
stepCountIs
|
|
12
|
+
} from "./cli-6p7d2k55.js";
|
|
13
|
+
import {
|
|
14
|
+
ensureValidToken,
|
|
15
|
+
getPensarApiUrl,
|
|
16
|
+
init_auth,
|
|
17
|
+
init_constants
|
|
18
|
+
} from "./cli-w5990vr6.js";
|
|
19
|
+
import {
|
|
20
|
+
exports_external1 as exports_external,
|
|
21
|
+
init_zod
|
|
22
|
+
} from "./cli-e6rgwtpb.js";
|
|
23
|
+
import {
|
|
24
|
+
config,
|
|
25
|
+
init_config
|
|
26
|
+
} from "./cli-9egg9azd.js";
|
|
4
27
|
import {
|
|
5
28
|
__commonJS,
|
|
6
29
|
__require
|
|
@@ -1338,7 +1361,6 @@ var require_stringify = __commonJS((exports) => {
|
|
|
1338
1361
|
nullStr: "null",
|
|
1339
1362
|
simpleKeys: false,
|
|
1340
1363
|
singleQuote: null,
|
|
1341
|
-
trailingComma: false,
|
|
1342
1364
|
trueStr: "true",
|
|
1343
1365
|
verifyAliasOrder: true
|
|
1344
1366
|
}, doc.schema.toStringOptions, options);
|
|
@@ -1847,20 +1869,13 @@ ${indent}${line}` : `
|
|
|
1847
1869
|
if (comment)
|
|
1848
1870
|
reqNewline = true;
|
|
1849
1871
|
let str = stringify.stringify(item, itemCtx, () => comment = null);
|
|
1850
|
-
|
|
1851
|
-
`));
|
|
1852
|
-
if (i < items.length - 1) {
|
|
1872
|
+
if (i < items.length - 1)
|
|
1853
1873
|
str += ",";
|
|
1854
|
-
} else if (ctx.options.trailingComma) {
|
|
1855
|
-
if (ctx.options.lineWidth > 0) {
|
|
1856
|
-
reqNewline || (reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) + (str.length + 2) > ctx.options.lineWidth);
|
|
1857
|
-
}
|
|
1858
|
-
if (reqNewline) {
|
|
1859
|
-
str += ",";
|
|
1860
|
-
}
|
|
1861
|
-
}
|
|
1862
1874
|
if (comment)
|
|
1863
1875
|
str += stringifyComment.lineComment(str, itemIndent, commentString(comment));
|
|
1876
|
+
if (!reqNewline && (lines.length > linesAtValue || str.includes(`
|
|
1877
|
+
`)))
|
|
1878
|
+
reqNewline = true;
|
|
1864
1879
|
lines.push(str);
|
|
1865
1880
|
linesAtValue = lines.length;
|
|
1866
1881
|
}
|
|
@@ -4655,22 +4670,17 @@ var require_compose_node = __commonJS((exports) => {
|
|
|
4655
4670
|
case "block-map":
|
|
4656
4671
|
case "block-seq":
|
|
4657
4672
|
case "flow-collection":
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
node.anchor = anchor.source.substring(1);
|
|
4662
|
-
} catch (error) {
|
|
4663
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
4664
|
-
onError(token, "RESOURCE_EXHAUSTION", message);
|
|
4665
|
-
}
|
|
4673
|
+
node = composeCollection.composeCollection(CN, ctx, token, props, onError);
|
|
4674
|
+
if (anchor)
|
|
4675
|
+
node.anchor = anchor.source.substring(1);
|
|
4666
4676
|
break;
|
|
4667
4677
|
default: {
|
|
4668
4678
|
const message = token.type === "error" ? token.message : `Unsupported token (type: ${token.type})`;
|
|
4669
4679
|
onError(token, "UNEXPECTED_TOKEN", message);
|
|
4680
|
+
node = composeEmptyNode(ctx, token.offset, undefined, null, props, onError);
|
|
4670
4681
|
isSrcToken = false;
|
|
4671
4682
|
}
|
|
4672
4683
|
}
|
|
4673
|
-
node ?? (node = composeEmptyNode(ctx, token.offset, undefined, null, props, onError));
|
|
4674
4684
|
if (anchor && node.anchor === "")
|
|
4675
4685
|
onError(anchor, "BAD_ALIAS", "Anchor cannot be an empty string");
|
|
4676
4686
|
if (atKey && ctx.options.stringKeys && (!identity.isScalar(node) || typeof node.value !== "string" || node.tag && node.tag !== "tag:yaml.org,2002:str")) {
|
|
@@ -6920,6 +6930,329 @@ var require_public_api = __commonJS((exports) => {
|
|
|
6920
6930
|
exports.parseDocument = parseDocument;
|
|
6921
6931
|
exports.stringify = stringify;
|
|
6922
6932
|
});
|
|
6933
|
+
|
|
6934
|
+
// src/core/api/apiClient.ts
|
|
6935
|
+
init_auth();
|
|
6936
|
+
init_config();
|
|
6937
|
+
init_constants();
|
|
6938
|
+
async function getAuthHeaders() {
|
|
6939
|
+
const cfg = await config.get();
|
|
6940
|
+
const validToken = await ensureValidToken({
|
|
6941
|
+
accessToken: cfg.accessToken,
|
|
6942
|
+
refreshToken: cfg.refreshToken,
|
|
6943
|
+
pensarAPIKey: cfg.pensarAPIKey
|
|
6944
|
+
});
|
|
6945
|
+
if (!validToken) {
|
|
6946
|
+
throw new Error("Not authenticated. Run `pensar login` to connect to Pensar Console.");
|
|
6947
|
+
}
|
|
6948
|
+
const headers = {
|
|
6949
|
+
"Content-Type": "application/json",
|
|
6950
|
+
Authorization: `Bearer ${validToken.token}`
|
|
6951
|
+
};
|
|
6952
|
+
if (cfg.workspaceId) {
|
|
6953
|
+
headers["X-Workspace-Id"] = cfg.workspaceId;
|
|
6954
|
+
}
|
|
6955
|
+
return headers;
|
|
6956
|
+
}
|
|
6957
|
+
async function apiRequest(method, path, body) {
|
|
6958
|
+
const baseUrl = getPensarApiUrl();
|
|
6959
|
+
const headers = await getAuthHeaders();
|
|
6960
|
+
const url = `${baseUrl}${path}`;
|
|
6961
|
+
const init = { method, headers };
|
|
6962
|
+
if (body !== undefined) {
|
|
6963
|
+
init.body = JSON.stringify(body);
|
|
6964
|
+
}
|
|
6965
|
+
const response = await fetch(url, init);
|
|
6966
|
+
if (!response.ok) {
|
|
6967
|
+
const text2 = await response.text();
|
|
6968
|
+
let message;
|
|
6969
|
+
try {
|
|
6970
|
+
const err = JSON.parse(text2);
|
|
6971
|
+
message = err.error ?? text2;
|
|
6972
|
+
} catch {
|
|
6973
|
+
message = text2;
|
|
6974
|
+
}
|
|
6975
|
+
throw new Error(`API error (${response.status}): ${message}`);
|
|
6976
|
+
}
|
|
6977
|
+
const text = await response.text();
|
|
6978
|
+
if (!text)
|
|
6979
|
+
return;
|
|
6980
|
+
return JSON.parse(text);
|
|
6981
|
+
}
|
|
6982
|
+
|
|
6983
|
+
// src/core/api/apps.ts
|
|
6984
|
+
async function listApps(opts) {
|
|
6985
|
+
const params = new URLSearchParams;
|
|
6986
|
+
if (opts?.limit !== undefined)
|
|
6987
|
+
params.set("limit", String(opts.limit));
|
|
6988
|
+
if (opts?.offset !== undefined)
|
|
6989
|
+
params.set("offset", String(opts.offset));
|
|
6990
|
+
const qs = params.toString();
|
|
6991
|
+
return apiRequest("GET", `/apps${qs ? `?${qs}` : ""}`);
|
|
6992
|
+
}
|
|
6993
|
+
async function getApp(appId) {
|
|
6994
|
+
return apiRequest("GET", `/apps/${appId}`);
|
|
6995
|
+
}
|
|
6996
|
+
async function createApp(data) {
|
|
6997
|
+
return apiRequest("POST", "/apps", data);
|
|
6998
|
+
}
|
|
6999
|
+
async function updateApp(appId, data) {
|
|
7000
|
+
return apiRequest("PATCH", `/apps/${appId}`, data);
|
|
7001
|
+
}
|
|
7002
|
+
async function deleteApp(appId) {
|
|
7003
|
+
return apiRequest("DELETE", `/apps/${appId}`);
|
|
7004
|
+
}
|
|
7005
|
+
async function listEndpoints(appId, filters) {
|
|
7006
|
+
const params = new URLSearchParams;
|
|
7007
|
+
if (filters?.type)
|
|
7008
|
+
params.set("type", filters.type);
|
|
7009
|
+
if (filters?.minRiskScore !== undefined) {
|
|
7010
|
+
params.set("minRiskScore", String(filters.minRiskScore));
|
|
7011
|
+
}
|
|
7012
|
+
if (filters?.limit !== undefined)
|
|
7013
|
+
params.set("limit", String(filters.limit));
|
|
7014
|
+
if (filters?.offset !== undefined) {
|
|
7015
|
+
params.set("offset", String(filters.offset));
|
|
7016
|
+
}
|
|
7017
|
+
const qs = params.toString();
|
|
7018
|
+
const path = `/apps/${appId}/endpoints${qs ? `?${qs}` : ""}`;
|
|
7019
|
+
return apiRequest("GET", path);
|
|
7020
|
+
}
|
|
7021
|
+
async function getEndpoint(endpointId) {
|
|
7022
|
+
return apiRequest("GET", `/endpoints/${endpointId}`);
|
|
7023
|
+
}
|
|
7024
|
+
async function createEndpoint(appId, data) {
|
|
7025
|
+
return apiRequest("POST", `/apps/${appId}/endpoints`, data);
|
|
7026
|
+
}
|
|
7027
|
+
async function updateEndpoint(endpointId, data) {
|
|
7028
|
+
return apiRequest("PATCH", `/endpoints/${endpointId}`, data);
|
|
7029
|
+
}
|
|
7030
|
+
async function deleteEndpoint(endpointId) {
|
|
7031
|
+
return apiRequest("DELETE", `/endpoints/${endpointId}`);
|
|
7032
|
+
}
|
|
7033
|
+
async function searchApps(query, opts) {
|
|
7034
|
+
const params = new URLSearchParams({ q: query });
|
|
7035
|
+
if (opts?.type)
|
|
7036
|
+
params.set("type", opts.type);
|
|
7037
|
+
if (opts?.limit !== undefined)
|
|
7038
|
+
params.set("limit", String(opts.limit));
|
|
7039
|
+
if (opts?.offset !== undefined)
|
|
7040
|
+
params.set("offset", String(opts.offset));
|
|
7041
|
+
return apiRequest("GET", `/search/apps?${params.toString()}`);
|
|
7042
|
+
}
|
|
7043
|
+
async function searchEndpoints(query, opts) {
|
|
7044
|
+
const params = new URLSearchParams({ q: query });
|
|
7045
|
+
if (opts?.applicationId)
|
|
7046
|
+
params.set("applicationId", opts.applicationId);
|
|
7047
|
+
if (opts?.type)
|
|
7048
|
+
params.set("type", opts.type);
|
|
7049
|
+
if (opts?.minRiskScore !== undefined) {
|
|
7050
|
+
params.set("minRiskScore", String(opts.minRiskScore));
|
|
7051
|
+
}
|
|
7052
|
+
if (opts?.authRequired !== undefined) {
|
|
7053
|
+
params.set("authRequired", opts.authRequired ? "true" : "false");
|
|
7054
|
+
}
|
|
7055
|
+
if (opts?.limit !== undefined)
|
|
7056
|
+
params.set("limit", String(opts.limit));
|
|
7057
|
+
if (opts?.offset !== undefined)
|
|
7058
|
+
params.set("offset", String(opts.offset));
|
|
7059
|
+
return apiRequest("GET", `/search/endpoints?${params.toString()}`);
|
|
7060
|
+
}
|
|
7061
|
+
|
|
7062
|
+
// src/core/api/issues.ts
|
|
7063
|
+
async function listScans() {
|
|
7064
|
+
return apiRequest("GET", "/pentests");
|
|
7065
|
+
}
|
|
7066
|
+
async function getScan(scanId) {
|
|
7067
|
+
return apiRequest("GET", `/pentests/${scanId}`);
|
|
7068
|
+
}
|
|
7069
|
+
async function dispatchPentest(opts) {
|
|
7070
|
+
return apiRequest("POST", "/pentests", opts);
|
|
7071
|
+
}
|
|
7072
|
+
async function listIssues(filters) {
|
|
7073
|
+
const params = new URLSearchParams;
|
|
7074
|
+
if (filters?.scanId)
|
|
7075
|
+
params.set("scanId", filters.scanId);
|
|
7076
|
+
if (filters?.status)
|
|
7077
|
+
params.set("status", filters.status);
|
|
7078
|
+
if (filters?.severity)
|
|
7079
|
+
params.set("severity", filters.severity);
|
|
7080
|
+
if (filters?.branch)
|
|
7081
|
+
params.set("branch", filters.branch);
|
|
7082
|
+
const qs = params.toString();
|
|
7083
|
+
const path = `/issues${qs ? `?${qs}` : ""}`;
|
|
7084
|
+
return apiRequest("GET", path);
|
|
7085
|
+
}
|
|
7086
|
+
async function getIssue(issueId) {
|
|
7087
|
+
return apiRequest("GET", `/issues/${issueId}`);
|
|
7088
|
+
}
|
|
7089
|
+
async function updateIssue(issueId, data) {
|
|
7090
|
+
return apiRequest("PATCH", `/issues/${issueId}`, data);
|
|
7091
|
+
}
|
|
7092
|
+
async function listFixes(issueId) {
|
|
7093
|
+
return apiRequest("GET", `/issues/${issueId}/fixes`);
|
|
7094
|
+
}
|
|
7095
|
+
async function getFix(fixId) {
|
|
7096
|
+
return apiRequest("GET", `/fixes/${fixId}`);
|
|
7097
|
+
}
|
|
7098
|
+
async function listAgentLogs(issueId, opts) {
|
|
7099
|
+
const params = new URLSearchParams;
|
|
7100
|
+
if (opts?.level)
|
|
7101
|
+
params.set("level", opts.level);
|
|
7102
|
+
if (opts?.role)
|
|
7103
|
+
params.set("role", opts.role);
|
|
7104
|
+
if (opts?.limit)
|
|
7105
|
+
params.set("limit", String(opts.limit));
|
|
7106
|
+
const qs = params.toString();
|
|
7107
|
+
const path = `/issues/${issueId}/logs${qs ? `?${qs}` : ""}`;
|
|
7108
|
+
return apiRequest("GET", path);
|
|
7109
|
+
}
|
|
7110
|
+
async function searchAgentLogs(issueId, query, opts) {
|
|
7111
|
+
return apiRequest("POST", `/issues/${issueId}/logs/search`, { query, ...opts });
|
|
7112
|
+
}
|
|
7113
|
+
|
|
7114
|
+
// src/core/api/index.ts
|
|
7115
|
+
init_constants();
|
|
7116
|
+
|
|
7117
|
+
// src/core/agents/specialized/environment/prompts.ts
|
|
7118
|
+
var PREAMBLE = `You are an expert DevOps agent responsible for setting up and validating development environments. Your goal is to ensure the application can run fully with all required services operational and healthy.`;
|
|
7119
|
+
var DOCKER_COMPOSE_STEP = `1. **Docker Compose Assessment**
|
|
7120
|
+
- First, check if a docker-compose.yml or docker-compose.yaml file exists in the repository
|
|
7121
|
+
- If present, thoroughly review its configuration:
|
|
7122
|
+
* Verify all services are properly defined
|
|
7123
|
+
* Check for proper networking configuration
|
|
7124
|
+
* Validate volume mounts and environment variables
|
|
7125
|
+
* Ensure health checks are configured where appropriate
|
|
7126
|
+
- If not present, analyze the application to determine if Docker Compose is required:
|
|
7127
|
+
* Check for databases (PostgreSQL, MySQL, MongoDB, Redis, etc.)
|
|
7128
|
+
* Look for message queues (RabbitMQ, Kafka, etc.)
|
|
7129
|
+
* Identify cache layers or other external dependencies
|
|
7130
|
+
* Review application configuration files for service dependencies`;
|
|
7131
|
+
var DOCKER_COMPOSE_CREATION_STEP = `2. **Docker Compose Creation (if required but missing)**
|
|
7132
|
+
- Analyze package.json, requirements.txt, go.mod, or other dependency files
|
|
7133
|
+
- Identify database and service requirements from:
|
|
7134
|
+
* Environment variable examples (.env.example, .env.sample)
|
|
7135
|
+
* Configuration files
|
|
7136
|
+
* Database connection strings in code
|
|
7137
|
+
* Documentation (README.md, docs/)
|
|
7138
|
+
- Create a comprehensive docker-compose.yml that includes:
|
|
7139
|
+
* All required services (databases, caches, message queues, etc.)
|
|
7140
|
+
* Proper service networking
|
|
7141
|
+
* Volume mounts for data persistence
|
|
7142
|
+
* Health checks for each service
|
|
7143
|
+
* Appropriate environment variables
|
|
7144
|
+
* Dependency ordering (depends_on with conditions)`;
|
|
7145
|
+
var STARTUP_STEP = `3. **Environment Startup & Validation**
|
|
7146
|
+
- Use docker-compose to bring up all services
|
|
7147
|
+
- Monitor startup logs for errors
|
|
7148
|
+
- Wait for all health checks to pass
|
|
7149
|
+
- Verify service accessibility:
|
|
7150
|
+
* Check database connectivity
|
|
7151
|
+
* Verify ports are properly exposed and accessible
|
|
7152
|
+
* Test inter-service communication
|
|
7153
|
+
- If the application itself needs to run, start it and ensure it connects to all services`;
|
|
7154
|
+
var TROUBLESHOOTING_STEP = `4. **Iteration & Troubleshooting**
|
|
7155
|
+
- If any service fails to start or becomes unhealthy:
|
|
7156
|
+
* Analyze logs to identify the root cause
|
|
7157
|
+
* Fix configuration issues (ports, environment variables, volumes, etc.)
|
|
7158
|
+
* Update the docker-compose.yml as needed
|
|
7159
|
+
* Recreate and restart affected services
|
|
7160
|
+
- Continue iterating until:
|
|
7161
|
+
* All services are running and healthy
|
|
7162
|
+
* The application can successfully connect to all dependencies
|
|
7163
|
+
* No error logs indicate configuration issues`;
|
|
7164
|
+
var AUTH_STEP = `5. **Authentication Testing & Documentation**
|
|
7165
|
+
- After the application is running, thoroughly investigate authentication:
|
|
7166
|
+
* Check the codebase for authentication mechanisms (JWT, sessions, OAuth, etc.)
|
|
7167
|
+
* Identify registration/signup endpoints and methods
|
|
7168
|
+
* Identify login/authentication endpoints
|
|
7169
|
+
* Look for initial admin user creation or seed data scripts
|
|
7170
|
+
* Review documentation (README.md, API docs) for auth instructions
|
|
7171
|
+
- Test the authentication flow:
|
|
7172
|
+
* Attempt to register a new user (via API, CLI, or web interface)
|
|
7173
|
+
* Try to login with the registered credentials
|
|
7174
|
+
* Verify that authentication tokens/sessions are properly issued
|
|
7175
|
+
* Test accessing a protected endpoint to confirm auth is working
|
|
7176
|
+
- Document your findings:
|
|
7177
|
+
* Step-by-step instructions for registering a new user
|
|
7178
|
+
* Step-by-step instructions for authenticating/logging in
|
|
7179
|
+
* Any default credentials that exist
|
|
7180
|
+
* API endpoints for registration and login (including HTTP methods and payload format)
|
|
7181
|
+
* Authentication method used (bearer tokens, cookies, etc.)
|
|
7182
|
+
* Example curl commands or code snippets for registration and login
|
|
7183
|
+
* Any prerequisites or special configuration needed for auth to work`;
|
|
7184
|
+
var COMPLETION_STEP = `6. **Completion**
|
|
7185
|
+
- Once the environment is fully operational and authentication has been tested:
|
|
7186
|
+
* Verify all services are accessible
|
|
7187
|
+
* Note the URL where the application is running (if applicable)
|
|
7188
|
+
* Use the response tool with:
|
|
7189
|
+
- status: "ready" if successful
|
|
7190
|
+
- status: "failed" if unable to establish a working environment after extensive attempts
|
|
7191
|
+
- url: the URL where the application is accessible (or empty string if not applicable)
|
|
7192
|
+
- authenticationDetails: comprehensive details on how to register and authenticate, including tested examples`;
|
|
7193
|
+
var TOOL_USAGE = `## Available Tools
|
|
7194
|
+
|
|
7195
|
+
- **execute_command**: Run shell commands (docker-compose, curl, database clients, etc.)
|
|
7196
|
+
- **list_files**: List files in directories to explore the repository structure
|
|
7197
|
+
- **read_file**: Read file contents to understand configurations and dependencies
|
|
7198
|
+
- **grep**: Search for patterns across the codebase
|
|
7199
|
+
- **create_file**: Create new files (like docker-compose.yml)
|
|
7200
|
+
- **update_file**: Update existing files to fix configurations
|
|
7201
|
+
- **response**: Call this when the environment is ready or has failed after extensive attempts`;
|
|
7202
|
+
var BEST_PRACTICES = `## Best Practices
|
|
7203
|
+
|
|
7204
|
+
- Always check for existing configuration before creating new files
|
|
7205
|
+
- Use health checks to properly wait for services to be ready
|
|
7206
|
+
- Check logs thoroughly when services fail
|
|
7207
|
+
- For databases, ensure proper initialization scripts are run
|
|
7208
|
+
- Consider startup order - databases should be healthy before apps connect
|
|
7209
|
+
- Test connectivity explicitly (ping, curl, database client connections)
|
|
7210
|
+
- Be thorough but efficient - don't repeat failed attempts without changes`;
|
|
7211
|
+
var IMPORTANT_NOTES = `## Important Notes
|
|
7212
|
+
|
|
7213
|
+
- You have up to 1000 steps to complete this task
|
|
7214
|
+
- Always provide clear reasoning for your decisions
|
|
7215
|
+
- Document any assumptions you make about the application's requirements
|
|
7216
|
+
- If you cannot determine requirements from the codebase, make reasonable defaults
|
|
7217
|
+
- Prioritize getting a working environment over perfect configuration
|
|
7218
|
+
|
|
7219
|
+
STOP when you have called the response tool with status "ready" or "failed"`;
|
|
7220
|
+
function buildEnvironmentSystemPrompt() {
|
|
7221
|
+
return [
|
|
7222
|
+
PREAMBLE,
|
|
7223
|
+
"",
|
|
7224
|
+
"## Core Responsibilities",
|
|
7225
|
+
"",
|
|
7226
|
+
DOCKER_COMPOSE_STEP,
|
|
7227
|
+
"",
|
|
7228
|
+
DOCKER_COMPOSE_CREATION_STEP,
|
|
7229
|
+
"",
|
|
7230
|
+
STARTUP_STEP,
|
|
7231
|
+
"",
|
|
7232
|
+
TROUBLESHOOTING_STEP,
|
|
7233
|
+
"",
|
|
7234
|
+
AUTH_STEP,
|
|
7235
|
+
"",
|
|
7236
|
+
COMPLETION_STEP,
|
|
7237
|
+
"",
|
|
7238
|
+
TOOL_USAGE,
|
|
7239
|
+
"",
|
|
7240
|
+
BEST_PRACTICES,
|
|
7241
|
+
"",
|
|
7242
|
+
IMPORTANT_NOTES
|
|
7243
|
+
].join(`
|
|
7244
|
+
`);
|
|
7245
|
+
}
|
|
7246
|
+
var ENVIRONMENT_SYSTEM_PROMPT = buildEnvironmentSystemPrompt();
|
|
7247
|
+
|
|
7248
|
+
// src/core/agents/specialized/environment/types.ts
|
|
7249
|
+
init_zod();
|
|
7250
|
+
var EnvironmentResultSchema = exports_external.object({
|
|
7251
|
+
url: exports_external.string().describe("The URL where the application is accessible"),
|
|
7252
|
+
status: exports_external.enum(["ready", "failed"]).describe("The status of the development environment"),
|
|
7253
|
+
stepsTaken: exports_external.string().describe("The steps taken to start the development environment"),
|
|
7254
|
+
authenticationDetails: exports_external.string().describe("Details on how to register a user and authenticate within the development environment")
|
|
7255
|
+
});
|
|
6923
7256
|
// src/core/api/offesecAgent.ts
|
|
6924
7257
|
async function runOffensiveSecurityAgent(input) {
|
|
6925
7258
|
const agent = input.session ? new OffensiveSecurityAgent(input) : await OffensiveSecurityAgent.create(input);
|
|
@@ -6927,6 +7260,190 @@ async function runOffensiveSecurityAgent(input) {
|
|
|
6927
7260
|
await agent.consume();
|
|
6928
7261
|
return { streamResult: agent.streamResult, session: agent.session };
|
|
6929
7262
|
}
|
|
7263
|
+
// src/core/agents/specialized/patching/prompts.ts
|
|
7264
|
+
var PREAMBLE2 = `You are an expert security vulnerability patching agent. Your goal is to analyze security vulnerabilities, provide high-quality fixes, and verify the fixes don't break existing functionality.`;
|
|
7265
|
+
var ORIENT_STEP = `1. **Orient Yourself**:
|
|
7266
|
+
- Review the AGENTS.md / project documentation provided in your prompt for build, lint, and test commands
|
|
7267
|
+
- Use list_files to explore the repository structure
|
|
7268
|
+
- Read package.json, Makefile, or equivalent to understand the project's toolchain
|
|
7269
|
+
- Identify the lint command, test command, type-check command, and any other verification scripts`;
|
|
7270
|
+
var UNDERSTAND_STEP = `2. **Understand the Vulnerability**:
|
|
7271
|
+
- Carefully read the vulnerability description, CWE mappings, and any dataflow analysis provided
|
|
7272
|
+
- Understand the root cause: What makes this code vulnerable?
|
|
7273
|
+
- Identify the attack vector: How would an attacker exploit this?
|
|
7274
|
+
- Consider the context: What is the application trying to do?`;
|
|
7275
|
+
var REVIEW_STEP = `3. **Review the Code**:
|
|
7276
|
+
- Use read_file to read the vulnerable file(s) mentioned in the issue
|
|
7277
|
+
- Use grep to search for related code patterns, similar vulnerabilities, or existing security controls
|
|
7278
|
+
- Review related files: imports, dependencies, configuration files
|
|
7279
|
+
- Understand the data flow: Where does user input come from? Where does it go?`;
|
|
7280
|
+
var PLAN_STEP = `4. **Plan Your Fix**:
|
|
7281
|
+
- Identify the exact code that needs to change
|
|
7282
|
+
- Determine the appropriate security control (input validation, parameterized queries, access control, etc.)
|
|
7283
|
+
- Consider side effects: Will this break existing functionality?
|
|
7284
|
+
- Think about edge cases: What other inputs or scenarios need to be handled?
|
|
7285
|
+
- Look for framework-specific or language-specific best practices
|
|
7286
|
+
- State your complete plan clearly before making changes`;
|
|
7287
|
+
var APPLY_STEP = `5. **Apply the Patch**:
|
|
7288
|
+
- Use update_file to modify existing files with your security fixes
|
|
7289
|
+
- Use create_file if you need to add new security utilities or middleware
|
|
7290
|
+
- Make minimal, targeted changes — don't refactor unrelated code
|
|
7291
|
+
- Follow the existing code style and conventions
|
|
7292
|
+
- Ensure your changes integrate cleanly with the existing codebase`;
|
|
7293
|
+
var RESTART_STEP = `6. **Restart Dev Environment** (if applicable):
|
|
7294
|
+
- Use execute_command to restart any dev servers or services so your changes are loaded
|
|
7295
|
+
- Wait for the services to become healthy`;
|
|
7296
|
+
var VERIFY_STEP = `7. **Verify the Patch**:
|
|
7297
|
+
- Use execute_command to run the project's lint command (e.g. \`npm run lint\`, \`ruff check\`, \`cargo clippy\`)
|
|
7298
|
+
- Use execute_command to run the project's type-check command if applicable (e.g. \`npx tsc --noEmit\`, \`mypy\`)
|
|
7299
|
+
- Use execute_command to run the project's test suite (e.g. \`npm test\`, \`pytest\`, \`cargo test\`)
|
|
7300
|
+
- If a Proof of Concept (POC) is provided, run it to verify the vulnerability is fixed — the POC should FAIL (non-zero exit code) after a successful patch
|
|
7301
|
+
- If any check fails, read the error output carefully, fix the issues, and re-run until all checks pass
|
|
7302
|
+
- If the project has no clear lint/test commands, at minimum verify the changed files parse correctly (e.g. \`node -c file.js\`, \`python -m py_compile file.py\`)`;
|
|
7303
|
+
var FINALIZE_STEP = `8. **Finalize**:
|
|
7304
|
+
- Use the response tool to complete the patching process
|
|
7305
|
+
- Provide a clear, detailed summary of:
|
|
7306
|
+
* Each file you changed and why
|
|
7307
|
+
* The security principles applied
|
|
7308
|
+
* How your fix addresses the vulnerability
|
|
7309
|
+
* Verification results (lint, type-check, test outcomes, POC result if applicable)
|
|
7310
|
+
* Any assumptions or limitations of the fix
|
|
7311
|
+
- Write a professional PR title and description that explains the security fix`;
|
|
7312
|
+
var SECURITY_BEST_PRACTICES = `# Security Best Practices by Vulnerability Type
|
|
7313
|
+
|
|
7314
|
+
**SQL Injection / NoSQL Injection**:
|
|
7315
|
+
- Use parameterized queries or prepared statements ALWAYS
|
|
7316
|
+
- Use ORM query builders with parameterization
|
|
7317
|
+
- Never concatenate user input into queries
|
|
7318
|
+
- Validate and sanitize input as a defense-in-depth measure
|
|
7319
|
+
|
|
7320
|
+
**Cross-Site Scripting (XSS)**:
|
|
7321
|
+
- Use framework-provided output encoding (React JSX, template engines with auto-escaping)
|
|
7322
|
+
- Apply context-appropriate encoding (HTML, JavaScript, URL, CSS)
|
|
7323
|
+
- Use Content Security Policy headers
|
|
7324
|
+
- Sanitize rich text input with allowlist-based libraries
|
|
7325
|
+
|
|
7326
|
+
**Path Traversal / Directory Traversal**:
|
|
7327
|
+
- Validate file paths against an allowlist
|
|
7328
|
+
- Use path normalization and canonicalization
|
|
7329
|
+
- Check that resolved paths stay within intended directories
|
|
7330
|
+
- Never trust user input for file paths
|
|
7331
|
+
|
|
7332
|
+
**Authentication / Authorization Issues**:
|
|
7333
|
+
- Verify user identity before sensitive operations
|
|
7334
|
+
- Check permissions at the application layer, not just UI
|
|
7335
|
+
- Use framework authentication middleware
|
|
7336
|
+
- Implement proper session management
|
|
7337
|
+
- Follow principle of least privilege
|
|
7338
|
+
|
|
7339
|
+
**Command Injection**:
|
|
7340
|
+
- Avoid executing shell commands with user input
|
|
7341
|
+
- Use language-specific APIs instead of shell commands
|
|
7342
|
+
- If shell execution is necessary, use safe APIs with argument arrays
|
|
7343
|
+
- Validate input against strict allowlists
|
|
7344
|
+
|
|
7345
|
+
**Insecure Deserialization**:
|
|
7346
|
+
- Avoid deserializing untrusted data
|
|
7347
|
+
- Use safe data formats (JSON instead of pickle/Java serialization)
|
|
7348
|
+
- Implement integrity checks (HMAC signatures)
|
|
7349
|
+
- Validate deserialized objects strictly
|
|
7350
|
+
|
|
7351
|
+
**Server-Side Request Forgery (SSRF)**:
|
|
7352
|
+
- Validate and sanitize URLs
|
|
7353
|
+
- Use allowlists for allowed domains/IPs
|
|
7354
|
+
- Disable URL redirects or validate redirect targets
|
|
7355
|
+
- Block access to internal/private IP ranges
|
|
7356
|
+
|
|
7357
|
+
**Cryptographic Issues**:
|
|
7358
|
+
- Use strong, modern algorithms (AES-256, RSA-2048+, SHA-256+)
|
|
7359
|
+
- Never implement custom cryptography
|
|
7360
|
+
- Use cryptographically secure random number generators
|
|
7361
|
+
- Properly handle keys (don't hardcode, use key management)
|
|
7362
|
+
|
|
7363
|
+
**Sensitive Data Exposure**:
|
|
7364
|
+
- Don't log sensitive data (passwords, tokens, PII)
|
|
7365
|
+
- Use proper error handling that doesn't leak implementation details
|
|
7366
|
+
- Encrypt sensitive data at rest and in transit
|
|
7367
|
+
- Remove sensitive data from client-side code`;
|
|
7368
|
+
var TOOL_USAGE2 = `# Tool Usage
|
|
7369
|
+
|
|
7370
|
+
- **list_files**: Explore directory structure and find relevant files
|
|
7371
|
+
- **read_file**: Read file contents to understand code
|
|
7372
|
+
- **grep**: Search for patterns across the codebase
|
|
7373
|
+
- **update_file**: Modify existing files with security fixes
|
|
7374
|
+
- **create_file**: Create new files if needed (utilities, middleware, etc.)
|
|
7375
|
+
- **execute_command**: Run shell commands — use for linting, type-checking, running tests, restarting services, running POCs, installing dependencies, and verifying your changes
|
|
7376
|
+
- **response**: Complete the process with the structured patch result`;
|
|
7377
|
+
var REQUIREMENTS = `# Critical Requirements
|
|
7378
|
+
|
|
7379
|
+
1. **Be Thorough**: Your analysis must be comprehensive — read related code, not just the vulnerable file
|
|
7380
|
+
2. **Be Conservative**: When in doubt, prefer defense-in-depth approaches
|
|
7381
|
+
3. **Be Specific**: Provide exact code changes, not vague suggestions
|
|
7382
|
+
4. **Be Contextual**: Respect the existing codebase, frameworks, and patterns
|
|
7383
|
+
5. **Verify Your Work**: Always run lint, type-check, and tests after applying the patch. Fix any failures before finalizing.
|
|
7384
|
+
6. **Test the Fix**: If a POC is provided, run it after patching. The POC should FAIL (non-zero exit code) once the vulnerability is fixed.
|
|
7385
|
+
7. **Be Persistent**: It may take multiple iterations to get the fix right — iterate until the POC fails and tests pass.
|
|
7386
|
+
8. **Be Complete**: Address the root cause, not just symptoms
|
|
7387
|
+
|
|
7388
|
+
# Important Notes
|
|
7389
|
+
|
|
7390
|
+
- You are creating production code that will be deployed
|
|
7391
|
+
- Your fixes must not break existing functionality — verify this by running the project's tests
|
|
7392
|
+
- If a POC is provided, the POC should FAIL after patching (meaning the exploit no longer works)
|
|
7393
|
+
- Consider backward compatibility and edge cases
|
|
7394
|
+
- Follow language and framework conventions
|
|
7395
|
+
- When multiple approaches exist, choose the most secure and idiomatic
|
|
7396
|
+
- If a fix requires configuration changes or environment variables, note this clearly
|
|
7397
|
+
- If AGENTS.md or project docs specify particular lint/test/build commands, use those exact commands`;
|
|
7398
|
+
function buildSystemPrompt() {
|
|
7399
|
+
return [
|
|
7400
|
+
PREAMBLE2,
|
|
7401
|
+
"",
|
|
7402
|
+
"# Process",
|
|
7403
|
+
"",
|
|
7404
|
+
"You MUST follow this prescriptive process:",
|
|
7405
|
+
"",
|
|
7406
|
+
ORIENT_STEP,
|
|
7407
|
+
"",
|
|
7408
|
+
UNDERSTAND_STEP,
|
|
7409
|
+
"",
|
|
7410
|
+
REVIEW_STEP,
|
|
7411
|
+
"",
|
|
7412
|
+
PLAN_STEP,
|
|
7413
|
+
"",
|
|
7414
|
+
APPLY_STEP,
|
|
7415
|
+
"",
|
|
7416
|
+
RESTART_STEP,
|
|
7417
|
+
"",
|
|
7418
|
+
VERIFY_STEP,
|
|
7419
|
+
"",
|
|
7420
|
+
FINALIZE_STEP,
|
|
7421
|
+
"",
|
|
7422
|
+
SECURITY_BEST_PRACTICES,
|
|
7423
|
+
"",
|
|
7424
|
+
TOOL_USAGE2,
|
|
7425
|
+
"",
|
|
7426
|
+
REQUIREMENTS
|
|
7427
|
+
].join(`
|
|
7428
|
+
`);
|
|
7429
|
+
}
|
|
7430
|
+
var PATCHING_SYSTEM_PROMPT = buildSystemPrompt();
|
|
7431
|
+
|
|
7432
|
+
// src/core/agents/specialized/patching/types.ts
|
|
7433
|
+
init_zod();
|
|
7434
|
+
var PatchResultSchema = exports_external.object({
|
|
7435
|
+
filesChanged: exports_external.array(exports_external.object({
|
|
7436
|
+
filePath: exports_external.string().describe("Path to the file that was changed"),
|
|
7437
|
+
changesDescription: exports_external.string().describe("Detailed description of the changes made to the file")
|
|
7438
|
+
})),
|
|
7439
|
+
prTitle: exports_external.string().describe("Title for the pull request"),
|
|
7440
|
+
prDescription: exports_external.string().describe("Description for the pull request")
|
|
7441
|
+
});
|
|
7442
|
+
// src/core/workflows/threatModel.ts
|
|
7443
|
+
init_dist();
|
|
7444
|
+
|
|
7445
|
+
// src/core/skills/registry.ts
|
|
7446
|
+
import fs2 from "fs/promises";
|
|
6930
7447
|
|
|
6931
7448
|
// src/core/skills/builtins/pentest.ts
|
|
6932
7449
|
function buildPentestPrompt(opts) {
|
|
@@ -7380,12 +7897,8 @@ IMPORTANT: When writing the output, use the \`create_file\` tool with the EXACT
|
|
|
7380
7897
|
`
|
|
7381
7898
|
};
|
|
7382
7899
|
|
|
7383
|
-
// src/core/skills/
|
|
7384
|
-
|
|
7385
|
-
|
|
7386
|
-
// src/core/skills/scanner.ts
|
|
7387
|
-
import path2 from "path";
|
|
7388
|
-
import fs from "fs/promises";
|
|
7900
|
+
// src/core/skills/builtins/index.ts
|
|
7901
|
+
var BUILTIN_SKILLS = [pentestSkill, threatModelSkill];
|
|
7389
7902
|
|
|
7390
7903
|
// node_modules/yaml/dist/index.js
|
|
7391
7904
|
var composer = require_composer();
|
|
@@ -7501,6 +8014,10 @@ function parseSkillMd(raw) {
|
|
|
7501
8014
|
return { manifest, instructions: parts.body };
|
|
7502
8015
|
}
|
|
7503
8016
|
|
|
8017
|
+
// src/core/skills/scanner.ts
|
|
8018
|
+
import fs from "fs/promises";
|
|
8019
|
+
import path2 from "path";
|
|
8020
|
+
|
|
7504
8021
|
// src/core/skills/utils.ts
|
|
7505
8022
|
import os from "os";
|
|
7506
8023
|
import path from "path";
|
|
@@ -7575,9 +8092,6 @@ async function discoverScripts(skillDir) {
|
|
|
7575
8092
|
return scripts;
|
|
7576
8093
|
}
|
|
7577
8094
|
|
|
7578
|
-
// src/core/skills/builtins/index.ts
|
|
7579
|
-
var BUILTIN_SKILLS = [pentestSkill, threatModelSkill];
|
|
7580
|
-
|
|
7581
8095
|
// src/core/skills/registry.ts
|
|
7582
8096
|
class SkillsRegistry {
|
|
7583
8097
|
skills = new Map;
|
|
@@ -7647,4 +8161,41 @@ function createSkillsRegistry() {
|
|
|
7647
8161
|
return new SkillsRegistry;
|
|
7648
8162
|
}
|
|
7649
8163
|
|
|
7650
|
-
|
|
8164
|
+
// src/core/workflows/threatModel.ts
|
|
8165
|
+
var HEADLESS_TOOL_NAMES = ALL_TOOL_NAMES.filter((name) => name !== ASK_USER_QUESTIONS_TOOL_NAME);
|
|
8166
|
+
async function runThreatModelWorkflow(input) {
|
|
8167
|
+
const model = input.model ?? "claude-sonnet-4-5";
|
|
8168
|
+
const registry = createSkillsRegistry();
|
|
8169
|
+
await registry.load({ projectRoot: input.codebasePath });
|
|
8170
|
+
const { content } = await registry.readSkillContent("threat-model");
|
|
8171
|
+
const prompt = buildThreatModelPrompt({
|
|
8172
|
+
outputPath: input.outputPath,
|
|
8173
|
+
codebasePath: input.codebasePath,
|
|
8174
|
+
skillContent: content
|
|
8175
|
+
});
|
|
8176
|
+
const session = input.session ?? await sessions.create({
|
|
8177
|
+
name: "Threat Model",
|
|
8178
|
+
targets: [input.codebasePath],
|
|
8179
|
+
config: { mode: "operator", agentCwd: input.codebasePath }
|
|
8180
|
+
});
|
|
8181
|
+
const system = `${buildBaseSystemPrompt({ sandboxMode: false })}
|
|
8182
|
+
|
|
8183
|
+
# Threat Model Mode
|
|
8184
|
+
|
|
8185
|
+
You are generating an application-centric threat model from source code analysis.
|
|
8186
|
+
Working directory: ${input.codebasePath}`;
|
|
8187
|
+
await runOffensiveSecurityAgent({
|
|
8188
|
+
system,
|
|
8189
|
+
prompt,
|
|
8190
|
+
model,
|
|
8191
|
+
session,
|
|
8192
|
+
activeTools: [...HEADLESS_TOOL_NAMES, ...SKILL_TOOL_NAMES],
|
|
8193
|
+
authConfig: input.authConfig,
|
|
8194
|
+
abortSignal: input.abortSignal,
|
|
8195
|
+
skillsRegistry: registry,
|
|
8196
|
+
eventBus: input.eventBus,
|
|
8197
|
+
stopWhen: stepCountIs(1e4)
|
|
8198
|
+
});
|
|
8199
|
+
return { session, outputPath: input.outputPath };
|
|
8200
|
+
}
|
|
8201
|
+
export { listApps, getApp, createApp, updateApp, deleteApp, listEndpoints, getEndpoint, createEndpoint, updateEndpoint, deleteEndpoint, searchApps, searchEndpoints, listScans, getScan, dispatchPentest, listIssues, getIssue, updateIssue, listFixes, getFix, listAgentLogs, searchAgentLogs, runOffensiveSecurityAgent, buildPentestPrompt, buildThreatModelPrompt, createSkillsRegistry, runThreatModelWorkflow };
|