0sec-cli 0.15.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/0sec.js +327 -0
  2. package/README.md +68 -48
  3. package/attacks/data-exfiltration/pii-leakage.yaml +27 -0
  4. package/attacks/encoding-bypass/base64-encoding.yaml +24 -0
  5. package/attacks/jailbreak/dan-roleplay.yaml +27 -0
  6. package/attacks/jailbreak/hypothetical-scenario.yaml +25 -0
  7. package/attacks/jailbreak/multilingual-bypass.yaml +22 -0
  8. package/attacks/output-manipulation/harmful-content.yaml +25 -0
  9. package/attacks/prompt-injection/context-manipulation.yaml +32 -0
  10. package/attacks/prompt-injection/direct-injection.yaml +28 -0
  11. package/attacks/prompt-injection/indirect-injection.yaml +33 -0
  12. package/attacks/system-prompt-extraction/direct-ask.yaml +30 -0
  13. package/attacks/system-prompt-extraction/markdown-exfil.yaml +26 -0
  14. package/attacks/tool-misuse/ssrf-via-tools.yaml +27 -0
  15. package/chunks/adapt-loop-SMH6V4PD.js +18 -0
  16. package/chunks/adgraph-JLGA6RYI.js +54 -0
  17. package/chunks/agent/skills/frameworks/entra-id.yaml +63 -0
  18. package/chunks/agent/skills/frameworks/graphql-introspection.yaml +116 -0
  19. package/chunks/agent/skills/frameworks/nextjs.yaml +82 -0
  20. package/chunks/agent/skills/frameworks/python-web.yaml +85 -0
  21. package/chunks/agent/skills/frameworks/supabase.yaml +83 -0
  22. package/chunks/agent/skills/frameworks/wordpress-deep.yaml +122 -0
  23. package/chunks/agent/skills/techniques/ad-attack-paths.yaml +57 -0
  24. package/chunks/agent/skills/techniques/advisory-disclosure.yaml +59 -0
  25. package/chunks/agent/skills/techniques/assumption-mining.yaml +53 -0
  26. package/chunks/agent/skills/techniques/blind-exploitation.yaml +143 -0
  27. package/chunks/agent/skills/techniques/crypto-misuse.yaml +88 -0
  28. package/chunks/agent/skills/techniques/cve-poc-adaptation.yaml +82 -0
  29. package/chunks/agent/skills/techniques/entra-attack-paths.yaml +55 -0
  30. package/chunks/agent/skills/techniques/http-conformance-diff.yaml +48 -0
  31. package/chunks/agent/skills/techniques/jwt-attacks.yaml +137 -0
  32. package/chunks/agent/skills/techniques/kernel-weaponization.yaml +53 -0
  33. package/chunks/agent/skills/techniques/llm-excessive-agency.yaml +55 -0
  34. package/chunks/agent/skills/techniques/llm-insecure-output-handling.yaml +56 -0
  35. package/chunks/agent/skills/techniques/llm-prompt-injection.yaml +54 -0
  36. package/chunks/agent/skills/techniques/llm-prompt-layer-write.yaml +68 -0
  37. package/chunks/agent/skills/techniques/llm-rag-poisoning.yaml +57 -0
  38. package/chunks/agent/skills/techniques/llm-safety-eval.yaml +51 -0
  39. package/chunks/agent/skills/techniques/npm-ecosystem.yaml +51 -0
  40. package/chunks/agent/skills/techniques/poc-verification.yaml +55 -0
  41. package/chunks/agent/skills/techniques/race-condition.yaml +122 -0
  42. package/chunks/agent/skills/techniques/scoped-fix.yaml +49 -0
  43. package/chunks/agent/skills/techniques/seedless-depth-review.yaml +59 -0
  44. package/chunks/agent/skills/techniques/spec-differential.yaml +48 -0
  45. package/chunks/agent/skills/techniques/variant-hunting.yaml +55 -0
  46. package/chunks/agent/skills/vulnerabilities/cardano-eutxo-validators.yaml +72 -0
  47. package/chunks/agent/skills/vulnerabilities/command-injection.yaml +99 -0
  48. package/chunks/agent/skills/vulnerabilities/deserialization-chains.yaml +106 -0
  49. package/chunks/agent/skills/vulnerabilities/native-memory-safety.yaml +93 -0
  50. package/chunks/agent/skills/vulnerabilities/path-traversal.yaml +78 -0
  51. package/chunks/agent/skills/vulnerabilities/prototype-pollution.yaml +132 -0
  52. package/chunks/agent/skills/vulnerabilities/request-smuggling.yaml +129 -0
  53. package/chunks/agent/skills/vulnerabilities/sqli-advanced.yaml +102 -0
  54. package/chunks/agent/skills/vulnerabilities/ssrf-bypass.yaml +84 -0
  55. package/chunks/agent/skills/vulnerabilities/ssti-exploitation.yaml +112 -0
  56. package/chunks/agent/skills/vulnerabilities/structural-sqli.yaml +91 -0
  57. package/chunks/appsec-catalog-CBWHGTEL.js +24 -0
  58. package/chunks/artifact-scraper-HQ7HLP6V.js +34 -0
  59. package/chunks/assumption-mining-5SNIVVDN.js +79 -0
  60. package/chunks/chunk-242TMK6G.js +110 -0
  61. package/chunks/chunk-2JCCA2JL.js +381 -0
  62. package/chunks/chunk-2RMLOJVB.js +47 -0
  63. package/chunks/chunk-3KPWWJCI.js +1422 -0
  64. package/chunks/chunk-3MOLBTLS.js +953 -0
  65. package/chunks/chunk-53G27VPS.js +136 -0
  66. package/chunks/chunk-57ZENEX2.js +169 -0
  67. package/chunks/chunk-5G3ZXFBW.js +182 -0
  68. package/chunks/chunk-5JI7L7KV.js +74240 -0
  69. package/chunks/chunk-6L26OBWI.js +1094 -0
  70. package/chunks/chunk-6LKRLK2R.js +542 -0
  71. package/chunks/chunk-72CISA2D.js +2597 -0
  72. package/chunks/chunk-7DQEV5QI.js +287 -0
  73. package/chunks/chunk-AD7WXDH6.js +3250 -0
  74. package/chunks/chunk-ADOLI6DT.js +102 -0
  75. package/chunks/chunk-AHTBZC3E.js +596 -0
  76. package/chunks/chunk-ASUR522M.js +518 -0
  77. package/chunks/chunk-ATATQACO.js +471 -0
  78. package/chunks/chunk-BATRQBOR.js +1732 -0
  79. package/chunks/chunk-BFR2CDV5.js +5735 -0
  80. package/chunks/chunk-BFRB6HB2.js +235 -0
  81. package/chunks/chunk-BKZFDZ23.js +361 -0
  82. package/chunks/chunk-BVAZO4WA.js +193 -0
  83. package/chunks/chunk-BZNEY2ZS.js +33225 -0
  84. package/chunks/chunk-C2WXWFBB.js +1070 -0
  85. package/chunks/chunk-CMKXP5RR.js +917 -0
  86. package/chunks/chunk-DW5UWPFY.js +275 -0
  87. package/chunks/chunk-F3WBKITT.js +687 -0
  88. package/chunks/chunk-GMT2AZKM.js +2439 -0
  89. package/chunks/chunk-H2FFLZNK.js +3 -0
  90. package/chunks/chunk-IOL7D5YV.js +515 -0
  91. package/chunks/chunk-IR537GON.js +49 -0
  92. package/chunks/chunk-JQHOLLTD.js +3729 -0
  93. package/chunks/chunk-KLTNTE2Z.js +121 -0
  94. package/chunks/chunk-LP3HHYQU.js +245 -0
  95. package/chunks/chunk-MYVT64FN.js +16 -0
  96. package/chunks/chunk-N7BOUYEV.js +852 -0
  97. package/chunks/chunk-OEFNRYI2.js +150 -0
  98. package/chunks/chunk-P6WKNFWX.js +1968 -0
  99. package/chunks/chunk-QI233I24.js +333 -0
  100. package/chunks/chunk-RJWOYEOG.js +271 -0
  101. package/chunks/chunk-RRMJC3ZE.js +105 -0
  102. package/chunks/chunk-RWONANDA.js +973 -0
  103. package/chunks/chunk-SAFFWQW4.js +5921 -0
  104. package/chunks/chunk-SF4KZ4O3.js +502 -0
  105. package/chunks/chunk-SVJEDVYK.js +808 -0
  106. package/chunks/chunk-TSK2AG6J.js +5108 -0
  107. package/chunks/chunk-U5FLXGHT.js +2010 -0
  108. package/chunks/chunk-UCYRA73C.js +662 -0
  109. package/chunks/chunk-UR4ELX2Y.js +4784 -0
  110. package/chunks/chunk-VQG4FT5D.js +685 -0
  111. package/chunks/chunk-WEBMRWEG.js +9337 -0
  112. package/chunks/chunk-WU6AFRAZ.js +1167 -0
  113. package/chunks/chunk-WVTBZEQO.js +1531 -0
  114. package/chunks/chunk-WXQ6BJ6A.js +596 -0
  115. package/chunks/chunk-XM5NLHYU.js +600 -0
  116. package/chunks/chunk-YLMN3N25.js +4054 -0
  117. package/chunks/chunk-YYRBQVFE.js +2572 -0
  118. package/chunks/chunk-Z5FA2XOX.js +2798 -0
  119. package/chunks/commands-TBC2F5CE.js +16999 -0
  120. package/chunks/corpus-v1.json +403 -0
  121. package/chunks/cost-ledger-NU63MYZM.js +13 -0
  122. package/chunks/data/appsec-archetypes.json +102 -0
  123. package/chunks/data/chromium-archetypes.json +204 -0
  124. package/chunks/data/freebsd-archetypes.json +171 -0
  125. package/chunks/data/kernel-archetypes.json +611 -0
  126. package/chunks/db-KFWOAUUB.js +16 -0
  127. package/chunks/disclose-EKTWSCGW.js +132 -0
  128. package/chunks/dist-4MAW5X6L.js +74 -0
  129. package/chunks/dist-4YICS2J2.js +2776 -0
  130. package/chunks/dist-FMGSR3DW.js +159 -0
  131. package/chunks/eval-runner-7ZF472KV.js +27 -0
  132. package/chunks/example-manifest.json +95 -0
  133. package/chunks/exploit-agent-45YQOHPJ.js +98 -0
  134. package/chunks/exploit-autoclimb-UZGEMGYT.js +81 -0
  135. package/chunks/exploit-climb-SG23KB2G.js +358 -0
  136. package/chunks/fix-IG7LYXH3.js +12 -0
  137. package/chunks/github-issues-MJ6OYOOU.js +157 -0
  138. package/chunks/harness-7ODOLOWU.js +22 -0
  139. package/chunks/http-conformance-DU66MZIU.js +11 -0
  140. package/chunks/http-sender-GWH2IYEA.js +10 -0
  141. package/chunks/hunt-scan-MMKUOETU.js +38 -0
  142. package/chunks/identity-6ZAIIWOR.js +191 -0
  143. package/chunks/kernel-primitive-7U6CWHXD.js +44 -0
  144. package/chunks/kernel-vm-runner-3JAU4O6J.js +62 -0
  145. package/chunks/memsafety-scan-J7SECV5W.js +16 -0
  146. package/chunks/native-loop-RJCJPOUS.js +54 -0
  147. package/chunks/npm-detectors-KB5Y5ZFX.js +69 -0
  148. package/chunks/npm-dynamic-discovery-AHROOZDB.js +13 -0
  149. package/chunks/orchestrate-OC2VZN2X.js +62 -0
  150. package/chunks/pipeline-BZK5BLJR.js +14 -0
  151. package/chunks/pre-recon-cve-66EB6G4M.js +351 -0
  152. package/chunks/prepare-MYY743TK.js +13 -0
  153. package/chunks/process-LQRCS5OY.js +13 -0
  154. package/chunks/replay-runner-45G3VU7X.js +39 -0
  155. package/chunks/run-D56MPDKY.js +32716 -0
  156. package/chunks/runtime-G7YWIO3B.js +43 -0
  157. package/chunks/runtime-J7PLXZNM.js +12 -0
  158. package/chunks/scan-stream-FHI2FYZE.js +96 -0
  159. package/chunks/scope-BI7BF4ZY.js +18 -0
  160. package/chunks/session-store-GZ4A4KYT.js +28 -0
  161. package/chunks/source-files-PWRQR6LY.js +12 -0
  162. package/chunks/specdrift-WCLH6TTQ.js +19 -0
  163. package/chunks/variant-candidates-YERCYMPD.js +13 -0
  164. package/chunks/web-recon-prepass-JJGPEOLE.js +1148 -0
  165. package/dashboard/assets/0sec-icon-66SreztZ.gif +0 -0
  166. package/dashboard/assets/bot-yILPnRgD.js +1 -0
  167. package/dashboard/assets/chevron-down-BeDJ-Vka.js +1 -0
  168. package/dashboard/assets/circle-alert-BEnMBMT-.js +1 -0
  169. package/dashboard/assets/client-DRYsuOGl.js +9 -0
  170. package/dashboard/assets/copy-Bi5vzoF9.js +1 -0
  171. package/dashboard/assets/desktop-CXTQonNm.js +32 -0
  172. package/dashboard/assets/desktop-NOekk4QS.css +1 -0
  173. package/dashboard/assets/dist-CmX-h7a4.js +1 -0
  174. package/dashboard/assets/dist-DAwYQmf_.js +45 -0
  175. package/dashboard/assets/findings-page-CACW9nw2.js +5 -0
  176. package/dashboard/assets/format-PoISqsES.js +1 -0
  177. package/dashboard/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  178. package/dashboard/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  179. package/dashboard/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  180. package/dashboard/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  181. package/dashboard/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  182. package/dashboard/assets/ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2 +0 -0
  183. package/dashboard/assets/ibm-plex-mono-cyrillic-400-normal-CEL4l2ZJ.woff +0 -0
  184. package/dashboard/assets/ibm-plex-mono-cyrillic-ext-400-normal-DMdlQ8Kv.woff +0 -0
  185. package/dashboard/assets/ibm-plex-mono-cyrillic-ext-400-normal-xuaO2J-f.woff2 +0 -0
  186. package/dashboard/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  187. package/dashboard/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  188. package/dashboard/assets/ibm-plex-mono-latin-ext-400-normal-BmRBH3aV.woff2 +0 -0
  189. package/dashboard/assets/ibm-plex-mono-latin-ext-400-normal-D3D2R8hC.woff +0 -0
  190. package/dashboard/assets/ibm-plex-mono-vietnamese-400-normal-BulugwFq.woff2 +0 -0
  191. package/dashboard/assets/ibm-plex-mono-vietnamese-400-normal-DDuiU_S-.woff +0 -0
  192. package/dashboard/assets/jsx-runtime-C7oxC63R.js +1 -0
  193. package/dashboard/assets/live-page-DrgQqQK5.js +1 -0
  194. package/dashboard/assets/meta-tile-CcskIV_o.js +1 -0
  195. package/dashboard/assets/operations-BKE8T-vY.css +2 -0
  196. package/dashboard/assets/operations-D8nUP5_m.js +4 -0
  197. package/dashboard/assets/operations-app-CQQhG54n.js +2 -0
  198. package/dashboard/assets/overview-page-DTGS8dPo.js +1 -0
  199. package/dashboard/assets/page-header-MFVvEtZW.js +1 -0
  200. package/dashboard/assets/play-Dwo-9xt6.js +1 -0
  201. package/dashboard/assets/scans-page-ChVtq8Us.js +1 -0
  202. package/dashboard/assets/search-CiooTLck.js +1 -0
  203. package/dashboard/assets/siren-CCBwTSuk.js +1 -0
  204. package/dashboard/assets/table-BYS-nIVA.js +1 -0
  205. package/dashboard/assets/tabs-DivxbhQy.js +1 -0
  206. package/dashboard/desktop.html +21 -0
  207. package/dashboard/index.html +15 -0
  208. package/package.json +30 -18
  209. package/bin/0sec.cjs +0 -361
@@ -0,0 +1,518 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __0secCreateRequire } from "node:module";
3
+ const require = __0secCreateRequire(import.meta.url);
4
+ import {
5
+ verifyKernelFinding
6
+ } from "./chunk-3KPWWJCI.js";
7
+ import {
8
+ createJournalWriter
9
+ } from "./chunk-UCYRA73C.js";
10
+ import {
11
+ homeStateDir
12
+ } from "./chunk-6L26OBWI.js";
13
+
14
+ // packages/core/dist/cve/adapt-loop.js
15
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
16
+ import { basename } from "node:path";
17
+
18
+ // packages/core/dist/cve/poc-fetcher.js
19
+ import { createHash } from "node:crypto";
20
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
21
+ import { join } from "node:path";
22
+ var MAX_POC_BYTES = 1 * 1024 * 1024;
23
+ var LANG_EXT = {
24
+ c: "c",
25
+ py: "py",
26
+ sh: "sh",
27
+ syz: "syz"
28
+ };
29
+ var TEXT_CONTENT_TYPES = [
30
+ "text/",
31
+ "application/json",
32
+ "application/javascript",
33
+ "application/x-sh",
34
+ "application/x-shellscript",
35
+ "application/x-python",
36
+ "application/octet-stream"
37
+ // GitHub raw sometimes serves this for plaintext
38
+ ];
39
+ var PocFetchError = class extends Error {
40
+ kind;
41
+ constructor(kind, message) {
42
+ super(message);
43
+ this.name = "PocFetchError";
44
+ this.kind = kind;
45
+ }
46
+ };
47
+ function defaultCacheDir() {
48
+ return process.env["0SEC_CVE_POC_CACHE"]?.trim() || join(homeStateDir(), "cve-pocs");
49
+ }
50
+ function buildHeaders(token) {
51
+ const headers = {
52
+ "Accept": "*/*",
53
+ "User-Agent": "0sec-cve-adapt/0.1"
54
+ };
55
+ const resolved = token ?? process.env.GITHUB_TOKEN?.trim();
56
+ if (resolved)
57
+ headers["Authorization"] = `Bearer ${resolved}`;
58
+ return headers;
59
+ }
60
+ function isTextContentType(contentType) {
61
+ if (!contentType)
62
+ return true;
63
+ const lower = contentType.toLowerCase();
64
+ return TEXT_CONTENT_TYPES.some((prefix) => lower.includes(prefix));
65
+ }
66
+ function extractInlineCodeBlock(html) {
67
+ const fenced = /```(?:[a-zA-Z0-9_+-]*)\n([\s\S]*?)\n?```/m.exec(html);
68
+ if (fenced && fenced[1]) {
69
+ return fenced[1];
70
+ }
71
+ const htmlBlock = /<pre[^>]*>\s*<code[^>]*>([\s\S]*?)<\/code>\s*<\/pre>/i.exec(html);
72
+ if (htmlBlock && htmlBlock[1]) {
73
+ return decodeHtmlEntities(htmlBlock[1]);
74
+ }
75
+ const preBlock = /<pre[^>]*>([\s\S]*?)<\/pre>/i.exec(html);
76
+ if (preBlock && preBlock[1]) {
77
+ return decodeHtmlEntities(preBlock[1]);
78
+ }
79
+ throw new PocFetchError("no-inline-block", "no fenced code block found in writeup");
80
+ }
81
+ function decodeHtmlEntities(input) {
82
+ return input.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&amp;/g, "&");
83
+ }
84
+ function sha256(bytes) {
85
+ return createHash("sha256").update(bytes).digest("hex");
86
+ }
87
+ function cacheEntryPaths(cacheDir, sha, ext) {
88
+ return {
89
+ source: join(cacheDir, `${sha}.${ext}`),
90
+ meta: join(cacheDir, `${sha}.meta.json`)
91
+ };
92
+ }
93
+ function urlPointerPath(cacheDir, url) {
94
+ return join(cacheDir, `${sha256(url).slice(0, 24)}.url.json`);
95
+ }
96
+ function readUrlPointer(cacheDir, url) {
97
+ const path = urlPointerPath(cacheDir, url);
98
+ if (!existsSync(path))
99
+ return null;
100
+ try {
101
+ const parsed = JSON.parse(readFileSync(path, "utf-8"));
102
+ if (parsed.url !== url)
103
+ return null;
104
+ return parsed;
105
+ } catch {
106
+ return null;
107
+ }
108
+ }
109
+ function writeUrlPointer(cacheDir, pointer) {
110
+ writeFileSync(urlPointerPath(cacheDir, pointer.url), JSON.stringify(pointer, null, 2), "utf-8");
111
+ }
112
+ async function fetchPoc(candidate, opts = {}) {
113
+ const cacheDir = opts.cacheDir ?? defaultCacheDir();
114
+ mkdirSync(cacheDir, { recursive: true });
115
+ const now = opts.now ?? (() => /* @__PURE__ */ new Date());
116
+ const fetchImpl = opts.fetchImpl ?? fetch;
117
+ const pointer = readUrlPointer(cacheDir, candidate.url);
118
+ if (pointer) {
119
+ const { source: source2 } = cacheEntryPaths(cacheDir, pointer.sha256, pointer.ext);
120
+ if (existsSync(source2)) {
121
+ const bytes = readFileSync(source2);
122
+ if (sha256(bytes) === pointer.sha256) {
123
+ return {
124
+ local_path: source2,
125
+ language: candidate.language,
126
+ sha256: pointer.sha256,
127
+ source_url: candidate.url,
128
+ fetched_at: pointer.fetched_at
129
+ };
130
+ }
131
+ }
132
+ }
133
+ let response;
134
+ try {
135
+ response = await fetchImpl(candidate.url, {
136
+ method: "GET",
137
+ headers: buildHeaders(opts.githubToken)
138
+ });
139
+ } catch (err) {
140
+ throw new PocFetchError("network", `network error fetching ${candidate.url}: ${err instanceof Error ? err.message : String(err)}`);
141
+ }
142
+ if (!response.ok) {
143
+ throw new PocFetchError("http", `HTTP ${response.status} fetching ${candidate.url}: ${response.statusText}`);
144
+ }
145
+ const contentLength = response.headers.get("content-length");
146
+ if (contentLength && parseInt(contentLength, 10) > MAX_POC_BYTES) {
147
+ throw new PocFetchError("too-large", `PoC at ${candidate.url} is ${contentLength} bytes (cap ${MAX_POC_BYTES})`);
148
+ }
149
+ const contentType = response.headers.get("content-type");
150
+ if (!isTextContentType(contentType)) {
151
+ throw new PocFetchError("non-text", `PoC at ${candidate.url} has non-text content-type: ${contentType}`);
152
+ }
153
+ const buf = Buffer.from(await response.arrayBuffer());
154
+ if (buf.byteLength > MAX_POC_BYTES) {
155
+ throw new PocFetchError("too-large", `PoC at ${candidate.url} is ${buf.byteLength} bytes (cap ${MAX_POC_BYTES})`);
156
+ }
157
+ let payload = buf.toString("utf-8");
158
+ if (candidate.source === "inline-writeup") {
159
+ try {
160
+ payload = extractInlineCodeBlock(payload);
161
+ } catch (err) {
162
+ if (err instanceof PocFetchError)
163
+ throw err;
164
+ throw new PocFetchError("extract", `failed to extract inline code block: ${String(err)}`);
165
+ }
166
+ }
167
+ const newSha = sha256(payload);
168
+ const ext = LANG_EXT[candidate.language];
169
+ const { source } = cacheEntryPaths(cacheDir, newSha, ext);
170
+ if (pointer && pointer.sha256 !== newSha && opts.onShaMismatch) {
171
+ opts.onShaMismatch({ url: candidate.url, oldSha: pointer.sha256, newSha });
172
+ }
173
+ writeFileSync(source, payload, "utf-8");
174
+ const fetched_at = now().toISOString();
175
+ writeUrlPointer(cacheDir, { url: candidate.url, sha256: newSha, ext, fetched_at });
176
+ return {
177
+ local_path: source,
178
+ language: candidate.language,
179
+ sha256: newSha,
180
+ source_url: candidate.url,
181
+ fetched_at
182
+ };
183
+ }
184
+
185
+ // packages/core/dist/cve/adapt-loop.js
186
+ var DEFAULT_ATTEMPTS = 5;
187
+ var DEFAULT_WALL_CLOCK_MS = 30 * 60 * 1e3;
188
+ function applyUnifiedDiff(source, diff) {
189
+ const sourceLines = source.split("\n");
190
+ const diffLines = diff.replace(/\r\n/g, "\n").split("\n");
191
+ while (diffLines.length > 0 && diffLines[diffLines.length - 1] === "") {
192
+ diffLines.pop();
193
+ }
194
+ let i = 0;
195
+ while (i < diffLines.length && !diffLines[i].startsWith("@@"))
196
+ i += 1;
197
+ if (i >= diffLines.length) {
198
+ return source;
199
+ }
200
+ const out = [...sourceLines];
201
+ let cursorOffset = 0;
202
+ while (i < diffLines.length) {
203
+ const header = diffLines[i];
204
+ const match = /^@@\s+-(\d+)(?:,(\d+))?\s+\+(\d+)(?:,(\d+))?\s+@@/.exec(header);
205
+ if (!match) {
206
+ throw new Error(`malformed hunk header: ${header}`);
207
+ }
208
+ const oldStart = parseInt(match[1], 10);
209
+ i += 1;
210
+ let target = oldStart - 1 + cursorOffset;
211
+ while (i < diffLines.length && !diffLines[i].startsWith("@@")) {
212
+ const line = diffLines[i];
213
+ const marker = line[0];
214
+ const text = line.slice(1);
215
+ if (marker === " ") {
216
+ if (out[target] !== text) {
217
+ throw new Error(`context mismatch at line ${target + 1}: expected "${text}", got "${out[target] ?? "<eof>"}"`);
218
+ }
219
+ target += 1;
220
+ } else if (marker === "-") {
221
+ if (out[target] !== text) {
222
+ throw new Error(`delete mismatch at line ${target + 1}: expected "${text}", got "${out[target] ?? "<eof>"}"`);
223
+ }
224
+ out.splice(target, 1);
225
+ cursorOffset -= 1;
226
+ } else if (marker === "+") {
227
+ out.splice(target, 0, text);
228
+ target += 1;
229
+ cursorOffset += 1;
230
+ } else if (marker === "\\") {
231
+ } else {
232
+ throw new Error(`unknown diff marker '${marker ?? "<empty>"}' at line: ${line}`);
233
+ }
234
+ i += 1;
235
+ }
236
+ }
237
+ return out.join("\n");
238
+ }
239
+ function inferAdaptedFilename(originalPath, attemptIndex) {
240
+ const base = basename(originalPath);
241
+ const dot = base.lastIndexOf(".");
242
+ if (dot < 0)
243
+ return `${base}.adapt${attemptIndex}`;
244
+ return `${base.slice(0, dot)}.adapt${attemptIndex}${base.slice(dot)}`;
245
+ }
246
+ function defaultAgent() {
247
+ return async () => {
248
+ return "";
249
+ };
250
+ }
251
+ function renderAdaptationPrompt(input) {
252
+ const lines = [];
253
+ lines.push(`# CVE adaptation request \u2014 ${input.cveId}`);
254
+ lines.push(`Attempt ${input.attemptIndex} did not reproduce the bug.`);
255
+ lines.push("");
256
+ lines.push("Your job: produce a **unified diff** against the PoC source below that", "makes the reproducer trigger on the target kernel. Output ONLY the diff,", "starting with `--- a/poc.<ext>` and `+++ b/poc.<ext>` headers. If you have", "no useful adaptation, output an empty diff (no `@@` hunks).");
257
+ lines.push("");
258
+ lines.push(`## PoC source (language=${input.pocLanguage})`);
259
+ lines.push("```");
260
+ lines.push(input.pocSource);
261
+ lines.push("```");
262
+ if (input.writeupText) {
263
+ lines.push("");
264
+ lines.push("## Writeup excerpt");
265
+ lines.push(input.writeupText);
266
+ }
267
+ if (input.targetKernelSubsystemSource) {
268
+ lines.push("");
269
+ lines.push("## Target kernel subsystem source (relevant slice)");
270
+ lines.push("```c");
271
+ lines.push(input.targetKernelSubsystemSource);
272
+ lines.push("```");
273
+ }
274
+ lines.push("");
275
+ lines.push("## Error log (build / dmesg from last attempt)");
276
+ lines.push("```");
277
+ lines.push(input.errorLog);
278
+ lines.push("```");
279
+ return lines.join("\n");
280
+ }
281
+ function nowMs(clock) {
282
+ return clock ? clock() : Date.now();
283
+ }
284
+ async function adaptAndVerify(cveId, opts) {
285
+ const attemptsBudget = opts.attempts ?? DEFAULT_ATTEMPTS;
286
+ const wallClockMs = opts.wallClockMs ?? DEFAULT_WALL_CLOCK_MS;
287
+ const fetcher = opts.fetcher ?? fetchPoc;
288
+ const runner = opts.runner ?? verifyKernelFinding;
289
+ const agent = opts.agent ?? defaultAgent();
290
+ const clock = opts.clock;
291
+ const startedAt = nowMs(clock);
292
+ const deadline = startedAt + wallClockMs;
293
+ const runId = opts.runId ?? `cve-adapt-${cveId.toLowerCase()}-${startedAt}`;
294
+ const journal = (opts.journalFactory ?? ((id) => createJournalWriter({ runId: id })))(runId);
295
+ journal.append({
296
+ kind: "dispatch",
297
+ targetAgent: "cve-adapt-loop",
298
+ objective: `adapt + verify PoC for ${cveId}`,
299
+ context: { kernelTree: opts.kernelTree, kernelConfig: opts.kernelConfig ?? "kasan", attemptsBudget, wallClockMs }
300
+ });
301
+ let artifacts;
302
+ try {
303
+ artifacts = await opts.artifactProvider(cveId);
304
+ } catch (err) {
305
+ const message = err instanceof Error ? err.message : String(err);
306
+ journal.append({ kind: "error", message: `artifact-provider failed: ${message}` });
307
+ journal.append({ kind: "done", status: "failed", summary: "artifact provider failed" });
308
+ return {
309
+ status: "no_artifact",
310
+ cveId,
311
+ attempts: [],
312
+ total_ms: nowMs(clock) - startedAt
313
+ };
314
+ }
315
+ if (!artifacts.pocCandidates || artifacts.pocCandidates.length === 0) {
316
+ journal.append({
317
+ kind: "observation",
318
+ source: "cve-adapt-loop",
319
+ summary: "no PoC candidates returned by artifact provider",
320
+ data: { cveId }
321
+ });
322
+ journal.append({ kind: "done", status: "failed", summary: "no_artifact" });
323
+ return {
324
+ status: "no_artifact",
325
+ cveId,
326
+ attempts: [],
327
+ total_ms: nowMs(clock) - startedAt
328
+ };
329
+ }
330
+ const ordered = [...artifacts.pocCandidates].sort((a, b) => b.confidence - a.confidence);
331
+ const attempts = [];
332
+ let totalAttempts = 0;
333
+ let lastPocPath;
334
+ for (const candidate of ordered) {
335
+ if (totalAttempts >= attemptsBudget)
336
+ break;
337
+ if (nowMs(clock) >= deadline)
338
+ break;
339
+ journal.append({
340
+ kind: "observation",
341
+ source: "cve-adapt-loop",
342
+ summary: "attempt_started",
343
+ data: { candidate, attemptIndex: totalAttempts }
344
+ });
345
+ const attemptStart = nowMs(clock);
346
+ let fetched = null;
347
+ try {
348
+ fetched = await fetcher(candidate, {});
349
+ } catch (err) {
350
+ const message = err instanceof Error ? err.message : String(err);
351
+ journal.append({ kind: "error", message: `poc_fetch_failed: ${message}` });
352
+ attempts.push({
353
+ candidate,
354
+ attemptIndex: totalAttempts,
355
+ fetched: null,
356
+ verification: null,
357
+ diffApplied: false,
358
+ error: message,
359
+ durationMs: nowMs(clock) - attemptStart
360
+ });
361
+ totalAttempts += 1;
362
+ continue;
363
+ }
364
+ journal.append({
365
+ kind: "observation",
366
+ source: "cve-adapt-loop",
367
+ summary: "poc_fetched",
368
+ data: { sha256: fetched.sha256, source_url: fetched.source_url, local_path: fetched.local_path }
369
+ });
370
+ let currentPath = fetched.local_path;
371
+ let confirmed = null;
372
+ while (totalAttempts < attemptsBudget && nowMs(clock) < deadline) {
373
+ const verify = await runVerifySafe(runner, currentPath, fetched.language, opts);
374
+ journal.append({
375
+ kind: "observation",
376
+ source: "cve-adapt-loop",
377
+ summary: "verify_run",
378
+ data: {
379
+ attemptIndex: totalAttempts,
380
+ status: verify.status,
381
+ signature: verify.signature ?? null,
382
+ dmesg_path: verify.dmesg_path
383
+ }
384
+ });
385
+ if (verify.status === "reproduced") {
386
+ confirmed = verify;
387
+ attempts.push({
388
+ candidate,
389
+ attemptIndex: totalAttempts,
390
+ fetched,
391
+ verification: verify,
392
+ diffApplied: currentPath !== fetched.local_path,
393
+ durationMs: nowMs(clock) - attemptStart
394
+ });
395
+ lastPocPath = currentPath;
396
+ totalAttempts += 1;
397
+ break;
398
+ }
399
+ attempts.push({
400
+ candidate,
401
+ attemptIndex: totalAttempts,
402
+ fetched,
403
+ verification: verify,
404
+ diffApplied: currentPath !== fetched.local_path,
405
+ durationMs: nowMs(clock) - attemptStart
406
+ });
407
+ totalAttempts += 1;
408
+ lastPocPath = currentPath;
409
+ if (totalAttempts >= attemptsBudget || nowMs(clock) >= deadline)
410
+ break;
411
+ const errorLog = existsSync2(verify.dmesg_path) ? readFileSync2(verify.dmesg_path, "utf-8") : "";
412
+ const pocSource = readFileSync2(currentPath, "utf-8");
413
+ const promptInput = {
414
+ cveId,
415
+ pocSource,
416
+ pocLanguage: fetched.language,
417
+ writeupText: artifacts.writeupText,
418
+ errorLog,
419
+ attemptIndex: totalAttempts
420
+ };
421
+ let diff = "";
422
+ try {
423
+ diff = await agent(promptInput);
424
+ } catch (err) {
425
+ const message = err instanceof Error ? err.message : String(err);
426
+ journal.append({ kind: "error", message: `agent_failed: ${message}` });
427
+ break;
428
+ }
429
+ if (!diff.trim() || !diff.includes("@@")) {
430
+ journal.append({
431
+ kind: "observation",
432
+ source: "cve-adapt-loop",
433
+ summary: "adapt_diff_empty",
434
+ data: { attemptIndex: totalAttempts }
435
+ });
436
+ break;
437
+ }
438
+ let nextSource;
439
+ try {
440
+ nextSource = applyUnifiedDiff(pocSource, diff);
441
+ } catch (err) {
442
+ const message = err instanceof Error ? err.message : String(err);
443
+ journal.append({
444
+ kind: "error",
445
+ message: `apply_diff_failed: ${message}`
446
+ });
447
+ break;
448
+ }
449
+ const nextPath = inferAdaptedFilename(fetched.local_path, totalAttempts);
450
+ const nextAbs = currentPath.replace(basename(currentPath), basename(nextPath));
451
+ writeFileSync2(nextAbs, nextSource, "utf-8");
452
+ journal.append({
453
+ kind: "observation",
454
+ source: "cve-adapt-loop",
455
+ summary: "adapt_diff_applied",
456
+ data: { attemptIndex: totalAttempts, prev_path: currentPath, next_path: nextAbs },
457
+ artifacts: [
458
+ { name: "adapt.diff", mediaType: "text/x-diff", content: diff }
459
+ ]
460
+ });
461
+ currentPath = nextAbs;
462
+ lastPocPath = nextAbs;
463
+ }
464
+ if (confirmed) {
465
+ journal.append({ kind: "done", status: "success", summary: "reproduced" });
466
+ return {
467
+ status: "confirmed",
468
+ cveId,
469
+ attempts,
470
+ final_poc_path: lastPocPath,
471
+ signature: confirmed.signature,
472
+ total_ms: nowMs(clock) - startedAt
473
+ };
474
+ }
475
+ }
476
+ const exhaustedByBudget = totalAttempts >= attemptsBudget || nowMs(clock) >= deadline;
477
+ const status = exhaustedByBudget ? "budget_exhausted" : "unreproduced";
478
+ journal.append({
479
+ kind: "done",
480
+ status: "failed",
481
+ summary: status
482
+ });
483
+ return {
484
+ status,
485
+ cveId,
486
+ attempts,
487
+ final_poc_path: lastPocPath,
488
+ total_ms: nowMs(clock) - startedAt
489
+ };
490
+ }
491
+ async function runVerifySafe(runner, reproducerPath, language, opts) {
492
+ const isSyz = language === "syz";
493
+ try {
494
+ return await runner({
495
+ kernelTree: opts.kernelTree,
496
+ kernelConfig: opts.kernelConfig,
497
+ reproducerPath: isSyz ? void 0 : reproducerPath,
498
+ syzProgramPath: isSyz ? reproducerPath : void 0
499
+ });
500
+ } catch (err) {
501
+ return {
502
+ status: "run_failed",
503
+ dmesg_path: "",
504
+ build_cache_hit: false,
505
+ signature: void 0
506
+ };
507
+ }
508
+ }
509
+
510
+ export {
511
+ MAX_POC_BYTES,
512
+ PocFetchError,
513
+ extractInlineCodeBlock,
514
+ fetchPoc,
515
+ applyUnifiedDiff,
516
+ renderAdaptationPrompt,
517
+ adaptAndVerify
518
+ };