0sec-cli 0.18.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{0sec.js → 0.js} +90 -82
- package/LICENSE +1 -1
- package/README.md +62 -46
- package/chunks/adapt-loop-7I57LXXR.js +18 -0
- package/chunks/{adgraph-JLGA6RYI.js → adgraph-AUDQTBYA.js} +5 -5
- package/chunks/agent/skills/frameworks/entra-id.yaml +2 -2
- package/chunks/agent/skills/techniques/assumption-mining.yaml +2 -2
- package/chunks/agent/skills/techniques/cve-poc-adaptation.yaml +2 -2
- package/chunks/agent/skills/techniques/entra-attack-paths.yaml +1 -1
- package/chunks/agent/skills/techniques/kernel-weaponization.yaml +1 -1
- package/chunks/agent/skills/techniques/llm-prompt-injection.yaml +2 -2
- package/chunks/agent/skills/techniques/npm-ecosystem.yaml +1 -1
- package/chunks/agent/skills/techniques/poc-verification.yaml +1 -1
- package/chunks/agent/skills/techniques/seedless-depth-review.yaml +20 -38
- package/chunks/{artifact-scraper-HQ7HLP6V.js → artifact-scraper-PYZ3RU3O.js} +6 -6
- package/chunks/{assumption-mining-5SNIVVDN.js → assumption-mining-MFLF43IR.js} +24 -26
- package/chunks/{chunk-7DQEV5QI.js → chunk-23DG5YKS.js} +4 -4
- package/chunks/{chunk-UR4ELX2Y.js → chunk-2GV4HQKE.js} +340 -703
- package/chunks/{chunk-P6WKNFWX.js → chunk-2OQOQ2FZ.js} +8 -8
- package/chunks/{chunk-5G3ZXFBW.js → chunk-2WNCI664.js} +3 -3
- package/chunks/{chunk-DW5UWPFY.js → chunk-4VGLO2YS.js} +6 -5
- package/chunks/{chunk-KLTNTE2Z.js → chunk-5IBCBQEH.js} +13 -14
- package/chunks/{chunk-N7BOUYEV.js → chunk-5MWAG3FT.js} +14 -14
- package/chunks/{chunk-OEFNRYI2.js → chunk-6GHSR47F.js} +3 -6
- package/chunks/chunk-6YNKRUMC.js +4474 -0
- package/chunks/{chunk-6L26OBWI.js → chunk-76KSBWOQ.js} +255 -35
- package/chunks/chunk-7DEHG7YT.js +2143 -0
- package/chunks/{chunk-AD7WXDH6.js → chunk-7UFUALR2.js} +288 -22
- package/chunks/{chunk-53G27VPS.js → chunk-AZ7L3HFD.js} +7 -2
- package/chunks/{chunk-TSK2AG6J.js → chunk-CAYANSH6.js} +173 -1757
- package/chunks/{chunk-SAFFWQW4.js → chunk-DKSCN2AB.js} +7 -7
- package/chunks/{chunk-2JCCA2JL.js → chunk-DM5C5L5D.js} +3 -3
- package/chunks/{chunk-RWONANDA.js → chunk-DQTNI3KY.js} +5 -5
- package/chunks/{chunk-5JI7L7KV.js → chunk-EGZGZFAH.js} +10036 -12938
- package/chunks/{chunk-6LKRLK2R.js → chunk-FHC2B7LN.js} +3 -3
- package/chunks/{chunk-MYVT64FN.js → chunk-GHWODZMR.js} +2 -2
- package/chunks/{chunk-2RMLOJVB.js → chunk-GVD6SJGH.js} +2 -2
- package/chunks/{chunk-SF4KZ4O3.js → chunk-HLFS6WV2.js} +2 -2
- package/chunks/chunk-HR2TU42B.js +1228 -0
- package/chunks/{chunk-BFRB6HB2.js → chunk-HUNAPTKV.js} +3 -3
- package/chunks/chunk-IO7R7WBM.js +114 -0
- package/chunks/{chunk-WEBMRWEG.js → chunk-IXT64DV5.js} +656 -1868
- package/chunks/{chunk-3MOLBTLS.js → chunk-K2PWUPUI.js} +2 -2
- package/chunks/{chunk-WXQ6BJ6A.js → chunk-LCRTAQN2.js} +7 -7
- package/chunks/{chunk-SVJEDVYK.js → chunk-LPTRPRZR.js} +5 -5
- package/chunks/{chunk-CMKXP5RR.js → chunk-LYUAM3TG.js} +3 -3
- package/chunks/{chunk-BVAZO4WA.js → chunk-MICHDTBK.js} +3 -3
- package/chunks/{chunk-UCYRA73C.js → chunk-OAYUPGF6.js} +4 -4
- package/chunks/{chunk-XM5NLHYU.js → chunk-OWLJYJ5O.js} +14 -14
- package/chunks/{chunk-BKZFDZ23.js → chunk-QCUFBVIZ.js} +3 -3
- package/chunks/chunk-RE5EZDG2.js +5523 -0
- package/chunks/{chunk-ASUR522M.js → chunk-RRD4XXPU.js} +9 -9
- package/chunks/{chunk-AHTBZC3E.js → chunk-RSIUX3RW.js} +4 -4
- package/chunks/{chunk-BZNEY2ZS.js → chunk-SJBCK2EI.js} +15268 -16053
- package/chunks/{chunk-IOL7D5YV.js → chunk-SQCBHFWN.js} +3 -3
- package/chunks/chunk-TH2LW437.js +7829 -0
- package/chunks/{chunk-WVTBZEQO.js → chunk-TM74SSHC.js} +8 -8
- package/chunks/{chunk-U5FLXGHT.js → chunk-TO35Y326.js} +13 -729
- package/chunks/chunk-TRH2PJSN.js +547 -0
- package/chunks/{chunk-YYRBQVFE.js → chunk-TZFIAMWZ.js} +70 -16
- package/chunks/chunk-UELXHK2Y.js +1950 -0
- package/chunks/{chunk-RJWOYEOG.js → chunk-UEX7PFSE.js} +5 -5
- package/chunks/{chunk-VQG4FT5D.js → chunk-UFHN6RIU.js} +2 -2
- package/chunks/{chunk-JQHOLLTD.js → chunk-UU7PQP6N.js} +9 -9
- package/chunks/{chunk-BFR2CDV5.js → chunk-UV5QWZGE.js} +283 -153
- package/chunks/{chunk-WU6AFRAZ.js → chunk-V36HVTUL.js} +12 -12
- package/chunks/{chunk-IR537GON.js → chunk-VCSFCHAJ.js} +2 -2
- package/chunks/{chunk-YLMN3N25.js → chunk-VIT5ALXF.js} +3 -3
- package/chunks/{chunk-BATRQBOR.js → chunk-VMRRNRMR.js} +41 -41
- package/chunks/{chunk-72CISA2D.js → chunk-VNRY6AWF.js} +89 -41
- package/chunks/chunk-W6UWZFKL.js +298 -0
- package/chunks/{chunk-3KPWWJCI.js → chunk-XFCTUKXR.js} +88 -88
- package/chunks/{chunk-GMT2AZKM.js → chunk-YIQSGNAA.js} +897 -130
- package/chunks/codex-models-7TLJSY3L.js +17 -0
- package/chunks/{commands-TBC2F5CE.js → commands-NEI7L3QA.js} +2836 -1424
- package/chunks/corpus-v1.json +2 -2
- package/chunks/data/appsec-archetypes.json +2 -2
- package/chunks/data/chromium-archetypes.json +1 -1
- package/chunks/data/freebsd-archetypes.json +1 -1
- package/chunks/data/kernel-archetypes.json +2 -2
- package/chunks/db-5AP3JB4W.js +16 -0
- package/chunks/{disclose-EKTWSCGW.js → disclose-LDNKAVRH.js} +13 -11
- package/chunks/{dist-4YICS2J2.js → dist-3FNZIBB4.js} +394 -404
- package/chunks/{dist-4MAW5X6L.js → dist-5YHYNLI3.js} +6 -6
- package/chunks/{dist-FMGSR3DW.js → dist-DD4H6HMQ.js} +13 -5
- package/chunks/dist-KEULE5IQ.js +21914 -0
- package/chunks/dist-XZB53PS5.js +53 -0
- package/chunks/eval-runner-43BO2C4T.js +26 -0
- package/chunks/example-manifest.json +2 -2
- package/chunks/{exploit-agent-45YQOHPJ.js → exploit-agent-N4A5ELBK.js} +4 -4
- package/chunks/{exploit-autoclimb-UZGEMGYT.js → exploit-autoclimb-N7P6KIF5.js} +6 -6
- package/chunks/{exploit-climb-SG23KB2G.js → exploit-climb-WNEJUB5W.js} +12 -12
- package/chunks/fix-Z452M4EC.js +26 -0
- package/chunks/{github-issues-MJ6OYOOU.js → github-issues-IGTTWM7V.js} +7 -7
- package/chunks/harness-QJJJVSG4.js +22 -0
- package/chunks/http-conformance-U5F6GKYG.js +11 -0
- package/chunks/http-sender-I5XFFY35.js +10 -0
- package/chunks/hunt-scan-K6D2V3PX.js +36 -0
- package/chunks/{identity-6ZAIIWOR.js → identity-62SVRW4H.js} +5 -5
- package/chunks/{kernel-primitive-7U6CWHXD.js → kernel-primitive-TKUACPKD.js} +6 -6
- package/chunks/{kernel-vm-runner-3JAU4O6J.js → kernel-vm-runner-RAAO2PGT.js} +6 -6
- package/chunks/memsafety-scan-FCPAXIZE.js +16 -0
- package/chunks/{native-loop-RJCJPOUS.js → native-loop-2ZRJENZ3.js} +17 -18
- package/chunks/{npm-detectors-KB5Y5ZFX.js → npm-detectors-Z2ZIQCN4.js} +6 -6
- package/chunks/npm-dynamic-discovery-5J7FT3XM.js +13 -0
- package/chunks/orchestrate-2GWGNTBF.js +58 -0
- package/chunks/{pre-recon-cve-66EB6G4M.js → pre-recon-cve-X2K2P5YQ.js} +4 -4
- package/chunks/prepare-KYHGFWCJ.js +13 -0
- package/chunks/process-N245QIQG.js +12 -0
- package/chunks/{run-D56MPDKY.js → run-U3XU4CTC.js} +11507 -13632
- package/chunks/{runtime-G7YWIO3B.js → runtime-G75TEWQY.js} +10 -11
- package/chunks/runtime-XFWJTBUO.js +12 -0
- package/chunks/{scan-stream-FHI2FYZE.js → scan-stream-BMOCPKQX.js} +7 -7
- package/chunks/scope-WXI46UHJ.js +21 -0
- package/chunks/{session-store-GZ4A4KYT.js → session-store-27L3ZU73.js} +6 -6
- package/chunks/source-files-REHOM44I.js +12 -0
- package/chunks/{specdrift-WCLH6TTQ.js → specdrift-AFS54WEJ.js} +5 -5
- package/chunks/token-KRWP5JYA.js +72 -0
- package/chunks/token-util-DWTL33S3.js +8 -0
- package/chunks/variant-candidates-YWZORZMK.js +13 -0
- package/chunks/{web-recon-prepass-JJGPEOLE.js → web-recon-prepass-YVMFXCIK.js} +9 -9
- package/cli-path-traversal-fixture.js +352 -0
- package/dashboard/assets/bot-Bg1Tp9_d.js +1 -0
- package/dashboard/assets/dist-B_dDCPbu.js +1 -0
- package/dashboard/assets/findings-page-mayGhNx6.js +5 -0
- package/dashboard/assets/format--susmHX7.js +1 -0
- package/dashboard/assets/input-TuVPR3Zl.js +1 -0
- package/dashboard/assets/jsx-runtime-MGseXjj5.js +3 -0
- package/dashboard/assets/live-page-HWWHX99U.js +1 -0
- package/dashboard/assets/meta-tile-ckHo-w7k.js +1 -0
- package/dashboard/assets/operations-BxZ0OoXO.js +10 -0
- package/dashboard/assets/operations-CMFVrXEe.css +2 -0
- package/dashboard/assets/operations-app-D3d35rgo.js +46 -0
- package/dashboard/assets/overview-page-W_4IteEr.js +1 -0
- package/dashboard/assets/page-header-Bw9AJgBV.js +1 -0
- package/dashboard/assets/scans-page-CgzVXHnn.js +1 -0
- package/dashboard/assets/siren-KQj8QAnJ.js +1 -0
- package/dashboard/assets/table-8EDklulN.js +1 -0
- package/dashboard/assets/tabs-CFHPOwg8.js +1 -0
- package/dashboard/index.html +4 -5
- package/node_modules/node-addon-api/LICENSE.md +9 -0
- package/node_modules/node-addon-api/README.md +95 -0
- package/node_modules/node-addon-api/common.gypi +21 -0
- package/node_modules/node-addon-api/except.gypi +25 -0
- package/node_modules/node-addon-api/index.js +14 -0
- package/node_modules/node-addon-api/napi-inl.deprecated.h +186 -0
- package/node_modules/node-addon-api/napi-inl.h +7250 -0
- package/node_modules/node-addon-api/napi.h +3463 -0
- package/node_modules/node-addon-api/node_addon_api.gyp +42 -0
- package/node_modules/node-addon-api/node_api.gyp +9 -0
- package/node_modules/node-addon-api/noexcept.gypi +26 -0
- package/node_modules/node-addon-api/nothing.c +0 -0
- package/node_modules/node-addon-api/package-support.json +21 -0
- package/node_modules/node-addon-api/package.json +481 -0
- package/node_modules/node-addon-api/tools/README.md +73 -0
- package/node_modules/node-addon-api/tools/check-napi.js +99 -0
- package/node_modules/node-addon-api/tools/clang-format.js +71 -0
- package/node_modules/node-addon-api/tools/conversion.js +301 -0
- package/node_modules/node-gyp-build/LICENSE +21 -0
- package/node_modules/node-gyp-build/README.md +58 -0
- package/node_modules/node-gyp-build/SECURITY.md +5 -0
- package/node_modules/node-gyp-build/bin.js +84 -0
- package/node_modules/node-gyp-build/build-test.js +19 -0
- package/node_modules/node-gyp-build/index.js +6 -0
- package/node_modules/node-gyp-build/node-gyp-build.js +207 -0
- package/node_modules/node-gyp-build/optional.js +7 -0
- package/node_modules/node-gyp-build/package.json +43 -0
- package/node_modules/tree-sitter/LICENSE +21 -0
- package/node_modules/tree-sitter/README.md +90 -0
- package/node_modules/tree-sitter/binding.gyp +76 -0
- package/node_modules/tree-sitter/index.js +895 -0
- package/node_modules/tree-sitter/package.json +62 -0
- package/node_modules/tree-sitter/prebuilds/darwin-arm64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/darwin-x64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/linux-x64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/win32-x64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/src/addon_data.h +47 -0
- package/node_modules/tree-sitter/src/binding.cc +35 -0
- package/node_modules/tree-sitter/src/conversions.cc +140 -0
- package/node_modules/tree-sitter/src/conversions.h +22 -0
- package/node_modules/tree-sitter/src/language.cc +106 -0
- package/node_modules/tree-sitter/src/language.h +17 -0
- package/node_modules/tree-sitter/src/logger.cc +70 -0
- package/node_modules/tree-sitter/src/logger.h +19 -0
- package/node_modules/tree-sitter/src/lookaheaditerator.cc +122 -0
- package/node_modules/tree-sitter/src/lookaheaditerator.h +33 -0
- package/node_modules/tree-sitter/src/node.cc +1056 -0
- package/node_modules/tree-sitter/src/node.h +30 -0
- package/node_modules/tree-sitter/src/parser.cc +298 -0
- package/node_modules/tree-sitter/src/parser.h +35 -0
- package/node_modules/tree-sitter/src/query.cc +383 -0
- package/node_modules/tree-sitter/src/query.h +39 -0
- package/node_modules/tree-sitter/src/tree.cc +307 -0
- package/node_modules/tree-sitter/src/tree.h +45 -0
- package/node_modules/tree-sitter/src/tree_cursor.cc +213 -0
- package/node_modules/tree-sitter/src/tree_cursor.h +52 -0
- package/node_modules/tree-sitter/tree-sitter.d.ts +211 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/LICENSE +21 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/README.md +21 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/README.md +6 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/include/tree_sitter/api.h +1266 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.c +48 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.h +41 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/array.h +290 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/atomic.h +68 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/clock.h +146 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/error_costs.h +11 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.c +501 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.h +36 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/host.h +21 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.c +221 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.h +299 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/length.h +52 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.c +419 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.h +49 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lib.c +14 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/node.c +774 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.c +2151 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.h +230 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/point.h +62 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/query.c +4134 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reduce_action.h +34 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reusable_node.h +95 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.c +899 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.h +133 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.c +1060 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.h +382 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.c +165 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.h +31 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.c +714 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.h +48 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ICU_SHA +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/LICENSE +414 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/README.md +29 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ptypes.h +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/umachine.h +448 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/urename.h +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf.h +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf16.h +733 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf8.h +881 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode.h +50 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib-symbols.txt +23 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib.c +109 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/wasm-stdlib.h +1294 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.c +1823 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.h +31 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/test/fixtures/grammars/.gitkeep +0 -0
- package/node_modules/tree-sitter-c/LICENSE +21 -0
- package/node_modules/tree-sitter-c/README.md +18 -0
- package/node_modules/tree-sitter-c/binding.gyp +20 -0
- package/node_modules/tree-sitter-c/bindings/node/binding.cc +20 -0
- package/node_modules/tree-sitter-c/bindings/node/index.d.ts +28 -0
- package/node_modules/tree-sitter-c/bindings/node/index.js +7 -0
- package/node_modules/tree-sitter-c/grammar.js +1463 -0
- package/node_modules/tree-sitter-c/package.json +108 -0
- package/node_modules/tree-sitter-c/prebuilds/darwin-arm64/tree-sitter-c.node +0 -0
- package/node_modules/tree-sitter-c/prebuilds/darwin-x64/tree-sitter-c.node +0 -0
- package/node_modules/tree-sitter-c/prebuilds/linux-x64/tree-sitter-c.node +0 -0
- package/node_modules/tree-sitter-c/prebuilds/win32-x64/tree-sitter-c.node +0 -0
- package/node_modules/tree-sitter-c/queries/highlights.scm +81 -0
- package/node_modules/tree-sitter-c/queries/tags.scm +9 -0
- package/node_modules/tree-sitter-c/src/grammar.json +9682 -0
- package/node_modules/tree-sitter-c/src/node-types.json +4556 -0
- package/node_modules/tree-sitter-c/src/parser.c +113852 -0
- package/node_modules/tree-sitter-c/src/tree_sitter/alloc.h +54 -0
- package/node_modules/tree-sitter-c/src/tree_sitter/array.h +290 -0
- package/node_modules/tree-sitter-c/src/tree_sitter/parser.h +265 -0
- package/package.json +20 -13
- package/vendor/tree-sitter-0.21.1-node24.json +16 -0
- package/vendor/tree-sitter-0.21.1-node24.tgz +0 -0
- package/chunks/adapt-loop-SMH6V4PD.js +0 -18
- package/chunks/appsec-catalog-CBWHGTEL.js +0 -24
- package/chunks/chunk-242TMK6G.js +0 -110
- package/chunks/chunk-57ZENEX2.js +0 -169
- package/chunks/chunk-ADOLI6DT.js +0 -102
- package/chunks/chunk-ATATQACO.js +0 -471
- package/chunks/chunk-C2WXWFBB.js +0 -1070
- package/chunks/chunk-F3WBKITT.js +0 -687
- package/chunks/chunk-H2FFLZNK.js +0 -3
- package/chunks/chunk-LP3HHYQU.js +0 -245
- package/chunks/chunk-QI233I24.js +0 -333
- package/chunks/chunk-RRMJC3ZE.js +0 -105
- package/chunks/chunk-Z5FA2XOX.js +0 -2798
- package/chunks/cost-ledger-NU63MYZM.js +0 -13
- package/chunks/db-KFWOAUUB.js +0 -16
- package/chunks/eval-runner-7ZF472KV.js +0 -27
- package/chunks/fix-IG7LYXH3.js +0 -12
- package/chunks/harness-7ODOLOWU.js +0 -22
- package/chunks/http-conformance-DU66MZIU.js +0 -11
- package/chunks/http-sender-GWH2IYEA.js +0 -10
- package/chunks/hunt-scan-MMKUOETU.js +0 -38
- package/chunks/memsafety-scan-J7SECV5W.js +0 -16
- package/chunks/npm-dynamic-discovery-AHROOZDB.js +0 -13
- package/chunks/orchestrate-OC2VZN2X.js +0 -62
- package/chunks/pipeline-BZK5BLJR.js +0 -14
- package/chunks/prepare-MYY743TK.js +0 -13
- package/chunks/process-LQRCS5OY.js +0 -13
- package/chunks/replay-runner-45G3VU7X.js +0 -39
- package/chunks/runtime-J7PLXZNM.js +0 -12
- package/chunks/scope-BI7BF4ZY.js +0 -18
- package/chunks/source-files-PWRQR6LY.js +0 -12
- package/chunks/variant-candidates-YERCYMPD.js +0 -13
- package/dashboard/assets/0sec-icon-66SreztZ.gif +0 -0
- package/dashboard/assets/bot-yILPnRgD.js +0 -1
- package/dashboard/assets/chevron-down-BeDJ-Vka.js +0 -1
- package/dashboard/assets/circle-alert-BEnMBMT-.js +0 -1
- package/dashboard/assets/client-DRYsuOGl.js +0 -9
- package/dashboard/assets/copy-Bi5vzoF9.js +0 -1
- package/dashboard/assets/desktop-CXTQonNm.js +0 -32
- package/dashboard/assets/desktop-NOekk4QS.css +0 -1
- package/dashboard/assets/dist-CmX-h7a4.js +0 -1
- package/dashboard/assets/dist-DAwYQmf_.js +0 -45
- package/dashboard/assets/findings-page-CACW9nw2.js +0 -5
- package/dashboard/assets/format-PoISqsES.js +0 -1
- package/dashboard/assets/jsx-runtime-C7oxC63R.js +0 -1
- package/dashboard/assets/live-page-DrgQqQK5.js +0 -1
- package/dashboard/assets/meta-tile-CcskIV_o.js +0 -1
- package/dashboard/assets/operations-BKE8T-vY.css +0 -2
- package/dashboard/assets/operations-D8nUP5_m.js +0 -4
- package/dashboard/assets/operations-app-CQQhG54n.js +0 -2
- package/dashboard/assets/overview-page-DTGS8dPo.js +0 -1
- package/dashboard/assets/page-header-MFVvEtZW.js +0 -1
- package/dashboard/assets/play-Dwo-9xt6.js +0 -1
- package/dashboard/assets/scans-page-ChVtq8Us.js +0 -1
- package/dashboard/assets/search-CiooTLck.js +0 -1
- package/dashboard/assets/siren-CCBwTSuk.js +0 -1
- package/dashboard/assets/table-BYS-nIVA.js +0 -1
- package/dashboard/assets/tabs-DivxbhQy.js +0 -1
- package/dashboard/desktop.html +0 -21
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { createRequire as
|
|
3
|
-
const require =
|
|
2
|
+
import { createRequire as __0CreateRequire } from "node:module";
|
|
3
|
+
const require = __0CreateRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
__commonJS,
|
|
6
6
|
__require
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-VCSFCHAJ.js";
|
|
8
8
|
|
|
9
9
|
// node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/nodes/identity.js
|
|
10
10
|
var require_identity = __commonJS({
|
|
@@ -7393,1917 +7393,718 @@ function analyzeFindingForKnownMarkers(finding) {
|
|
|
7393
7393
|
};
|
|
7394
7394
|
}
|
|
7395
7395
|
|
|
7396
|
-
// packages/core/dist/disclose/
|
|
7397
|
-
|
|
7398
|
-
|
|
7399
|
-
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
|
|
7417
|
-
{ id: "CWE-284", name: "Improper Access Control", role: "primary" },
|
|
7418
|
-
{ id: "CWE-441", name: "Unintended Proxy or Intermediary ('Confused Deputy')", role: "secondary" },
|
|
7419
|
-
{ id: "CWE-285", name: "Improper Authorization", role: "secondary" }
|
|
7420
|
-
],
|
|
7421
|
-
"output-manipulation": [
|
|
7422
|
-
{ id: "CWE-116", name: "Improper Encoding or Escaping of Output", role: "primary" },
|
|
7423
|
-
{ id: "CWE-74", name: "Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection')", role: "secondary" }
|
|
7424
|
-
],
|
|
7425
|
-
"encoding-bypass": [
|
|
7426
|
-
{ id: "CWE-176", name: "Improper Handling of Unicode Encoding", role: "primary" },
|
|
7427
|
-
{ id: "CWE-20", name: "Improper Input Validation", role: "secondary" }
|
|
7428
|
-
],
|
|
7429
|
-
"multi-turn": [
|
|
7430
|
-
{ id: "CWE-1039", name: "Inadequate Detection or Handling of Adversarial Input Perturbations in AI/ML Classifier", role: "primary" },
|
|
7431
|
-
{ id: "CWE-841", name: "Improper Enforcement of Behavioral Workflow", role: "secondary" }
|
|
7432
|
-
],
|
|
7433
|
-
// Source-code audit
|
|
7434
|
-
"prototype-pollution": [
|
|
7435
|
-
{ id: "CWE-1321", name: "Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')", role: "primary" },
|
|
7436
|
-
{ id: "CWE-915", name: "Improperly Controlled Modification of Dynamically-Determined Object Attributes", role: "secondary" }
|
|
7437
|
-
],
|
|
7438
|
-
"path-traversal": [
|
|
7439
|
-
{ id: "CWE-22", name: "Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')", role: "primary" },
|
|
7440
|
-
{ id: "CWE-73", name: "External Control of File Name or Path", role: "secondary" },
|
|
7441
|
-
{ id: "CWE-284", name: "Improper Access Control", role: "secondary" }
|
|
7442
|
-
],
|
|
7443
|
-
"command-injection": [
|
|
7444
|
-
{ id: "CWE-78", name: "Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')", role: "primary" },
|
|
7445
|
-
{ id: "CWE-77", name: "Improper Neutralization of Special Elements used in a Command ('Command Injection')", role: "secondary" }
|
|
7446
|
-
],
|
|
7447
|
-
"code-injection": [
|
|
7448
|
-
{ id: "CWE-94", name: "Improper Control of Generation of Code ('Code Injection')", role: "primary" },
|
|
7449
|
-
{ id: "CWE-95", name: "Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')", role: "secondary" }
|
|
7450
|
-
],
|
|
7451
|
-
"regex-dos": [
|
|
7452
|
-
{ id: "CWE-1333", name: "Inefficient Regular Expression Complexity", role: "primary" },
|
|
7453
|
-
{ id: "CWE-400", name: "Uncontrolled Resource Consumption", role: "secondary" }
|
|
7454
|
-
],
|
|
7455
|
-
"unsafe-deserialization": [
|
|
7456
|
-
{ id: "CWE-502", name: "Deserialization of Untrusted Data", role: "primary" },
|
|
7457
|
-
{ id: "CWE-915", name: "Improperly Controlled Modification of Dynamically-Determined Object Attributes", role: "secondary" }
|
|
7458
|
-
],
|
|
7459
|
-
"information-disclosure": [
|
|
7460
|
-
{ id: "CWE-200", name: "Exposure of Sensitive Information to an Unauthorized Actor", role: "primary" },
|
|
7461
|
-
{ id: "CWE-285", name: "Improper Authorization", role: "secondary" },
|
|
7462
|
-
{ id: "CWE-522", name: "Insufficiently Protected Credentials", role: "secondary" }
|
|
7463
|
-
],
|
|
7464
|
-
"ssrf": [
|
|
7465
|
-
{ id: "CWE-918", name: "Server-Side Request Forgery (SSRF)", role: "primary" },
|
|
7466
|
-
{ id: "CWE-20", name: "Improper Input Validation", role: "secondary" },
|
|
7467
|
-
{ id: "CWE-441", name: "Unintended Proxy or Intermediary ('Confused Deputy')", role: "secondary" }
|
|
7468
|
-
],
|
|
7469
|
-
"sql-injection": [
|
|
7470
|
-
{ id: "CWE-89", name: "Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')", role: "primary" }
|
|
7471
|
-
],
|
|
7472
|
-
"xss": [
|
|
7473
|
-
{ id: "CWE-79", name: "Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')", role: "primary" },
|
|
7474
|
-
{ id: "CWE-80", name: "Improper Neutralization of Script-Related HTML Tags in a Web Page (Basic XSS)", role: "secondary" }
|
|
7475
|
-
],
|
|
7476
|
-
"cors": [
|
|
7477
|
-
{ id: "CWE-942", name: "Permissive Cross-domain Policy with Untrusted Domains", role: "primary" },
|
|
7478
|
-
{ id: "CWE-346", name: "Origin Validation Error", role: "secondary" }
|
|
7479
|
-
],
|
|
7480
|
-
"security-misconfiguration": [
|
|
7481
|
-
{ id: "CWE-1188", name: "Initialization of a Resource with an Insecure Default", role: "primary" },
|
|
7482
|
-
{ id: "CWE-16", name: "Configuration", role: "secondary" }
|
|
7483
|
-
],
|
|
7484
|
-
"missing-validation": [
|
|
7485
|
-
{ id: "CWE-20", name: "Improper Input Validation", role: "primary" }
|
|
7486
|
-
],
|
|
7487
|
-
"crypto-misuse": [
|
|
7488
|
-
{ id: "CWE-327", name: "Use of a Broken or Risky Cryptographic Algorithm", role: "primary" },
|
|
7489
|
-
{ id: "CWE-328", name: "Use of Weak Hash", role: "secondary" },
|
|
7490
|
-
{ id: "CWE-321", name: "Use of Hard-coded Cryptographic Key", role: "secondary" },
|
|
7491
|
-
{ id: "CWE-329", name: "Generation of Predictable IV with CBC Mode", role: "secondary" },
|
|
7492
|
-
{ id: "CWE-330", name: "Use of Insufficiently Random Values", role: "secondary" },
|
|
7493
|
-
{ id: "CWE-347", name: "Improper Verification of Cryptographic Signature", role: "secondary" }
|
|
7494
|
-
],
|
|
7495
|
-
// Memory corruption / binary
|
|
7496
|
-
"heap-overflow": [
|
|
7497
|
-
{ id: "CWE-122", name: "Heap-based Buffer Overflow", role: "primary" },
|
|
7498
|
-
{ id: "CWE-787", name: "Out-of-bounds Write", role: "secondary" }
|
|
7499
|
-
],
|
|
7500
|
-
"out-of-bounds-read": [
|
|
7501
|
-
{ id: "CWE-125", name: "Out-of-bounds Read", role: "primary" }
|
|
7502
|
-
],
|
|
7503
|
-
"out-of-bounds-write": [
|
|
7504
|
-
{ id: "CWE-787", name: "Out-of-bounds Write", role: "primary" },
|
|
7505
|
-
{ id: "CWE-122", name: "Heap-based Buffer Overflow", role: "secondary" }
|
|
7506
|
-
],
|
|
7507
|
-
"use-after-free": [
|
|
7508
|
-
{ id: "CWE-416", name: "Use After Free", role: "primary" },
|
|
7509
|
-
{ id: "CWE-672", name: "Operation on a Resource after Expiration or Release", role: "secondary" }
|
|
7510
|
-
],
|
|
7511
|
-
"stack-buffer-overflow": [
|
|
7512
|
-
{ id: "CWE-121", name: "Stack-based Buffer Overflow", role: "primary" },
|
|
7513
|
-
{ id: "CWE-787", name: "Out-of-bounds Write", role: "secondary" }
|
|
7514
|
-
],
|
|
7515
|
-
"null-pointer-deref": [
|
|
7516
|
-
{ id: "CWE-476", name: "NULL Pointer Dereference", role: "primary" }
|
|
7517
|
-
],
|
|
7518
|
-
"null-deref": [
|
|
7519
|
-
{ id: "CWE-476", name: "NULL Pointer Dereference", role: "primary" }
|
|
7520
|
-
],
|
|
7521
|
-
"integer-overflow": [
|
|
7522
|
-
{ id: "CWE-190", name: "Integer Overflow or Wraparound", role: "primary" },
|
|
7523
|
-
{ id: "CWE-191", name: "Integer Underflow (Wrap or Wraparound)", role: "secondary" }
|
|
7524
|
-
],
|
|
7525
|
-
"integer-truncation": [
|
|
7526
|
-
{ id: "CWE-197", name: "Numeric Truncation Error", role: "primary" },
|
|
7527
|
-
{ id: "CWE-681", name: "Incorrect Conversion between Numeric Types", role: "secondary" }
|
|
7528
|
-
],
|
|
7529
|
-
"denial-of-service": [
|
|
7530
|
-
{ id: "CWE-400", name: "Uncontrolled Resource Consumption", role: "primary" },
|
|
7531
|
-
{ id: "CWE-833", name: "Deadlock", role: "secondary" }
|
|
7532
|
-
],
|
|
7533
|
-
"race-condition": [
|
|
7534
|
-
{ id: "CWE-362", name: "Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')", role: "primary" },
|
|
7535
|
-
{ id: "CWE-367", name: "Time-of-check Time-of-use (TOCTOU) Race Condition", role: "secondary" }
|
|
7536
|
-
],
|
|
7537
|
-
"toctou": [
|
|
7538
|
-
{ id: "CWE-367", name: "Time-of-check Time-of-use (TOCTOU) Race Condition", role: "primary" },
|
|
7539
|
-
{ id: "CWE-362", name: "Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')", role: "secondary" }
|
|
7540
|
-
],
|
|
7541
|
-
"type-confusion": [
|
|
7542
|
-
{ id: "CWE-843", name: "Access of Resource Using Incompatible Type ('Type Confusion')", role: "primary" }
|
|
7543
|
-
],
|
|
7544
|
-
"double-free": [
|
|
7545
|
-
{ id: "CWE-415", name: "Double Free", role: "primary" }
|
|
7546
|
-
],
|
|
7547
|
-
"format-string": [
|
|
7548
|
-
{ id: "CWE-134", name: "Use of Externally-Controlled Format String", role: "primary" }
|
|
7549
|
-
],
|
|
7550
|
-
"uninitialized-memory": [
|
|
7551
|
-
{ id: "CWE-457", name: "Use of Uninitialized Variable", role: "primary" },
|
|
7552
|
-
{ id: "CWE-908", name: "Use of Uninitialized Resource", role: "secondary" }
|
|
7553
|
-
],
|
|
7554
|
-
// Supply-chain / package
|
|
7555
|
-
"known-vulnerable-package": [
|
|
7556
|
-
{ id: "CWE-1395", name: "Dependency on Vulnerable Third-Party Component", role: "primary" },
|
|
7557
|
-
{ id: "CWE-1104", name: "Use of Unmaintained Third Party Components", role: "secondary" },
|
|
7558
|
-
{ id: "CWE-937", name: "OWASP Top Ten 2013 Category A9 - Using Components with Known Vulnerabilities", role: "secondary" }
|
|
7559
|
-
],
|
|
7560
|
-
"supply-chain": [
|
|
7561
|
-
{ id: "CWE-1357", name: "Reliance on Insufficiently Trustworthy Component", role: "primary" },
|
|
7562
|
-
{ id: "CWE-506", name: "Embedded Malicious Code", role: "secondary" },
|
|
7563
|
-
{ id: "CWE-829", name: "Inclusion of Functionality from Untrusted Control Sphere", role: "secondary" }
|
|
7564
|
-
],
|
|
7565
|
-
"other": [
|
|
7566
|
-
{ id: "CWE-693", name: "Protection Mechanism Failure", role: "primary" }
|
|
7567
|
-
]
|
|
7568
|
-
};
|
|
7569
|
-
function suggestCwesForCategory(category) {
|
|
7570
|
-
return CWE_MAP[category] ?? [
|
|
7571
|
-
{ id: "CWE-693", name: "Protection Mechanism Failure", role: "primary" }
|
|
7572
|
-
];
|
|
7573
|
-
}
|
|
7574
|
-
function formatCweSection(entries) {
|
|
7575
|
-
if (entries.length === 0)
|
|
7576
|
-
return "";
|
|
7577
|
-
const lines = ["# CWE", ""];
|
|
7578
|
-
lines.push("Pick these in the GHSA form's CWE selector (multi-select):");
|
|
7579
|
-
lines.push("");
|
|
7580
|
-
for (const entry of entries) {
|
|
7581
|
-
const emphasis = entry.role === "primary" ? " *(primary)*" : "";
|
|
7582
|
-
lines.push(`- **${entry.id}**: ${entry.name}${emphasis}`);
|
|
7396
|
+
// packages/core/dist/disclose/poc-runtime.js
|
|
7397
|
+
import { spawn } from "node:child_process";
|
|
7398
|
+
var MAX_CAPTURE_BYTES = 1024 * 1024;
|
|
7399
|
+
var DEFAULT_STEP_TIMEOUT_MS = 3e4;
|
|
7400
|
+
var PERSONA_HEADER = "X-0-Persona";
|
|
7401
|
+
var TRUNCATION_MARKER = "\n\u2026[truncated at 1MiB]";
|
|
7402
|
+
var DEFAULT_RPS_PER_HOST = 2;
|
|
7403
|
+
var MAX_REDIRECT_HOPS = 5;
|
|
7404
|
+
var hostBuckets = /* @__PURE__ */ new Map();
|
|
7405
|
+
function getOrInitBucket(host, rps) {
|
|
7406
|
+
let bucket = hostBuckets.get(host);
|
|
7407
|
+
if (!bucket) {
|
|
7408
|
+
bucket = {
|
|
7409
|
+
tokens: rps,
|
|
7410
|
+
// full bucket on first use
|
|
7411
|
+
refillRatePerMs: rps / 1e3,
|
|
7412
|
+
capacity: rps,
|
|
7413
|
+
lastRefill: Date.now(),
|
|
7414
|
+
retryUntil: 0
|
|
7415
|
+
};
|
|
7416
|
+
hostBuckets.set(host, bucket);
|
|
7583
7417
|
}
|
|
7584
|
-
return
|
|
7585
|
-
}
|
|
7586
|
-
|
|
7587
|
-
// packages/core/dist/disclose/cvss.js
|
|
7588
|
-
var IMPACT_BY_CATEGORY = {
|
|
7589
|
-
"prompt-injection": { C: "L", I: "L", A: "N", scope: "U" },
|
|
7590
|
-
"jailbreak": { C: "L", I: "L", A: "N", scope: "U" },
|
|
7591
|
-
"system-prompt-extraction": { C: "H", I: "N", A: "N", scope: "U" },
|
|
7592
|
-
"data-exfiltration": { C: "H", I: "N", A: "N", scope: "C" },
|
|
7593
|
-
"tool-misuse": { C: "H", I: "H", A: "L", scope: "C" },
|
|
7594
|
-
"output-manipulation": { C: "L", I: "H", A: "N", scope: "U" },
|
|
7595
|
-
"encoding-bypass": { C: "L", I: "L", A: "N", scope: "U" },
|
|
7596
|
-
"multi-turn": { C: "L", I: "L", A: "N", scope: "U" },
|
|
7597
|
-
"prototype-pollution": { C: "H", I: "H", A: "H", scope: "U" },
|
|
7598
|
-
"path-traversal": { C: "H", I: "H", A: "L", scope: "U" },
|
|
7599
|
-
"command-injection": { C: "H", I: "H", A: "H", scope: "U" },
|
|
7600
|
-
"code-injection": { C: "H", I: "H", A: "H", scope: "U" },
|
|
7601
|
-
"regex-dos": { C: "N", I: "N", A: "H", scope: "U" },
|
|
7602
|
-
"unsafe-deserialization": { C: "H", I: "H", A: "H", scope: "U" },
|
|
7603
|
-
"information-disclosure": { C: "H", I: "N", A: "N", scope: "C" },
|
|
7604
|
-
"ssrf": { C: "H", I: "N", A: "N", scope: "C" },
|
|
7605
|
-
"sql-injection": { C: "H", I: "H", A: "H", scope: "U" },
|
|
7606
|
-
"xss": { C: "L", I: "L", A: "N", scope: "C" },
|
|
7607
|
-
"cors": { C: "L", I: "L", A: "N", scope: "U" },
|
|
7608
|
-
"security-misconfiguration": { C: "L", I: "L", A: "N", scope: "U" },
|
|
7609
|
-
"missing-validation": { C: "L", I: "L", A: "L", scope: "U" },
|
|
7610
|
-
"crypto-misuse": { C: "H", I: "H", A: "N", scope: "U" },
|
|
7611
|
-
"heap-overflow": { C: "H", I: "H", A: "H", scope: "U" },
|
|
7612
|
-
"out-of-bounds-read": { C: "H", I: "N", A: "L", scope: "U" },
|
|
7613
|
-
"out-of-bounds-write": { C: "H", I: "H", A: "H", scope: "U" },
|
|
7614
|
-
"use-after-free": { C: "H", I: "H", A: "H", scope: "U" },
|
|
7615
|
-
"stack-buffer-overflow": { C: "H", I: "H", A: "H", scope: "U" },
|
|
7616
|
-
"null-pointer-deref": { C: "N", I: "N", A: "H", scope: "U" },
|
|
7617
|
-
"null-deref": { C: "N", I: "N", A: "H", scope: "U" },
|
|
7618
|
-
"integer-overflow": { C: "L", I: "L", A: "L", scope: "U" },
|
|
7619
|
-
"integer-truncation": { C: "L", I: "L", A: "L", scope: "U" },
|
|
7620
|
-
"race-condition": { C: "L", I: "L", A: "L", scope: "U" },
|
|
7621
|
-
"denial-of-service": { C: "N", I: "N", A: "H", scope: "U" },
|
|
7622
|
-
"toctou": { C: "L", I: "L", A: "L", scope: "U" },
|
|
7623
|
-
"type-confusion": { C: "H", I: "H", A: "H", scope: "U" },
|
|
7624
|
-
"double-free": { C: "H", I: "H", A: "H", scope: "U" },
|
|
7625
|
-
"format-string": { C: "H", I: "H", A: "H", scope: "U" },
|
|
7626
|
-
"uninitialized-memory": { C: "H", I: "N", A: "L", scope: "U" },
|
|
7627
|
-
"known-vulnerable-package": { C: "L", I: "L", A: "L", scope: "U" },
|
|
7628
|
-
"supply-chain": { C: "H", I: "H", A: "H", scope: "C" },
|
|
7629
|
-
"other": { C: "L", I: "L", A: "L", scope: "U" }
|
|
7630
|
-
};
|
|
7631
|
-
var W = {
|
|
7632
|
-
AV: { N: 0.85, A: 0.62, L: 0.55, P: 0.2 },
|
|
7633
|
-
AC: { L: 0.77, H: 0.44 },
|
|
7634
|
-
PR_U: { N: 0.85, L: 0.62, H: 0.27 },
|
|
7635
|
-
PR_C: { N: 0.85, L: 0.68, H: 0.5 },
|
|
7636
|
-
UI: { N: 0.85, R: 0.62 },
|
|
7637
|
-
CIA: { N: 0, L: 0.22, H: 0.56 }
|
|
7638
|
-
};
|
|
7639
|
-
function roundUp(n) {
|
|
7640
|
-
return Math.ceil(n * 10) / 10;
|
|
7641
|
-
}
|
|
7642
|
-
function computeBaseScore(av, ac, pr, ui, scope, c, i, a) {
|
|
7643
|
-
const iss = 1 - (1 - W.CIA[c]) * (1 - W.CIA[i]) * (1 - W.CIA[a]);
|
|
7644
|
-
const impact = scope === "U" ? 6.42 * iss : 7.52 * (iss - 0.029) - 3.25 * Math.pow(iss - 0.02, 15);
|
|
7645
|
-
const prWeight = (scope === "C" ? W.PR_C : W.PR_U)[pr];
|
|
7646
|
-
const exploit = 8.22 * W.AV[av] * W.AC[ac] * prWeight * W.UI[ui];
|
|
7647
|
-
if (impact <= 0)
|
|
7648
|
-
return 0;
|
|
7649
|
-
const base = scope === "U" ? Math.min(impact + exploit, 10) : Math.min(1.08 * (impact + exploit), 10);
|
|
7650
|
-
return roundUp(base);
|
|
7418
|
+
return bucket;
|
|
7651
7419
|
}
|
|
7652
|
-
function
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
|
|
7656
|
-
|
|
7657
|
-
|
|
7658
|
-
case "medium":
|
|
7659
|
-
case "low":
|
|
7660
|
-
return "L";
|
|
7661
|
-
default:
|
|
7662
|
-
return "H";
|
|
7420
|
+
function refill(bucket) {
|
|
7421
|
+
const now = Date.now();
|
|
7422
|
+
const elapsed = now - bucket.lastRefill;
|
|
7423
|
+
if (elapsed > 0) {
|
|
7424
|
+
bucket.tokens = Math.min(bucket.capacity, bucket.tokens + elapsed * bucket.refillRatePerMs);
|
|
7425
|
+
bucket.lastRefill = now;
|
|
7663
7426
|
}
|
|
7664
7427
|
}
|
|
7665
|
-
function
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7428
|
+
async function acquireHostToken(host, rps) {
|
|
7429
|
+
const bucket = getOrInitBucket(host, rps);
|
|
7430
|
+
while (Date.now() < bucket.retryUntil) {
|
|
7431
|
+
const waitMs = bucket.retryUntil - Date.now();
|
|
7432
|
+
await sleep(Math.min(waitMs, 1e3));
|
|
7433
|
+
}
|
|
7434
|
+
while (true) {
|
|
7435
|
+
refill(bucket);
|
|
7436
|
+
if (bucket.tokens >= 1) {
|
|
7437
|
+
bucket.tokens -= 1;
|
|
7438
|
+
return;
|
|
7439
|
+
}
|
|
7440
|
+
const tokensNeeded = 1 - bucket.tokens;
|
|
7441
|
+
const waitMs = Math.max(1, Math.ceil(tokensNeeded / bucket.refillRatePerMs));
|
|
7442
|
+
await sleep(waitMs);
|
|
7679
7443
|
}
|
|
7680
7444
|
}
|
|
7681
|
-
function
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
7685
|
-
const
|
|
7686
|
-
const
|
|
7687
|
-
|
|
7688
|
-
const av = assessed?.av ?? "N";
|
|
7689
|
-
const pr = assessed?.pr ?? prForSeverity(finding.severity);
|
|
7690
|
-
const ui = assessed?.ui ?? "N";
|
|
7691
|
-
const vector = `CVSS:3.1/AV:${av}/AC:${ac}/PR:${pr}/UI:${ui}/S:${impact.scope}/C:${impact.C}/I:${impact.I}/A:${impact.A}`;
|
|
7692
|
-
const score = computeBaseScore(av, ac, pr, ui, impact.scope, impact.C, impact.I, impact.A);
|
|
7693
|
-
return { vector, score, source: assessed ? "impact-assessment" : "heuristic" };
|
|
7445
|
+
function markHostRateLimited(host, retryAfterHeader) {
|
|
7446
|
+
const bucket = hostBuckets.get(host);
|
|
7447
|
+
if (!bucket)
|
|
7448
|
+
return;
|
|
7449
|
+
const parsed = retryAfterHeader ? parseInt(retryAfterHeader, 10) : NaN;
|
|
7450
|
+
const retryAfterMs = Number.isFinite(parsed) && parsed > 0 ? parsed * 1e3 : 0;
|
|
7451
|
+
bucket.retryUntil = Date.now() + Math.max(retryAfterMs, 6e4);
|
|
7694
7452
|
}
|
|
7695
|
-
|
|
7696
|
-
|
|
7697
|
-
super(message);
|
|
7698
|
-
this.name = "Cvss4ParseError";
|
|
7699
|
-
}
|
|
7700
|
-
};
|
|
7701
|
-
var CVSS4_ALLOWED = {
|
|
7702
|
-
AV: /* @__PURE__ */ new Set(["N", "A", "L", "P"]),
|
|
7703
|
-
AC: /* @__PURE__ */ new Set(["L", "H"]),
|
|
7704
|
-
AT: /* @__PURE__ */ new Set(["N", "P"]),
|
|
7705
|
-
PR: /* @__PURE__ */ new Set(["N", "L", "H"]),
|
|
7706
|
-
UI: /* @__PURE__ */ new Set(["N", "P", "A"]),
|
|
7707
|
-
VC: /* @__PURE__ */ new Set(["H", "L", "N"]),
|
|
7708
|
-
VI: /* @__PURE__ */ new Set(["H", "L", "N"]),
|
|
7709
|
-
VA: /* @__PURE__ */ new Set(["H", "L", "N"]),
|
|
7710
|
-
SC: /* @__PURE__ */ new Set(["H", "L", "N"]),
|
|
7711
|
-
SI: /* @__PURE__ */ new Set(["H", "L", "N"]),
|
|
7712
|
-
SA: /* @__PURE__ */ new Set(["H", "L", "N"]),
|
|
7713
|
-
// Threat
|
|
7714
|
-
E: /* @__PURE__ */ new Set(["X", "A", "P", "U"]),
|
|
7715
|
-
// Environmental (requirements)
|
|
7716
|
-
CR: /* @__PURE__ */ new Set(["X", "H", "M", "L"]),
|
|
7717
|
-
IR: /* @__PURE__ */ new Set(["X", "H", "M", "L"]),
|
|
7718
|
-
AR: /* @__PURE__ */ new Set(["X", "H", "M", "L"]),
|
|
7719
|
-
// Environmental (modified base)
|
|
7720
|
-
MAV: /* @__PURE__ */ new Set(["X", "N", "A", "L", "P"]),
|
|
7721
|
-
MAC: /* @__PURE__ */ new Set(["X", "L", "H"]),
|
|
7722
|
-
MAT: /* @__PURE__ */ new Set(["X", "N", "P"]),
|
|
7723
|
-
MPR: /* @__PURE__ */ new Set(["X", "N", "L", "H"]),
|
|
7724
|
-
MUI: /* @__PURE__ */ new Set(["X", "N", "P", "A"]),
|
|
7725
|
-
MVC: /* @__PURE__ */ new Set(["X", "H", "L", "N"]),
|
|
7726
|
-
MVI: /* @__PURE__ */ new Set(["X", "H", "L", "N"]),
|
|
7727
|
-
MVA: /* @__PURE__ */ new Set(["X", "H", "L", "N"]),
|
|
7728
|
-
MSC: /* @__PURE__ */ new Set(["X", "H", "L", "N"]),
|
|
7729
|
-
MSI: /* @__PURE__ */ new Set(["X", "S", "H", "L", "N"]),
|
|
7730
|
-
MSA: /* @__PURE__ */ new Set(["X", "S", "H", "L", "N"]),
|
|
7731
|
-
// Supplemental (do not affect score)
|
|
7732
|
-
S: /* @__PURE__ */ new Set(["X", "N", "P"]),
|
|
7733
|
-
AU: /* @__PURE__ */ new Set(["X", "N", "Y"]),
|
|
7734
|
-
R: /* @__PURE__ */ new Set(["X", "A", "U", "I"]),
|
|
7735
|
-
V: /* @__PURE__ */ new Set(["X", "D", "C"]),
|
|
7736
|
-
RE: /* @__PURE__ */ new Set(["X", "L", "M", "H"]),
|
|
7737
|
-
U: /* @__PURE__ */ new Set(["X", "Clear", "Green", "Amber", "Red"])
|
|
7738
|
-
};
|
|
7739
|
-
var CVSS4_BASE_KEYS = [
|
|
7740
|
-
"AV",
|
|
7741
|
-
"AC",
|
|
7742
|
-
"AT",
|
|
7743
|
-
"PR",
|
|
7744
|
-
"UI",
|
|
7745
|
-
"VC",
|
|
7746
|
-
"VI",
|
|
7747
|
-
"VA",
|
|
7748
|
-
"SC",
|
|
7749
|
-
"SI",
|
|
7750
|
-
"SA"
|
|
7751
|
-
];
|
|
7752
|
-
var AV_levels = { N: 0, A: 0.1, L: 0.2, P: 0.3 };
|
|
7753
|
-
var PR_levels = { N: 0, L: 0.1, H: 0.2 };
|
|
7754
|
-
var UI_levels = { N: 0, P: 0.1, A: 0.2 };
|
|
7755
|
-
var AC_levels = { L: 0, H: 0.1 };
|
|
7756
|
-
var AT_levels = { N: 0, P: 0.1 };
|
|
7757
|
-
var VC_levels = { H: 0, L: 0.1, N: 0.2 };
|
|
7758
|
-
var VI_levels = { H: 0, L: 0.1, N: 0.2 };
|
|
7759
|
-
var VA_levels = { H: 0, L: 0.1, N: 0.2 };
|
|
7760
|
-
var SC_levels = { H: 0.1, L: 0.2, N: 0.3 };
|
|
7761
|
-
var SI_levels = { S: 0, H: 0.1, L: 0.2, N: 0.3 };
|
|
7762
|
-
var SA_levels = { S: 0, H: 0.1, L: 0.2, N: 0.3 };
|
|
7763
|
-
var CR_levels = { H: 0, M: 0.1, L: 0.2 };
|
|
7764
|
-
var IR_levels = { H: 0, M: 0.1, L: 0.2 };
|
|
7765
|
-
var AR_levels = { H: 0, M: 0.1, L: 0.2 };
|
|
7766
|
-
var CVSS40_LOOKUP = {
|
|
7767
|
-
"000000": 10,
|
|
7768
|
-
"000001": 9.9,
|
|
7769
|
-
"000010": 9.8,
|
|
7770
|
-
"000011": 9.5,
|
|
7771
|
-
"000020": 9.5,
|
|
7772
|
-
"000021": 9.2,
|
|
7773
|
-
"000100": 10,
|
|
7774
|
-
"000101": 9.6,
|
|
7775
|
-
"000110": 9.3,
|
|
7776
|
-
"000111": 8.7,
|
|
7777
|
-
"000120": 9.1,
|
|
7778
|
-
"000121": 8.1,
|
|
7779
|
-
"000200": 9.3,
|
|
7780
|
-
"000201": 9,
|
|
7781
|
-
"000210": 8.9,
|
|
7782
|
-
"000211": 8,
|
|
7783
|
-
"000220": 8.1,
|
|
7784
|
-
"000221": 6.8,
|
|
7785
|
-
"001000": 9.8,
|
|
7786
|
-
"001001": 9.5,
|
|
7787
|
-
"001010": 9.5,
|
|
7788
|
-
"001011": 9.2,
|
|
7789
|
-
"001020": 9,
|
|
7790
|
-
"001021": 8.4,
|
|
7791
|
-
"001100": 9.3,
|
|
7792
|
-
"001101": 9.2,
|
|
7793
|
-
"001110": 8.9,
|
|
7794
|
-
"001111": 8.1,
|
|
7795
|
-
"001120": 8.1,
|
|
7796
|
-
"001121": 6.5,
|
|
7797
|
-
"001200": 8.8,
|
|
7798
|
-
"001201": 8,
|
|
7799
|
-
"001210": 7.8,
|
|
7800
|
-
"001211": 7,
|
|
7801
|
-
"001220": 6.9,
|
|
7802
|
-
"001221": 4.8,
|
|
7803
|
-
"002001": 9.2,
|
|
7804
|
-
"002011": 8.2,
|
|
7805
|
-
"002021": 7.2,
|
|
7806
|
-
"002101": 7.9,
|
|
7807
|
-
"002111": 6.9,
|
|
7808
|
-
"002121": 5,
|
|
7809
|
-
"002201": 6.9,
|
|
7810
|
-
"002211": 5.5,
|
|
7811
|
-
"002221": 2.7,
|
|
7812
|
-
"010000": 9.9,
|
|
7813
|
-
"010001": 9.7,
|
|
7814
|
-
"010010": 9.5,
|
|
7815
|
-
"010011": 9.2,
|
|
7816
|
-
"010020": 9.2,
|
|
7817
|
-
"010021": 8.5,
|
|
7818
|
-
"010100": 9.5,
|
|
7819
|
-
"010101": 9.1,
|
|
7820
|
-
"010110": 9,
|
|
7821
|
-
"010111": 8.3,
|
|
7822
|
-
"010120": 8.4,
|
|
7823
|
-
"010121": 7.1,
|
|
7824
|
-
"010200": 9.2,
|
|
7825
|
-
"010201": 8.1,
|
|
7826
|
-
"010210": 8.2,
|
|
7827
|
-
"010211": 7.1,
|
|
7828
|
-
"010220": 7.2,
|
|
7829
|
-
"010221": 5.3,
|
|
7830
|
-
"011000": 9.5,
|
|
7831
|
-
"011001": 9.3,
|
|
7832
|
-
"011010": 9.2,
|
|
7833
|
-
"011011": 8.5,
|
|
7834
|
-
"011020": 8.5,
|
|
7835
|
-
"011021": 7.3,
|
|
7836
|
-
"011100": 9.2,
|
|
7837
|
-
"011101": 8.2,
|
|
7838
|
-
"011110": 8,
|
|
7839
|
-
"011111": 7.2,
|
|
7840
|
-
"011120": 7,
|
|
7841
|
-
"011121": 5.9,
|
|
7842
|
-
"011200": 8.4,
|
|
7843
|
-
"011201": 7,
|
|
7844
|
-
"011210": 7.1,
|
|
7845
|
-
"011211": 5.2,
|
|
7846
|
-
"011220": 5,
|
|
7847
|
-
"011221": 3,
|
|
7848
|
-
"012001": 8.6,
|
|
7849
|
-
"012011": 7.5,
|
|
7850
|
-
"012021": 5.2,
|
|
7851
|
-
"012101": 7.1,
|
|
7852
|
-
"012111": 5.2,
|
|
7853
|
-
"012121": 2.9,
|
|
7854
|
-
"012201": 6.3,
|
|
7855
|
-
"012211": 2.9,
|
|
7856
|
-
"012221": 1.7,
|
|
7857
|
-
"100000": 9.8,
|
|
7858
|
-
"100001": 9.5,
|
|
7859
|
-
"100010": 9.4,
|
|
7860
|
-
"100011": 8.7,
|
|
7861
|
-
"100020": 9.1,
|
|
7862
|
-
"100021": 8.1,
|
|
7863
|
-
"100100": 9.4,
|
|
7864
|
-
"100101": 8.9,
|
|
7865
|
-
"100110": 8.6,
|
|
7866
|
-
"100111": 7.4,
|
|
7867
|
-
"100120": 7.7,
|
|
7868
|
-
"100121": 6.4,
|
|
7869
|
-
"100200": 8.7,
|
|
7870
|
-
"100201": 7.5,
|
|
7871
|
-
"100210": 7.4,
|
|
7872
|
-
"100211": 6.3,
|
|
7873
|
-
"100220": 6.3,
|
|
7874
|
-
"100221": 4.9,
|
|
7875
|
-
"101000": 9.4,
|
|
7876
|
-
"101001": 8.9,
|
|
7877
|
-
"101010": 8.8,
|
|
7878
|
-
"101011": 7.7,
|
|
7879
|
-
"101020": 7.6,
|
|
7880
|
-
"101021": 6.7,
|
|
7881
|
-
"101100": 8.6,
|
|
7882
|
-
"101101": 7.6,
|
|
7883
|
-
"101110": 7.4,
|
|
7884
|
-
"101111": 5.8,
|
|
7885
|
-
"101120": 5.9,
|
|
7886
|
-
"101121": 5,
|
|
7887
|
-
"101200": 7.2,
|
|
7888
|
-
"101201": 5.7,
|
|
7889
|
-
"101210": 5.7,
|
|
7890
|
-
"101211": 5.2,
|
|
7891
|
-
"101220": 5.2,
|
|
7892
|
-
"101221": 2.5,
|
|
7893
|
-
"102001": 8.3,
|
|
7894
|
-
"102011": 7,
|
|
7895
|
-
"102021": 5.4,
|
|
7896
|
-
"102101": 6.5,
|
|
7897
|
-
"102111": 5.8,
|
|
7898
|
-
"102121": 2.6,
|
|
7899
|
-
"102201": 5.3,
|
|
7900
|
-
"102211": 2.1,
|
|
7901
|
-
"102221": 1.3,
|
|
7902
|
-
"110000": 9.5,
|
|
7903
|
-
"110001": 9,
|
|
7904
|
-
"110010": 8.8,
|
|
7905
|
-
"110011": 7.6,
|
|
7906
|
-
"110020": 7.6,
|
|
7907
|
-
"110021": 7,
|
|
7908
|
-
"110100": 9,
|
|
7909
|
-
"110101": 7.7,
|
|
7910
|
-
"110110": 7.5,
|
|
7911
|
-
"110111": 6.2,
|
|
7912
|
-
"110120": 6.1,
|
|
7913
|
-
"110121": 5.3,
|
|
7914
|
-
"110200": 7.7,
|
|
7915
|
-
"110201": 6.6,
|
|
7916
|
-
"110210": 6.8,
|
|
7917
|
-
"110211": 5.9,
|
|
7918
|
-
"110220": 5.2,
|
|
7919
|
-
"110221": 3,
|
|
7920
|
-
"111000": 8.9,
|
|
7921
|
-
"111001": 7.8,
|
|
7922
|
-
"111010": 7.6,
|
|
7923
|
-
"111011": 6.7,
|
|
7924
|
-
"111020": 6.2,
|
|
7925
|
-
"111021": 5.8,
|
|
7926
|
-
"111100": 7.4,
|
|
7927
|
-
"111101": 5.9,
|
|
7928
|
-
"111110": 5.7,
|
|
7929
|
-
"111111": 5.7,
|
|
7930
|
-
"111120": 4.7,
|
|
7931
|
-
"111121": 2.3,
|
|
7932
|
-
"111200": 6.1,
|
|
7933
|
-
"111201": 5.2,
|
|
7934
|
-
"111210": 5.7,
|
|
7935
|
-
"111211": 2.9,
|
|
7936
|
-
"111220": 2.4,
|
|
7937
|
-
"111221": 1.6,
|
|
7938
|
-
"112001": 7.1,
|
|
7939
|
-
"112011": 5.9,
|
|
7940
|
-
"112021": 3,
|
|
7941
|
-
"112101": 5.8,
|
|
7942
|
-
"112111": 2.6,
|
|
7943
|
-
"112121": 1.5,
|
|
7944
|
-
"112201": 2.3,
|
|
7945
|
-
"112211": 1.3,
|
|
7946
|
-
"112221": 0.6,
|
|
7947
|
-
"200000": 9.3,
|
|
7948
|
-
"200001": 8.7,
|
|
7949
|
-
"200010": 8.6,
|
|
7950
|
-
"200011": 7.2,
|
|
7951
|
-
"200020": 7.5,
|
|
7952
|
-
"200021": 5.8,
|
|
7953
|
-
"200100": 8.6,
|
|
7954
|
-
"200101": 7.4,
|
|
7955
|
-
"200110": 7.4,
|
|
7956
|
-
"200111": 6.1,
|
|
7957
|
-
"200120": 5.6,
|
|
7958
|
-
"200121": 3.4,
|
|
7959
|
-
"200200": 7,
|
|
7960
|
-
"200201": 5.4,
|
|
7961
|
-
"200210": 5.2,
|
|
7962
|
-
"200211": 4,
|
|
7963
|
-
"200220": 4,
|
|
7964
|
-
"200221": 2.2,
|
|
7965
|
-
"201000": 8.5,
|
|
7966
|
-
"201001": 7.5,
|
|
7967
|
-
"201010": 7.4,
|
|
7968
|
-
"201011": 5.5,
|
|
7969
|
-
"201020": 6.2,
|
|
7970
|
-
"201021": 5.1,
|
|
7971
|
-
"201100": 7.2,
|
|
7972
|
-
"201101": 5.7,
|
|
7973
|
-
"201110": 5.5,
|
|
7974
|
-
"201111": 4.1,
|
|
7975
|
-
"201120": 4.6,
|
|
7976
|
-
"201121": 1.9,
|
|
7977
|
-
"201200": 5.3,
|
|
7978
|
-
"201201": 3.6,
|
|
7979
|
-
"201210": 3.4,
|
|
7980
|
-
"201211": 1.9,
|
|
7981
|
-
"201220": 1.9,
|
|
7982
|
-
"201221": 0.8,
|
|
7983
|
-
"202001": 6.4,
|
|
7984
|
-
"202011": 5.1,
|
|
7985
|
-
"202021": 2,
|
|
7986
|
-
"202101": 4.7,
|
|
7987
|
-
"202111": 2.1,
|
|
7988
|
-
"202121": 1.1,
|
|
7989
|
-
"202201": 2.4,
|
|
7990
|
-
"202211": 0.9,
|
|
7991
|
-
"202221": 0.4,
|
|
7992
|
-
"210000": 8.8,
|
|
7993
|
-
"210001": 7.5,
|
|
7994
|
-
"210010": 7.3,
|
|
7995
|
-
"210011": 5.3,
|
|
7996
|
-
"210020": 6,
|
|
7997
|
-
"210021": 5,
|
|
7998
|
-
"210100": 7.3,
|
|
7999
|
-
"210101": 5.5,
|
|
8000
|
-
"210110": 5.9,
|
|
8001
|
-
"210111": 4,
|
|
8002
|
-
"210120": 4.1,
|
|
8003
|
-
"210121": 2,
|
|
8004
|
-
"210200": 5.4,
|
|
8005
|
-
"210201": 4.3,
|
|
8006
|
-
"210210": 4.5,
|
|
8007
|
-
"210211": 2.2,
|
|
8008
|
-
"210220": 2,
|
|
8009
|
-
"210221": 1.1,
|
|
8010
|
-
"211000": 7.5,
|
|
8011
|
-
"211001": 5.5,
|
|
8012
|
-
"211010": 5.8,
|
|
8013
|
-
"211011": 4.5,
|
|
8014
|
-
"211020": 4,
|
|
8015
|
-
"211021": 2.1,
|
|
8016
|
-
"211100": 6.1,
|
|
8017
|
-
"211101": 5.1,
|
|
8018
|
-
"211110": 4.8,
|
|
8019
|
-
"211111": 1.8,
|
|
8020
|
-
"211120": 2,
|
|
8021
|
-
"211121": 0.9,
|
|
8022
|
-
"211200": 4.6,
|
|
8023
|
-
"211201": 1.8,
|
|
8024
|
-
"211210": 1.7,
|
|
8025
|
-
"211211": 0.7,
|
|
8026
|
-
"211220": 0.8,
|
|
8027
|
-
"211221": 0.2,
|
|
8028
|
-
"212001": 5.3,
|
|
8029
|
-
"212011": 2.4,
|
|
8030
|
-
"212021": 1.4,
|
|
8031
|
-
"212101": 2.4,
|
|
8032
|
-
"212111": 1.2,
|
|
8033
|
-
"212121": 0.5,
|
|
8034
|
-
"212201": 1,
|
|
8035
|
-
"212211": 0.3,
|
|
8036
|
-
"212221": 0.1
|
|
8037
|
-
};
|
|
8038
|
-
var CVSS40_MAX_COMPOSED = {
|
|
8039
|
-
eq1: {
|
|
8040
|
-
0: ["AV:N/PR:N/UI:N/"],
|
|
8041
|
-
1: ["AV:A/PR:N/UI:N/", "AV:N/PR:L/UI:N/", "AV:N/PR:N/UI:P/"],
|
|
8042
|
-
2: ["AV:P/PR:N/UI:N/", "AV:A/PR:L/UI:P/"]
|
|
8043
|
-
},
|
|
8044
|
-
eq2: {
|
|
8045
|
-
0: ["AC:L/AT:N/"],
|
|
8046
|
-
1: ["AC:H/AT:N/", "AC:L/AT:P/"]
|
|
8047
|
-
},
|
|
8048
|
-
eq3: {
|
|
8049
|
-
0: { "0": ["VC:H/VI:H/VA:H/CR:H/IR:H/AR:H/"], "1": ["VC:H/VI:H/VA:L/CR:M/IR:M/AR:H/", "VC:H/VI:H/VA:H/CR:M/IR:M/AR:M/"] },
|
|
8050
|
-
1: { "0": ["VC:L/VI:H/VA:H/CR:H/IR:H/AR:H/", "VC:H/VI:L/VA:H/CR:H/IR:H/AR:H/"], "1": ["VC:L/VI:H/VA:L/CR:H/IR:M/AR:H/", "VC:L/VI:H/VA:H/CR:H/IR:M/AR:M/", "VC:H/VI:L/VA:H/CR:M/IR:H/AR:M/", "VC:H/VI:L/VA:L/CR:M/IR:H/AR:H/", "VC:L/VI:L/VA:H/CR:H/IR:H/AR:M/"] },
|
|
8051
|
-
2: { "1": ["VC:L/VI:L/VA:L/CR:H/IR:H/AR:H/"] }
|
|
8052
|
-
},
|
|
8053
|
-
eq4: {
|
|
8054
|
-
0: ["SC:H/SI:S/SA:S/"],
|
|
8055
|
-
1: ["SC:H/SI:H/SA:H/"],
|
|
8056
|
-
2: ["SC:L/SI:L/SA:L/"]
|
|
8057
|
-
},
|
|
8058
|
-
eq5: {
|
|
8059
|
-
0: ["E:A/"],
|
|
8060
|
-
1: ["E:P/"],
|
|
8061
|
-
2: ["E:U/"]
|
|
8062
|
-
}
|
|
8063
|
-
};
|
|
8064
|
-
var CVSS40_MAX_SEVERITY = {
|
|
8065
|
-
eq1: { 0: 1, 1: 4, 2: 5 },
|
|
8066
|
-
eq2: { 0: 1, 1: 2 },
|
|
8067
|
-
eq3eq6: { 0: { 0: 7, 1: 6 }, 1: { 0: 8, 1: 8 }, 2: { 1: 10 } },
|
|
8068
|
-
eq4: { 0: 6, 1: 5, 2: 4 },
|
|
8069
|
-
eq5: { 0: 1, 1: 1, 2: 1 }
|
|
8070
|
-
};
|
|
8071
|
-
function m4(sel, metric) {
|
|
8072
|
-
const selected = sel[metric];
|
|
8073
|
-
if (metric === "E" && (selected === void 0 || selected === "X"))
|
|
8074
|
-
return "A";
|
|
8075
|
-
if ((metric === "CR" || metric === "IR" || metric === "AR") && (selected === void 0 || selected === "X")) {
|
|
8076
|
-
return "H";
|
|
8077
|
-
}
|
|
8078
|
-
const modified = sel["M" + metric];
|
|
8079
|
-
if (modified !== void 0 && modified !== "X")
|
|
8080
|
-
return modified;
|
|
8081
|
-
return selected ?? "";
|
|
7453
|
+
function sleep(ms) {
|
|
7454
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
8082
7455
|
}
|
|
8083
|
-
function
|
|
8084
|
-
|
|
8085
|
-
if (
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
const eq2 = m4(sel, "AC") === "L" && m4(sel, "AT") === "N" ? "0" : "1";
|
|
8093
|
-
let eq3;
|
|
8094
|
-
if (m4(sel, "VC") === "H" && m4(sel, "VI") === "H") {
|
|
8095
|
-
eq3 = "0";
|
|
8096
|
-
} else if (!(m4(sel, "VC") === "H" && m4(sel, "VI") === "H") && (m4(sel, "VC") === "H" || m4(sel, "VI") === "H" || m4(sel, "VA") === "H")) {
|
|
8097
|
-
eq3 = "1";
|
|
8098
|
-
} else {
|
|
8099
|
-
eq3 = "2";
|
|
8100
|
-
}
|
|
8101
|
-
let eq4;
|
|
8102
|
-
if (m4(sel, "MSI") === "S" || m4(sel, "MSA") === "S") {
|
|
8103
|
-
eq4 = "0";
|
|
8104
|
-
} else if (m4(sel, "SC") === "H" || m4(sel, "SI") === "H" || m4(sel, "SA") === "H") {
|
|
8105
|
-
eq4 = "1";
|
|
8106
|
-
} else {
|
|
8107
|
-
eq4 = "2";
|
|
8108
|
-
}
|
|
8109
|
-
let eq5;
|
|
8110
|
-
if (m4(sel, "E") === "A")
|
|
8111
|
-
eq5 = "0";
|
|
8112
|
-
else if (m4(sel, "E") === "P")
|
|
8113
|
-
eq5 = "1";
|
|
8114
|
-
else
|
|
8115
|
-
eq5 = "2";
|
|
8116
|
-
const eq6 = m4(sel, "CR") === "H" && m4(sel, "VC") === "H" || m4(sel, "IR") === "H" && m4(sel, "VI") === "H" || m4(sel, "AR") === "H" && m4(sel, "VA") === "H" ? "0" : "1";
|
|
8117
|
-
return eq1 + eq2 + eq3 + eq4 + eq5 + eq6;
|
|
8118
|
-
}
|
|
8119
|
-
function cvss4EqMaxes(macro, eq) {
|
|
8120
|
-
const idx = Number(macro[eq - 1]);
|
|
8121
|
-
if (eq === 1)
|
|
8122
|
-
return CVSS40_MAX_COMPOSED.eq1[idx];
|
|
8123
|
-
if (eq === 2)
|
|
8124
|
-
return CVSS40_MAX_COMPOSED.eq2[idx];
|
|
8125
|
-
if (eq === 4)
|
|
8126
|
-
return CVSS40_MAX_COMPOSED.eq4[idx];
|
|
8127
|
-
return CVSS40_MAX_COMPOSED.eq5[idx];
|
|
8128
|
-
}
|
|
8129
|
-
function extractValueMetric(metric, str) {
|
|
8130
|
-
const start = str.indexOf(metric) + metric.length + 1;
|
|
8131
|
-
const extracted = str.slice(start);
|
|
8132
|
-
const slash = extracted.indexOf("/");
|
|
8133
|
-
return slash > 0 ? extracted.substring(0, slash) : extracted;
|
|
7456
|
+
function normalizeHostForMatch(value) {
|
|
7457
|
+
const trimmed = value.trim().toLowerCase();
|
|
7458
|
+
if (trimmed.startsWith("[")) {
|
|
7459
|
+
const end = trimmed.indexOf("]");
|
|
7460
|
+
return end === -1 ? trimmed : trimmed.slice(1, end);
|
|
7461
|
+
}
|
|
7462
|
+
if ((trimmed.match(/:/g) ?? []).length >= 2)
|
|
7463
|
+
return trimmed;
|
|
7464
|
+
return trimmed.replace(/:\d+$/, "");
|
|
8134
7465
|
}
|
|
8135
|
-
function
|
|
8136
|
-
if (
|
|
8137
|
-
return
|
|
8138
|
-
|
|
8139
|
-
const
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
const eq2 = parseInt(macroVectorResult[1], 10);
|
|
8143
|
-
const eq3 = parseInt(macroVectorResult[2], 10);
|
|
8144
|
-
const eq4 = parseInt(macroVectorResult[3], 10);
|
|
8145
|
-
const eq5 = parseInt(macroVectorResult[4], 10);
|
|
8146
|
-
const eq6 = parseInt(macroVectorResult[5], 10);
|
|
8147
|
-
const eq1_next_lower_macro = `${eq1 + 1}${eq2}${eq3}${eq4}${eq5}${eq6}`;
|
|
8148
|
-
const eq2_next_lower_macro = `${eq1}${eq2 + 1}${eq3}${eq4}${eq5}${eq6}`;
|
|
8149
|
-
let eq3eq6_next_lower_macro = "";
|
|
8150
|
-
let eq3eq6_next_lower_macro_left = "";
|
|
8151
|
-
let eq3eq6_next_lower_macro_right = "";
|
|
8152
|
-
if (eq3 === 1 && eq6 === 1) {
|
|
8153
|
-
eq3eq6_next_lower_macro = `${eq1}${eq2}${eq3 + 1}${eq4}${eq5}${eq6}`;
|
|
8154
|
-
} else if (eq3 === 0 && eq6 === 1) {
|
|
8155
|
-
eq3eq6_next_lower_macro = `${eq1}${eq2}${eq3 + 1}${eq4}${eq5}${eq6}`;
|
|
8156
|
-
} else if (eq3 === 1 && eq6 === 0) {
|
|
8157
|
-
eq3eq6_next_lower_macro = `${eq1}${eq2}${eq3}${eq4}${eq5}${eq6 + 1}`;
|
|
8158
|
-
} else if (eq3 === 0 && eq6 === 0) {
|
|
8159
|
-
eq3eq6_next_lower_macro_left = `${eq1}${eq2}${eq3}${eq4}${eq5}${eq6 + 1}`;
|
|
8160
|
-
eq3eq6_next_lower_macro_right = `${eq1}${eq2}${eq3 + 1}${eq4}${eq5}${eq6}`;
|
|
8161
|
-
} else {
|
|
8162
|
-
eq3eq6_next_lower_macro = `${eq1}${eq2}${eq3 + 1}${eq4}${eq5}${eq6 + 1}`;
|
|
8163
|
-
}
|
|
8164
|
-
const eq4_next_lower_macro = `${eq1}${eq2}${eq3}${eq4 + 1}${eq5}${eq6}`;
|
|
8165
|
-
const eq5_next_lower_macro = `${eq1}${eq2}${eq3}${eq4}${eq5 + 1}${eq6}`;
|
|
8166
|
-
const score_eq1_next_lower_macro = CVSS40_LOOKUP[eq1_next_lower_macro];
|
|
8167
|
-
const score_eq2_next_lower_macro = CVSS40_LOOKUP[eq2_next_lower_macro];
|
|
8168
|
-
let score_eq3eq6_next_lower_macro;
|
|
8169
|
-
if (eq3 === 0 && eq6 === 0) {
|
|
8170
|
-
const left = CVSS40_LOOKUP[eq3eq6_next_lower_macro_left];
|
|
8171
|
-
const right = CVSS40_LOOKUP[eq3eq6_next_lower_macro_right];
|
|
8172
|
-
score_eq3eq6_next_lower_macro = left > right ? left : right;
|
|
8173
|
-
} else {
|
|
8174
|
-
score_eq3eq6_next_lower_macro = CVSS40_LOOKUP[eq3eq6_next_lower_macro];
|
|
8175
|
-
}
|
|
8176
|
-
const score_eq4_next_lower_macro = CVSS40_LOOKUP[eq4_next_lower_macro];
|
|
8177
|
-
const score_eq5_next_lower_macro = CVSS40_LOOKUP[eq5_next_lower_macro];
|
|
8178
|
-
const eq1_maxes = cvss4EqMaxes(macroVectorResult, 1);
|
|
8179
|
-
const eq2_maxes = cvss4EqMaxes(macroVectorResult, 2);
|
|
8180
|
-
const eq3_eq6_maxes = CVSS40_MAX_COMPOSED.eq3[eq3][macroVectorResult[5]];
|
|
8181
|
-
const eq4_maxes = cvss4EqMaxes(macroVectorResult, 4);
|
|
8182
|
-
const eq5_maxes = cvss4EqMaxes(macroVectorResult, 5);
|
|
8183
|
-
const max_vectors = [];
|
|
8184
|
-
for (const a of eq1_maxes)
|
|
8185
|
-
for (const b of eq2_maxes)
|
|
8186
|
-
for (const c of eq3_eq6_maxes)
|
|
8187
|
-
for (const d of eq4_maxes)
|
|
8188
|
-
for (const e of eq5_maxes)
|
|
8189
|
-
max_vectors.push(a + b + c + d + e);
|
|
8190
|
-
let severity_distance_AV = 0, severity_distance_PR = 0, severity_distance_UI = 0;
|
|
8191
|
-
let severity_distance_AC = 0, severity_distance_AT = 0;
|
|
8192
|
-
let severity_distance_VC = 0, severity_distance_VI = 0, severity_distance_VA = 0;
|
|
8193
|
-
let severity_distance_SC = 0, severity_distance_SI = 0, severity_distance_SA = 0;
|
|
8194
|
-
let severity_distance_CR = 0, severity_distance_IR = 0, severity_distance_AR = 0;
|
|
8195
|
-
for (const max_vector of max_vectors) {
|
|
8196
|
-
severity_distance_AV = AV_levels[m4(sel, "AV")] - AV_levels[extractValueMetric("AV", max_vector)];
|
|
8197
|
-
severity_distance_PR = PR_levels[m4(sel, "PR")] - PR_levels[extractValueMetric("PR", max_vector)];
|
|
8198
|
-
severity_distance_UI = UI_levels[m4(sel, "UI")] - UI_levels[extractValueMetric("UI", max_vector)];
|
|
8199
|
-
severity_distance_AC = AC_levels[m4(sel, "AC")] - AC_levels[extractValueMetric("AC", max_vector)];
|
|
8200
|
-
severity_distance_AT = AT_levels[m4(sel, "AT")] - AT_levels[extractValueMetric("AT", max_vector)];
|
|
8201
|
-
severity_distance_VC = VC_levels[m4(sel, "VC")] - VC_levels[extractValueMetric("VC", max_vector)];
|
|
8202
|
-
severity_distance_VI = VI_levels[m4(sel, "VI")] - VI_levels[extractValueMetric("VI", max_vector)];
|
|
8203
|
-
severity_distance_VA = VA_levels[m4(sel, "VA")] - VA_levels[extractValueMetric("VA", max_vector)];
|
|
8204
|
-
severity_distance_SC = SC_levels[m4(sel, "SC")] - SC_levels[extractValueMetric("SC", max_vector)];
|
|
8205
|
-
severity_distance_SI = SI_levels[m4(sel, "SI")] - SI_levels[extractValueMetric("SI", max_vector)];
|
|
8206
|
-
severity_distance_SA = SA_levels[m4(sel, "SA")] - SA_levels[extractValueMetric("SA", max_vector)];
|
|
8207
|
-
severity_distance_CR = CR_levels[m4(sel, "CR")] - CR_levels[extractValueMetric("CR", max_vector)];
|
|
8208
|
-
severity_distance_IR = IR_levels[m4(sel, "IR")] - IR_levels[extractValueMetric("IR", max_vector)];
|
|
8209
|
-
severity_distance_AR = AR_levels[m4(sel, "AR")] - AR_levels[extractValueMetric("AR", max_vector)];
|
|
8210
|
-
const anyNegative = [
|
|
8211
|
-
severity_distance_AV,
|
|
8212
|
-
severity_distance_PR,
|
|
8213
|
-
severity_distance_UI,
|
|
8214
|
-
severity_distance_AC,
|
|
8215
|
-
severity_distance_AT,
|
|
8216
|
-
severity_distance_VC,
|
|
8217
|
-
severity_distance_VI,
|
|
8218
|
-
severity_distance_VA,
|
|
8219
|
-
severity_distance_SC,
|
|
8220
|
-
severity_distance_SI,
|
|
8221
|
-
severity_distance_SA,
|
|
8222
|
-
severity_distance_CR,
|
|
8223
|
-
severity_distance_IR,
|
|
8224
|
-
severity_distance_AR
|
|
8225
|
-
].some((v) => v < 0);
|
|
8226
|
-
if (anyNegative)
|
|
7466
|
+
function hostMatchesAllowlist(host, allowlist) {
|
|
7467
|
+
if (!allowlist || allowlist.length === 0)
|
|
7468
|
+
return true;
|
|
7469
|
+
const target = normalizeHostForMatch(host);
|
|
7470
|
+
for (const raw of allowlist) {
|
|
7471
|
+
const pattern = normalizeHostForMatch(raw);
|
|
7472
|
+
if (!pattern)
|
|
8227
7473
|
continue;
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
|
|
8233
|
-
|
|
8234
|
-
const step = 0.1;
|
|
8235
|
-
const available_distance_eq1 = value - score_eq1_next_lower_macro;
|
|
8236
|
-
const available_distance_eq2 = value - score_eq2_next_lower_macro;
|
|
8237
|
-
const available_distance_eq3eq6 = value - score_eq3eq6_next_lower_macro;
|
|
8238
|
-
const available_distance_eq4 = value - score_eq4_next_lower_macro;
|
|
8239
|
-
const available_distance_eq5 = value - score_eq5_next_lower_macro;
|
|
8240
|
-
let n_existing_lower = 0;
|
|
8241
|
-
let normalized_severity_eq1 = 0;
|
|
8242
|
-
let normalized_severity_eq2 = 0;
|
|
8243
|
-
let normalized_severity_eq3eq6 = 0;
|
|
8244
|
-
let normalized_severity_eq4 = 0;
|
|
8245
|
-
let normalized_severity_eq5 = 0;
|
|
8246
|
-
const maxSeverity_eq1 = CVSS40_MAX_SEVERITY.eq1[eq1] * step;
|
|
8247
|
-
const maxSeverity_eq2 = CVSS40_MAX_SEVERITY.eq2[eq2] * step;
|
|
8248
|
-
const maxSeverity_eq3eq6 = CVSS40_MAX_SEVERITY.eq3eq6[eq3][eq6] * step;
|
|
8249
|
-
const maxSeverity_eq4 = CVSS40_MAX_SEVERITY.eq4[eq4] * step;
|
|
8250
|
-
if (!Number.isNaN(available_distance_eq1)) {
|
|
8251
|
-
n_existing_lower += 1;
|
|
8252
|
-
normalized_severity_eq1 = available_distance_eq1 * (current_severity_distance_eq1 / maxSeverity_eq1);
|
|
8253
|
-
}
|
|
8254
|
-
if (!Number.isNaN(available_distance_eq2)) {
|
|
8255
|
-
n_existing_lower += 1;
|
|
8256
|
-
normalized_severity_eq2 = available_distance_eq2 * (current_severity_distance_eq2 / maxSeverity_eq2);
|
|
8257
|
-
}
|
|
8258
|
-
if (!Number.isNaN(available_distance_eq3eq6)) {
|
|
8259
|
-
n_existing_lower += 1;
|
|
8260
|
-
normalized_severity_eq3eq6 = available_distance_eq3eq6 * (current_severity_distance_eq3eq6 / maxSeverity_eq3eq6);
|
|
8261
|
-
}
|
|
8262
|
-
if (!Number.isNaN(available_distance_eq4)) {
|
|
8263
|
-
n_existing_lower += 1;
|
|
8264
|
-
normalized_severity_eq4 = available_distance_eq4 * (current_severity_distance_eq4 / maxSeverity_eq4);
|
|
8265
|
-
}
|
|
8266
|
-
if (!Number.isNaN(available_distance_eq5)) {
|
|
8267
|
-
n_existing_lower += 1;
|
|
8268
|
-
normalized_severity_eq5 = available_distance_eq5 * 0;
|
|
8269
|
-
}
|
|
8270
|
-
let mean_distance;
|
|
8271
|
-
if (n_existing_lower === 0) {
|
|
8272
|
-
mean_distance = 0;
|
|
8273
|
-
} else {
|
|
8274
|
-
mean_distance = (normalized_severity_eq1 + normalized_severity_eq2 + normalized_severity_eq3eq6 + normalized_severity_eq4 + normalized_severity_eq5) / n_existing_lower;
|
|
8275
|
-
}
|
|
8276
|
-
value -= mean_distance;
|
|
8277
|
-
if (value < 0)
|
|
8278
|
-
value = 0;
|
|
8279
|
-
if (value > 10)
|
|
8280
|
-
value = 10;
|
|
8281
|
-
return Math.round(value * 10) / 10;
|
|
8282
|
-
}
|
|
8283
|
-
function cvss4Severity(score) {
|
|
8284
|
-
if (score <= 0)
|
|
8285
|
-
return "None";
|
|
8286
|
-
if (score < 4)
|
|
8287
|
-
return "Low";
|
|
8288
|
-
if (score < 7)
|
|
8289
|
-
return "Medium";
|
|
8290
|
-
if (score < 9)
|
|
8291
|
-
return "High";
|
|
8292
|
-
return "Critical";
|
|
8293
|
-
}
|
|
8294
|
-
var CVSS4_METRIC_ORDER = [
|
|
8295
|
-
"AV",
|
|
8296
|
-
"AC",
|
|
8297
|
-
"AT",
|
|
8298
|
-
"PR",
|
|
8299
|
-
"UI",
|
|
8300
|
-
"VC",
|
|
8301
|
-
"VI",
|
|
8302
|
-
"VA",
|
|
8303
|
-
"SC",
|
|
8304
|
-
"SI",
|
|
8305
|
-
"SA",
|
|
8306
|
-
"E",
|
|
8307
|
-
"CR",
|
|
8308
|
-
"IR",
|
|
8309
|
-
"AR",
|
|
8310
|
-
"MAV",
|
|
8311
|
-
"MAC",
|
|
8312
|
-
"MAT",
|
|
8313
|
-
"MPR",
|
|
8314
|
-
"MUI",
|
|
8315
|
-
"MVC",
|
|
8316
|
-
"MVI",
|
|
8317
|
-
"MVA",
|
|
8318
|
-
"MSC",
|
|
8319
|
-
"MSI",
|
|
8320
|
-
"MSA",
|
|
8321
|
-
"S",
|
|
8322
|
-
"AU",
|
|
8323
|
-
"R",
|
|
8324
|
-
"V",
|
|
8325
|
-
"RE",
|
|
8326
|
-
"U"
|
|
8327
|
-
];
|
|
8328
|
-
function parseCvss4Vector(vector) {
|
|
8329
|
-
const trimmed = vector.trim();
|
|
8330
|
-
if (!trimmed.startsWith("CVSS:4.0/")) {
|
|
8331
|
-
throw new Cvss4ParseError(`Not a CVSS 4.0 vector (must start with "CVSS:4.0/"): ${vector}`);
|
|
8332
|
-
}
|
|
8333
|
-
const body = trimmed.slice("CVSS:4.0/".length);
|
|
8334
|
-
const parts = body.split("/").filter((p) => p.length > 0);
|
|
8335
|
-
if (parts.length === 0) {
|
|
8336
|
-
throw new Cvss4ParseError(`CVSS 4.0 vector has no metrics: ${vector}`);
|
|
8337
|
-
}
|
|
8338
|
-
const sel = {};
|
|
8339
|
-
for (const part of parts) {
|
|
8340
|
-
const eq = part.indexOf(":");
|
|
8341
|
-
if (eq < 0)
|
|
8342
|
-
throw new Cvss4ParseError(`Malformed metric segment "${part}" in ${vector}`);
|
|
8343
|
-
const key = part.slice(0, eq);
|
|
8344
|
-
const val = part.slice(eq + 1);
|
|
8345
|
-
const allowed = CVSS4_ALLOWED[key];
|
|
8346
|
-
if (!allowed)
|
|
8347
|
-
throw new Cvss4ParseError(`Unknown CVSS 4.0 metric "${key}" in ${vector}`);
|
|
8348
|
-
if (!allowed.has(val)) {
|
|
8349
|
-
throw new Cvss4ParseError(`Illegal value "${val}" for metric "${key}" in ${vector}`);
|
|
8350
|
-
}
|
|
8351
|
-
if (key in sel)
|
|
8352
|
-
throw new Cvss4ParseError(`Duplicate metric "${key}" in ${vector}`);
|
|
8353
|
-
sel[key] = val;
|
|
8354
|
-
}
|
|
8355
|
-
for (const base of CVSS4_BASE_KEYS) {
|
|
8356
|
-
if (!(base in sel)) {
|
|
8357
|
-
throw new Cvss4ParseError(`Missing mandatory base metric "${base}" in ${vector}`);
|
|
7474
|
+
if (pattern.startsWith("*.")) {
|
|
7475
|
+
const suffix = pattern.slice(1);
|
|
7476
|
+
if (target.endsWith(suffix) && target.length > suffix.length)
|
|
7477
|
+
return true;
|
|
7478
|
+
} else if (target === pattern) {
|
|
7479
|
+
return true;
|
|
8358
7480
|
}
|
|
8359
7481
|
}
|
|
8360
|
-
return
|
|
7482
|
+
return false;
|
|
8361
7483
|
}
|
|
8362
|
-
function
|
|
8363
|
-
|
|
8364
|
-
|
|
8365
|
-
const v = sel[key];
|
|
8366
|
-
if (v !== void 0 && v !== "X")
|
|
8367
|
-
segs.push(`${key}:${v}`);
|
|
8368
|
-
}
|
|
8369
|
-
return `CVSS:4.0/${segs.join("/")}`;
|
|
8370
|
-
}
|
|
8371
|
-
function scoreCvss4Vector(vector) {
|
|
8372
|
-
const sel = parseCvss4Vector(vector);
|
|
8373
|
-
const score = computeCvss4BaseScore(sel);
|
|
7484
|
+
function scopeRequiredResult(step, target, start) {
|
|
7485
|
+
if (target.scopeAllowlist && target.scopeAllowlist.length > 0)
|
|
7486
|
+
return void 0;
|
|
8374
7487
|
return {
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
7488
|
+
stepId: step.id,
|
|
7489
|
+
kind: "errored",
|
|
7490
|
+
durationMs: Date.now() - start,
|
|
7491
|
+
error: "PoC reverify requires a non-empty scope allowlist"
|
|
8379
7492
|
};
|
|
8380
7493
|
}
|
|
8381
|
-
function
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
case "needs-hardware":
|
|
8392
|
-
return { AV: "P", AT: "N", PR: "N", UI: "N" };
|
|
8393
|
-
case "needs-host-migration":
|
|
8394
|
-
return { AV: "L", AT: "N", PR: "N", UI: "A" };
|
|
8395
|
-
}
|
|
7494
|
+
function extractUrlsFromShellCommand(cmd) {
|
|
7495
|
+
const matches = cmd.match(/https?:\/\/[^\s'"]+/g);
|
|
7496
|
+
return matches ?? [];
|
|
7497
|
+
}
|
|
7498
|
+
function dockerRegistryHost(image) {
|
|
7499
|
+
const separator = image.indexOf("/");
|
|
7500
|
+
if (separator === -1)
|
|
7501
|
+
return void 0;
|
|
7502
|
+
const firstSegment = image.slice(0, separator);
|
|
7503
|
+
return firstSegment.includes(".") || firstSegment.includes(":") || firstSegment === "localhost" ? firstSegment : void 0;
|
|
8396
7504
|
}
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
const
|
|
8400
|
-
|
|
8401
|
-
|
|
8402
|
-
|
|
8403
|
-
const UI = assessed?.UI ?? "N";
|
|
8404
|
-
const subsequent = impact.scope === "C";
|
|
8405
|
-
const sel = {
|
|
8406
|
-
AV,
|
|
8407
|
-
AC: "L",
|
|
8408
|
-
AT,
|
|
8409
|
-
PR: pr31,
|
|
8410
|
-
UI,
|
|
8411
|
-
VC: impact.C,
|
|
8412
|
-
VI: impact.I,
|
|
8413
|
-
VA: impact.A,
|
|
8414
|
-
SC: subsequent ? impact.C : "N",
|
|
8415
|
-
SI: subsequent ? impact.I : "N",
|
|
8416
|
-
SA: subsequent ? impact.A : "N"
|
|
7505
|
+
var deps = { spawn, fetch: globalThis.fetch };
|
|
7506
|
+
function setRuntimeDeps(overrides) {
|
|
7507
|
+
const previous = deps;
|
|
7508
|
+
deps = { ...previous, ...overrides };
|
|
7509
|
+
return () => {
|
|
7510
|
+
deps = previous;
|
|
8417
7511
|
};
|
|
8418
|
-
|
|
7512
|
+
}
|
|
7513
|
+
async function executePocSteps(finding, target) {
|
|
7514
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7515
|
+
const steps = [];
|
|
7516
|
+
const graph = finding.pocSteps ?? [];
|
|
7517
|
+
for (const step of graph) {
|
|
7518
|
+
const result = await executeStep(step, target);
|
|
7519
|
+
steps.push(result);
|
|
7520
|
+
if (result.kind === "errored" && step.kind !== "verify") {
|
|
7521
|
+
for (let i = graph.indexOf(step) + 1; i < graph.length; i++) {
|
|
7522
|
+
steps.push({
|
|
7523
|
+
stepId: graph[i].id,
|
|
7524
|
+
kind: "skipped",
|
|
7525
|
+
durationMs: 0,
|
|
7526
|
+
error: "skipped: an earlier step errored"
|
|
7527
|
+
});
|
|
7528
|
+
}
|
|
7529
|
+
break;
|
|
7530
|
+
}
|
|
7531
|
+
}
|
|
7532
|
+
const endedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
8419
7533
|
return {
|
|
8420
|
-
|
|
8421
|
-
|
|
8422
|
-
|
|
8423
|
-
|
|
7534
|
+
findingId: finding.id,
|
|
7535
|
+
startedAt,
|
|
7536
|
+
endedAt,
|
|
7537
|
+
steps,
|
|
7538
|
+
overallVerdict: aggregateVerdict(graph, steps)
|
|
8424
7539
|
};
|
|
8425
7540
|
}
|
|
8426
|
-
function
|
|
8427
|
-
const
|
|
8428
|
-
|
|
8429
|
-
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
|
|
8434
|
-
|
|
8435
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
8436
|
-
import { resolve, join } from "node:path";
|
|
8437
|
-
function extractFileRefs(finding) {
|
|
8438
|
-
const haystack = [
|
|
8439
|
-
finding.description,
|
|
8440
|
-
finding.evidence?.analysis,
|
|
8441
|
-
finding.evidence?.request,
|
|
8442
|
-
finding.evidence?.response
|
|
8443
|
-
].filter((s) => typeof s === "string" && s.length > 0).join("\n\n");
|
|
8444
|
-
const seen = /* @__PURE__ */ new Map();
|
|
8445
|
-
const regex = /(?<![\w/\-:])([a-zA-Z0-9_./\-]+\.(?:ts|tsx|js|jsx|mjs|cjs|py|rb|go|rs|c|h|cc|cpp|java|kt|swift|php|sh|sql))(?::(\d+)(?:-\d+)?)?/g;
|
|
8446
|
-
let match;
|
|
8447
|
-
while ((match = regex.exec(haystack)) !== null) {
|
|
8448
|
-
const file = match[1];
|
|
8449
|
-
const line = match[2] ? Number(match[2]) : void 0;
|
|
8450
|
-
if (file.startsWith("http:") || file.startsWith("https:"))
|
|
8451
|
-
continue;
|
|
8452
|
-
const key = `${file}:${line ?? ""}`;
|
|
8453
|
-
if (!seen.has(key))
|
|
8454
|
-
seen.set(key, { file, line });
|
|
7541
|
+
async function executeStep(step, target) {
|
|
7542
|
+
const start = Date.now();
|
|
7543
|
+
if (target.allowProcessActions === false && (step.action.type === "shell" || step.action.type === "docker")) {
|
|
7544
|
+
return {
|
|
7545
|
+
stepId: step.id,
|
|
7546
|
+
kind: "errored",
|
|
7547
|
+
durationMs: Date.now() - start,
|
|
7548
|
+
error: `PoC ${step.action.type} actions require an isolated execution environment`
|
|
7549
|
+
};
|
|
8455
7550
|
}
|
|
8456
|
-
return Array.from(seen.values());
|
|
8457
|
-
}
|
|
8458
|
-
function gitCmd(repoPath, args) {
|
|
8459
7551
|
try {
|
|
8460
|
-
|
|
8461
|
-
|
|
8462
|
-
|
|
7552
|
+
switch (step.action.type) {
|
|
7553
|
+
case "shell":
|
|
7554
|
+
return await runShellStep(step, step.action, target, start);
|
|
7555
|
+
case "http":
|
|
7556
|
+
return await runHttpStep(step, step.action, target, start);
|
|
7557
|
+
case "docker":
|
|
7558
|
+
return await runDockerStep(step, step.action, target, start);
|
|
7559
|
+
case "note":
|
|
7560
|
+
return {
|
|
7561
|
+
stepId: step.id,
|
|
7562
|
+
kind: "skipped",
|
|
7563
|
+
durationMs: Date.now() - start
|
|
7564
|
+
};
|
|
7565
|
+
default: {
|
|
7566
|
+
const _exhaustive = step.action;
|
|
7567
|
+
return {
|
|
7568
|
+
stepId: step.id,
|
|
7569
|
+
kind: "errored",
|
|
7570
|
+
durationMs: Date.now() - start,
|
|
7571
|
+
error: `unknown action type: ${JSON.stringify(_exhaustive)}`
|
|
7572
|
+
};
|
|
7573
|
+
}
|
|
7574
|
+
}
|
|
7575
|
+
} catch (err) {
|
|
7576
|
+
return {
|
|
7577
|
+
stepId: step.id,
|
|
7578
|
+
kind: "errored",
|
|
7579
|
+
durationMs: Date.now() - start,
|
|
7580
|
+
error: errMessage(err)
|
|
7581
|
+
};
|
|
8463
7582
|
}
|
|
8464
7583
|
}
|
|
8465
|
-
function
|
|
8466
|
-
const
|
|
8467
|
-
|
|
8468
|
-
|
|
8469
|
-
|
|
7584
|
+
async function runShellStep(step, action, target, start) {
|
|
7585
|
+
const scopeError = scopeRequiredResult(step, target, start);
|
|
7586
|
+
if (scopeError)
|
|
7587
|
+
return scopeError;
|
|
7588
|
+
if (target.scopeAllowlist && target.scopeAllowlist.length > 0) {
|
|
7589
|
+
for (const u of extractUrlsFromShellCommand(action.cmd)) {
|
|
7590
|
+
let host;
|
|
7591
|
+
try {
|
|
7592
|
+
host = new URL(u).host;
|
|
7593
|
+
} catch {
|
|
7594
|
+
continue;
|
|
7595
|
+
}
|
|
7596
|
+
if (!hostMatchesAllowlist(host, target.scopeAllowlist)) {
|
|
7597
|
+
return {
|
|
7598
|
+
stepId: step.id,
|
|
7599
|
+
kind: "errored",
|
|
7600
|
+
durationMs: Date.now() - start,
|
|
7601
|
+
error: `out-of-scope url in shell cmd: ${u} (allowlist: ${target.scopeAllowlist.join(", ")})`
|
|
7602
|
+
};
|
|
7603
|
+
}
|
|
7604
|
+
}
|
|
8470
7605
|
}
|
|
8471
|
-
const
|
|
8472
|
-
|
|
7606
|
+
const env = { ...process.env, ...target.env ?? {} };
|
|
7607
|
+
const cwd = action.cwd ?? target.cwd;
|
|
7608
|
+
const timeoutMs = target.timeoutMs ?? DEFAULT_STEP_TIMEOUT_MS;
|
|
7609
|
+
const spawned = await spawnAndCapture("/bin/sh", ["-c", action.cmd], { env, cwd, timeoutMs });
|
|
7610
|
+
return finaliseProcessStep(step, spawned, start);
|
|
7611
|
+
}
|
|
7612
|
+
async function runDockerStep(step, action, target, start) {
|
|
7613
|
+
const scopeError = scopeRequiredResult(step, target, start);
|
|
7614
|
+
if (scopeError)
|
|
7615
|
+
return scopeError;
|
|
7616
|
+
const registryHost = dockerRegistryHost(action.image);
|
|
7617
|
+
if (registryHost && !hostMatchesAllowlist(registryHost, target.scopeAllowlist)) {
|
|
8473
7618
|
return {
|
|
8474
|
-
|
|
8475
|
-
|
|
8476
|
-
|
|
8477
|
-
|
|
8478
|
-
refsStillPresent: [],
|
|
8479
|
-
refsMissing: []
|
|
7619
|
+
stepId: step.id,
|
|
7620
|
+
kind: "errored",
|
|
7621
|
+
durationMs: Date.now() - start,
|
|
7622
|
+
error: `out-of-scope docker registry: ${registryHost} (allowlist: ${target.scopeAllowlist.join(", ")})`
|
|
8480
7623
|
};
|
|
8481
7624
|
}
|
|
8482
|
-
|
|
8483
|
-
|
|
8484
|
-
|
|
8485
|
-
|
|
8486
|
-
const abs = join(repoPath, ref.file);
|
|
8487
|
-
if (!existsSync(abs)) {
|
|
8488
|
-
refsMissing.push(ref);
|
|
8489
|
-
notes.push(`${ref.file} \u2014 file does not exist at ${currentRef}.`);
|
|
8490
|
-
continue;
|
|
8491
|
-
}
|
|
8492
|
-
if (ref.line !== void 0) {
|
|
7625
|
+
if (target.scopeAllowlist && target.scopeAllowlist.length > 0) {
|
|
7626
|
+
const dockerTokens = [action.image, ...action.args].join(" ");
|
|
7627
|
+
for (const u of extractUrlsFromShellCommand(dockerTokens)) {
|
|
7628
|
+
let host;
|
|
8493
7629
|
try {
|
|
8494
|
-
|
|
8495
|
-
if (ref.line > content.length) {
|
|
8496
|
-
refsMissing.push(ref);
|
|
8497
|
-
notes.push(`${ref.file}:${ref.line} \u2014 line is out of range (file has ${content.length} lines at ${currentRef}).`);
|
|
8498
|
-
continue;
|
|
8499
|
-
}
|
|
7630
|
+
host = new URL(u).host;
|
|
8500
7631
|
} catch {
|
|
7632
|
+
continue;
|
|
7633
|
+
}
|
|
7634
|
+
if (!hostMatchesAllowlist(host, target.scopeAllowlist)) {
|
|
7635
|
+
return {
|
|
7636
|
+
stepId: step.id,
|
|
7637
|
+
kind: "errored",
|
|
7638
|
+
durationMs: Date.now() - start,
|
|
7639
|
+
error: `out-of-scope url in docker action: ${u} (allowlist: ${target.scopeAllowlist.join(", ")})`
|
|
7640
|
+
};
|
|
8501
7641
|
}
|
|
8502
7642
|
}
|
|
8503
|
-
refsStillPresent.push(ref);
|
|
8504
|
-
}
|
|
8505
|
-
let status;
|
|
8506
|
-
if (refsStillPresent.length === 0) {
|
|
8507
|
-
status = refsMissing.some((r) => !existsSync(join(repoPath, r.file))) ? "file-removed" : "fixed";
|
|
8508
|
-
} else if (refsMissing.length === 0) {
|
|
8509
|
-
status = "still-vulnerable";
|
|
8510
|
-
} else {
|
|
8511
|
-
status = "partial-fix";
|
|
8512
|
-
}
|
|
8513
|
-
if (status === "still-vulnerable") {
|
|
8514
|
-
notes.unshift(`All ${refsStillPresent.length} cited file${refsStillPresent.length === 1 ? "" : "s"} still resolve at ${currentRef}. Status is conservative \u2014 a human should confirm the *shape* of the code at each line hasn't been patched.`);
|
|
8515
7643
|
}
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
refsStillPresent,
|
|
8522
|
-
refsMissing
|
|
8523
|
-
};
|
|
7644
|
+
const env = { ...process.env, ...target.env ?? {} };
|
|
7645
|
+
const cwd = target.cwd;
|
|
7646
|
+
const timeoutMs = target.timeoutMs ?? DEFAULT_STEP_TIMEOUT_MS;
|
|
7647
|
+
const spawned = await spawnAndCapture("docker", ["run", "--rm", ...action.args, action.image], { env, cwd, timeoutMs });
|
|
7648
|
+
return finaliseProcessStep(step, spawned, start);
|
|
8524
7649
|
}
|
|
8525
|
-
function
|
|
8526
|
-
|
|
8527
|
-
|
|
8528
|
-
|
|
8529
|
-
const
|
|
8530
|
-
|
|
8531
|
-
|
|
8532
|
-
|
|
8533
|
-
|
|
8534
|
-
|
|
8535
|
-
|
|
8536
|
-
|
|
8537
|
-
lines.push(banner[result.status]);
|
|
8538
|
-
if (result.refsChecked.length > 0) {
|
|
8539
|
-
lines.push("");
|
|
8540
|
-
lines.push(`Refs checked (${result.refsChecked.length}):`);
|
|
8541
|
-
for (const ref of result.refsChecked) {
|
|
8542
|
-
const present = result.refsStillPresent.some((r) => refsMatch(r, ref));
|
|
8543
|
-
const marker = present ? "\u2713" : "\u2717";
|
|
8544
|
-
lines.push(`- ${marker} \`${ref.file}${ref.line ? `:${ref.line}` : ""}\``);
|
|
8545
|
-
}
|
|
8546
|
-
}
|
|
8547
|
-
if (result.notes.length > 0) {
|
|
8548
|
-
lines.push("");
|
|
8549
|
-
for (const note of result.notes)
|
|
8550
|
-
lines.push(`> ${note}`);
|
|
7650
|
+
async function runHttpStep(step, action, target, start) {
|
|
7651
|
+
const scopeError = scopeRequiredResult(step, target, start);
|
|
7652
|
+
if (scopeError)
|
|
7653
|
+
return scopeError;
|
|
7654
|
+
const url = resolveUrl(action.url, target.baseUrl);
|
|
7655
|
+
if (!url) {
|
|
7656
|
+
return {
|
|
7657
|
+
stepId: step.id,
|
|
7658
|
+
kind: "errored",
|
|
7659
|
+
durationMs: Date.now() - start,
|
|
7660
|
+
error: `http step has a relative url (${action.url}) but no target.baseUrl was provided`
|
|
7661
|
+
};
|
|
8551
7662
|
}
|
|
8552
|
-
|
|
8553
|
-
}
|
|
8554
|
-
|
|
8555
|
-
// packages/core/dist/disclose/version-range.js
|
|
8556
|
-
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
8557
|
-
import { resolve as resolve2 } from "node:path";
|
|
8558
|
-
function gitCmd2(repoPath, args) {
|
|
7663
|
+
let host;
|
|
8559
7664
|
try {
|
|
8560
|
-
|
|
8561
|
-
cwd: repoPath,
|
|
8562
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
8563
|
-
encoding: "utf8",
|
|
8564
|
-
maxBuffer: 4 * 1024 * 1024
|
|
8565
|
-
}).trim();
|
|
7665
|
+
host = new URL(url).host;
|
|
8566
7666
|
} catch {
|
|
8567
|
-
return null;
|
|
8568
|
-
}
|
|
8569
|
-
}
|
|
8570
|
-
function listTags(repoPath, limit, glob) {
|
|
8571
|
-
const baseArgs = ["tag"];
|
|
8572
|
-
if (glob)
|
|
8573
|
-
baseArgs.push("-l", glob);
|
|
8574
|
-
const byVersion = gitCmd2(repoPath, [...baseArgs, "--sort=-v:refname"]);
|
|
8575
|
-
if (byVersion && byVersion.length > 0) {
|
|
8576
|
-
return byVersion.split("\n").filter(Boolean).slice(0, limit);
|
|
8577
|
-
}
|
|
8578
|
-
const byDate = gitCmd2(repoPath, [...baseArgs, "--sort=-creatordate"]);
|
|
8579
|
-
if (!byDate)
|
|
8580
|
-
return [];
|
|
8581
|
-
return byDate.split("\n").filter(Boolean).slice(0, limit);
|
|
8582
|
-
}
|
|
8583
|
-
function fileExistsAtRef(repoPath, ref, filePath) {
|
|
8584
|
-
const out = gitCmd2(repoPath, ["cat-file", "-e", `${ref}:${filePath}`]);
|
|
8585
|
-
return out !== null;
|
|
8586
|
-
}
|
|
8587
|
-
function lineExistsAtRef(repoPath, ref, filePath, line) {
|
|
8588
|
-
const content = gitCmd2(repoPath, ["show", `${ref}:${filePath}`]);
|
|
8589
|
-
if (content === null)
|
|
8590
|
-
return false;
|
|
8591
|
-
const lineCount = content.split("\n").length;
|
|
8592
|
-
return line <= lineCount;
|
|
8593
|
-
}
|
|
8594
|
-
function findingPresentAtRef(repoPath, ref, refs) {
|
|
8595
|
-
if (refs.length === 0)
|
|
8596
|
-
return false;
|
|
8597
|
-
for (const r of refs) {
|
|
8598
|
-
if (!fileExistsAtRef(repoPath, ref, r.file))
|
|
8599
|
-
return false;
|
|
8600
|
-
if (r.line !== void 0 && !lineExistsAtRef(repoPath, ref, r.file, r.line))
|
|
8601
|
-
return false;
|
|
8602
|
-
}
|
|
8603
|
-
return true;
|
|
8604
|
-
}
|
|
8605
|
-
function detectVersionRange(finding, options) {
|
|
8606
|
-
const repoPath = resolve2(options.repoPath);
|
|
8607
|
-
const tagLimit = options.tagLimit ?? 30;
|
|
8608
|
-
const refs = extractFileRefs(finding);
|
|
8609
|
-
const notes = [];
|
|
8610
|
-
if (refs.length === 0) {
|
|
8611
7667
|
return {
|
|
8612
|
-
|
|
8613
|
-
|
|
8614
|
-
|
|
8615
|
-
|
|
7668
|
+
stepId: step.id,
|
|
7669
|
+
kind: "errored",
|
|
7670
|
+
durationMs: Date.now() - start,
|
|
7671
|
+
error: `http step url is not a valid URL: ${url}`
|
|
8616
7672
|
};
|
|
8617
7673
|
}
|
|
8618
|
-
|
|
8619
|
-
const presentOnHead = findingPresentAtRef(repoPath, "HEAD", refs);
|
|
8620
|
-
if (tags.length === 0) {
|
|
8621
|
-
notes.push(`No tags found in ${repoPath}${options.tagGlob ? ` matching '${options.tagGlob}'` : ""}.`);
|
|
7674
|
+
if (!hostMatchesAllowlist(host, target.scopeAllowlist)) {
|
|
8622
7675
|
return {
|
|
8623
|
-
|
|
8624
|
-
|
|
8625
|
-
|
|
8626
|
-
|
|
7676
|
+
stepId: step.id,
|
|
7677
|
+
kind: "errored",
|
|
7678
|
+
durationMs: Date.now() - start,
|
|
7679
|
+
error: `out-of-scope host: ${host} (allowlist: ${target.scopeAllowlist.join(", ")})`
|
|
8627
7680
|
};
|
|
8628
7681
|
}
|
|
8629
|
-
const
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
const
|
|
8634
|
-
const
|
|
8635
|
-
let
|
|
8636
|
-
|
|
8637
|
-
|
|
8638
|
-
|
|
8639
|
-
|
|
8640
|
-
|
|
8641
|
-
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
|
|
7682
|
+
const rps = target.rpsPerHost ?? DEFAULT_RPS_PER_HOST;
|
|
7683
|
+
await acquireHostToken(host, rps);
|
|
7684
|
+
const headers = mergePersonaHeaders(action.headers ?? {}, target);
|
|
7685
|
+
const timeoutMs = target.timeoutMs ?? DEFAULT_STEP_TIMEOUT_MS;
|
|
7686
|
+
const ac = new AbortController();
|
|
7687
|
+
const timer = setTimeout(() => ac.abort(), timeoutMs);
|
|
7688
|
+
let finalResponse;
|
|
7689
|
+
let body = "";
|
|
7690
|
+
let currentUrl = url;
|
|
7691
|
+
let redirectCount = 0;
|
|
7692
|
+
try {
|
|
7693
|
+
while (true) {
|
|
7694
|
+
finalResponse = await deps.fetch(currentUrl, {
|
|
7695
|
+
method: action.method,
|
|
7696
|
+
headers,
|
|
7697
|
+
body: action.body,
|
|
7698
|
+
signal: ac.signal,
|
|
7699
|
+
redirect: "manual"
|
|
7700
|
+
});
|
|
7701
|
+
const status = finalResponse.status;
|
|
7702
|
+
const isRedirect = [301, 302, 303, 307, 308].includes(status);
|
|
7703
|
+
if (!isRedirect) {
|
|
7704
|
+
body = await readBodyCapped(finalResponse);
|
|
7705
|
+
if (status === 429) {
|
|
7706
|
+
const retryAfter = finalResponse.headers.get("retry-after");
|
|
7707
|
+
markHostRateLimited(host, retryAfter);
|
|
7708
|
+
}
|
|
7709
|
+
break;
|
|
7710
|
+
}
|
|
7711
|
+
redirectCount++;
|
|
7712
|
+
if (redirectCount > MAX_REDIRECT_HOPS) {
|
|
7713
|
+
try {
|
|
7714
|
+
finalResponse.body?.cancel();
|
|
7715
|
+
} catch {
|
|
7716
|
+
}
|
|
7717
|
+
clearTimeout(timer);
|
|
7718
|
+
return {
|
|
7719
|
+
stepId: step.id,
|
|
7720
|
+
kind: "errored",
|
|
7721
|
+
durationMs: Date.now() - start,
|
|
7722
|
+
error: `too many redirects (exceeded ${MAX_REDIRECT_HOPS} hops)`
|
|
7723
|
+
};
|
|
7724
|
+
}
|
|
7725
|
+
const location = finalResponse.headers.get("location");
|
|
7726
|
+
if (!location) {
|
|
7727
|
+
body = await readBodyCapped(finalResponse);
|
|
7728
|
+
break;
|
|
7729
|
+
}
|
|
7730
|
+
const nextUrlStr = new URL(location, currentUrl).toString();
|
|
7731
|
+
const nextHost = new URL(nextUrlStr).host;
|
|
7732
|
+
if (!hostMatchesAllowlist(nextHost, target.scopeAllowlist)) {
|
|
7733
|
+
try {
|
|
7734
|
+
finalResponse.body?.cancel();
|
|
7735
|
+
} catch {
|
|
7736
|
+
}
|
|
7737
|
+
clearTimeout(timer);
|
|
7738
|
+
return {
|
|
7739
|
+
stepId: step.id,
|
|
7740
|
+
kind: "errored",
|
|
7741
|
+
durationMs: Date.now() - start,
|
|
7742
|
+
error: `redirect to out-of-scope host: ${nextHost} (allowlist: ${target.scopeAllowlist.join(", ")})`
|
|
7743
|
+
};
|
|
7744
|
+
}
|
|
7745
|
+
try {
|
|
7746
|
+
finalResponse.body?.cancel();
|
|
7747
|
+
} catch {
|
|
7748
|
+
}
|
|
7749
|
+
currentUrl = nextUrlStr;
|
|
7750
|
+
}
|
|
7751
|
+
} catch (err) {
|
|
7752
|
+
clearTimeout(timer);
|
|
7753
|
+
const aborted = ac.signal.aborted;
|
|
7754
|
+
return {
|
|
7755
|
+
stepId: step.id,
|
|
7756
|
+
kind: "errored",
|
|
7757
|
+
durationMs: Date.now() - start,
|
|
7758
|
+
error: aborted ? `timeout after ${timeoutMs}ms` : errMessage(err)
|
|
7759
|
+
};
|
|
7760
|
+
} finally {
|
|
7761
|
+
clearTimeout(timer);
|
|
8649
7762
|
}
|
|
7763
|
+
const verdict = evaluateExpect(step.expect, {
|
|
7764
|
+
status: finalResponse.status,
|
|
7765
|
+
body
|
|
7766
|
+
});
|
|
8650
7767
|
return {
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
|
|
8654
|
-
|
|
8655
|
-
|
|
8656
|
-
|
|
7768
|
+
stepId: step.id,
|
|
7769
|
+
kind: verdict.kind,
|
|
7770
|
+
observedStatus: finalResponse.status,
|
|
7771
|
+
observedResponseBody: body,
|
|
7772
|
+
durationMs: Date.now() - start,
|
|
7773
|
+
...verdict.error ? { error: verdict.error } : {}
|
|
8657
7774
|
};
|
|
8658
7775
|
}
|
|
8659
|
-
function
|
|
8660
|
-
|
|
8661
|
-
|
|
8662
|
-
|
|
8663
|
-
|
|
8664
|
-
}
|
|
8665
|
-
return "Present on the repo's current `HEAD` (no tagged introduction point detected).";
|
|
8666
|
-
case "removed-upstream":
|
|
8667
|
-
if (result.introducedIn && result.fixedIn) {
|
|
8668
|
-
return `\`>= ${result.introducedIn}\`, \`< ${result.fixedIn}\`. Confirmed affected: ${result.affectedTags.map((t) => "`" + t + "`").join(", ")}. Fixed from \`${result.fixedIn}\` onward.`;
|
|
8669
|
-
}
|
|
8670
|
-
if (result.introducedIn) {
|
|
8671
|
-
return `\`>= ${result.introducedIn}\`. Confirmed affected: ${result.affectedTags.map((t) => "`" + t + "`").join(", ")}. Fixed upstream at HEAD.`;
|
|
8672
|
-
}
|
|
8673
|
-
return "Removed upstream since the last release.";
|
|
8674
|
-
case "no-tags":
|
|
8675
|
-
return "_No release tags available in the target repo to infer a range._";
|
|
8676
|
-
case "indeterminate":
|
|
8677
|
-
default:
|
|
8678
|
-
return "_Could not auto-detect a version range \u2014 add file:line citations to the finding and re-run._";
|
|
8679
|
-
}
|
|
8680
|
-
}
|
|
8681
|
-
|
|
8682
|
-
// packages/core/dist/disclose/template.js
|
|
8683
|
-
var EmptyPocError = class extends Error {
|
|
8684
|
-
findingId;
|
|
8685
|
-
constructor(findingId) {
|
|
8686
|
-
super(`Finding ${findingId} has no PoC content (pocSteps, evidence, or screenshots) \u2014 refusing to render advisory.`);
|
|
8687
|
-
this.name = "EmptyPocError";
|
|
8688
|
-
this.findingId = findingId;
|
|
8689
|
-
}
|
|
8690
|
-
};
|
|
8691
|
-
var SENSITIVE_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
8692
|
-
"authorization",
|
|
8693
|
-
"proxy-authorization",
|
|
8694
|
-
"cookie",
|
|
8695
|
-
"set-cookie",
|
|
8696
|
-
"x-auth-token",
|
|
8697
|
-
"x-api-key",
|
|
8698
|
-
"x-csrf-token",
|
|
8699
|
-
"x-xsrf-token"
|
|
8700
|
-
]);
|
|
8701
|
-
var AWS_KEY_RE = /\bAKIA[0-9A-Z]{16}\b/g;
|
|
8702
|
-
var JWT_RE = /\b[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+={0,2}\b/g;
|
|
8703
|
-
var INLINE_BEARER_RE = /\b(Bearer)\s+([^\s"'`]+)/gi;
|
|
8704
|
-
var INLINE_CURL_HEADER_RE = /(-H|--header)(\s+|=)(["']?)([A-Za-z][A-Za-z0-9-]*)\s*:\s*([^"'\n]*)\3/gi;
|
|
8705
|
-
function redactSensitiveHeaders(text) {
|
|
8706
|
-
if (!text)
|
|
8707
|
-
return text;
|
|
8708
|
-
let out = redactAuthHeaders(text);
|
|
8709
|
-
out = out.replace(AWS_KEY_RE, "<REDACTED-AWS-KEY>");
|
|
8710
|
-
out = out.replace(JWT_RE, (match) => {
|
|
8711
|
-
if (match.length < 80)
|
|
8712
|
-
return match;
|
|
8713
|
-
return "<REDACTED-JWT>";
|
|
8714
|
-
});
|
|
8715
|
-
return out;
|
|
8716
|
-
}
|
|
8717
|
-
function redactAuthHeaders(text) {
|
|
8718
|
-
if (!text)
|
|
8719
|
-
return text;
|
|
8720
|
-
const lines = text.split("\n");
|
|
8721
|
-
const redactedLines = lines.map((line) => {
|
|
8722
|
-
const m = /^(\s*)([A-Za-z][A-Za-z0-9-]*)\s*:\s*(.*)$/.exec(line);
|
|
8723
|
-
if (m && SENSITIVE_HEADER_NAMES.has(m[2].toLowerCase())) {
|
|
8724
|
-
return `${m[1]}${m[2]}: <REDACTED-${m[2]}>`;
|
|
8725
|
-
}
|
|
8726
|
-
return line;
|
|
8727
|
-
});
|
|
8728
|
-
let out = redactedLines.join("\n");
|
|
8729
|
-
out = out.replace(INLINE_CURL_HEADER_RE, (match, flag, sep, quote, name, _value) => {
|
|
8730
|
-
if (!SENSITIVE_HEADER_NAMES.has(name.toLowerCase()))
|
|
8731
|
-
return match;
|
|
8732
|
-
return `${flag}${sep}${quote}${name}: <REDACTED-${name}>${quote}`;
|
|
8733
|
-
});
|
|
8734
|
-
return out.replace(INLINE_BEARER_RE, "$1 <REDACTED-Bearer>");
|
|
8735
|
-
}
|
|
8736
|
-
function reachabilityLabel(tier) {
|
|
8737
|
-
switch (tier) {
|
|
8738
|
-
case "remote-unauth":
|
|
8739
|
-
return "remote, unauthenticated \u2014 reachable over the network with no credentials";
|
|
8740
|
-
case "proximity-rf":
|
|
8741
|
-
return "RF/physical proximity \u2014 attacker must be within radio range (NFC/BLE/Wi-Fi)";
|
|
8742
|
-
case "local-unpriv":
|
|
8743
|
-
return "local, unprivileged \u2014 requires an unprivileged account on the host";
|
|
8744
|
-
case "local-priv":
|
|
8745
|
-
return "local, privileged \u2014 requires an already-privileged local account";
|
|
8746
|
-
case "needs-hardware":
|
|
8747
|
-
return "requires specific or attacker-supplied hardware";
|
|
8748
|
-
case "needs-host-migration":
|
|
8749
|
-
return "requires the victim to mount/import an attacker-supplied artifact";
|
|
8750
|
-
}
|
|
8751
|
-
}
|
|
8752
|
-
function weaponizabilityLabel(w) {
|
|
8753
|
-
switch (w) {
|
|
8754
|
-
case "rce":
|
|
8755
|
-
return "remote code execution";
|
|
8756
|
-
case "lpe-to-root":
|
|
8757
|
-
return "local privilege escalation to root/SYSTEM";
|
|
8758
|
-
case "info-leak":
|
|
8759
|
-
return "information disclosure";
|
|
8760
|
-
case "dos-crash":
|
|
8761
|
-
return "denial of service (crash)";
|
|
7776
|
+
function resolveUrl(stepUrl, baseUrl) {
|
|
7777
|
+
try {
|
|
7778
|
+
new URL(stepUrl);
|
|
7779
|
+
return stepUrl;
|
|
7780
|
+
} catch {
|
|
8762
7781
|
}
|
|
8763
|
-
|
|
8764
|
-
|
|
8765
|
-
|
|
8766
|
-
|
|
8767
|
-
}
|
|
8768
|
-
|
|
8769
|
-
return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, max);
|
|
8770
|
-
}
|
|
8771
|
-
function indentEvidenceBlock(raw, lang = "") {
|
|
8772
|
-
const trimmed = raw.trim();
|
|
8773
|
-
if (!trimmed)
|
|
8774
|
-
return "";
|
|
8775
|
-
return "```" + lang + "\n" + trimmed + "\n```";
|
|
8776
|
-
}
|
|
8777
|
-
function renderPocSteps(finding) {
|
|
8778
|
-
if (!finding.pocSteps || finding.pocSteps.length === 0)
|
|
8779
|
-
return [];
|
|
8780
|
-
const lines = ["**Step graph:**", ""];
|
|
8781
|
-
for (const [index, step] of finding.pocSteps.entries()) {
|
|
8782
|
-
lines.push(`${index + 1}. **${step.kind}** \u2014 ${step.summary} _(id: \`${step.id}\`)_`);
|
|
8783
|
-
if (step.action.type === "shell") {
|
|
8784
|
-
lines.push("", indentEvidenceBlock(step.action.cmd, "bash"));
|
|
8785
|
-
} else if (step.action.type === "http") {
|
|
8786
|
-
const method = step.action.method.toUpperCase();
|
|
8787
|
-
lines.push("", indentEvidenceBlock(`${method} ${step.action.url}${step.action.body ? `
|
|
8788
|
-
|
|
8789
|
-
${step.action.body}` : ""}`, "http"));
|
|
8790
|
-
} else if (step.action.type === "docker") {
|
|
8791
|
-
lines.push("", indentEvidenceBlock(`docker run ${step.action.image} ${step.action.args.join(" ")}`.trim(), "bash"));
|
|
8792
|
-
} else {
|
|
8793
|
-
lines.push("", step.action.text);
|
|
8794
|
-
}
|
|
8795
|
-
if (step.expect) {
|
|
8796
|
-
lines.push("", `Expected result: \`${step.expect.type}\``);
|
|
8797
|
-
}
|
|
8798
|
-
lines.push("");
|
|
7782
|
+
if (!baseUrl)
|
|
7783
|
+
return null;
|
|
7784
|
+
try {
|
|
7785
|
+
return new URL(stepUrl, baseUrl).toString();
|
|
7786
|
+
} catch {
|
|
7787
|
+
return null;
|
|
8799
7788
|
}
|
|
8800
|
-
return lines;
|
|
8801
7789
|
}
|
|
8802
|
-
function
|
|
8803
|
-
const
|
|
8804
|
-
|
|
8805
|
-
const
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
|
|
8809
|
-
let affectedLine;
|
|
8810
|
-
if (ctx.versionRange) {
|
|
8811
|
-
affectedLine = formatVersionRangeLine(ctx.versionRange);
|
|
8812
|
-
} else if (ctx.target) {
|
|
8813
|
-
affectedLine = `\`${ctx.target}\`${ctx.targetRef ? ` at \`${ctx.targetRef}\`` : ""}${ctx.commitHash ? ` (commit \`${ctx.commitHash.slice(0, 12)}\`)` : ""}`;
|
|
8814
|
-
} else {
|
|
8815
|
-
affectedLine = "_Pass `--repo <path>` to `0sec-cli disclose` to auto-detect the affected version range from git tags._";
|
|
8816
|
-
}
|
|
8817
|
-
const cvssSource = cvss.source === "finding" ? "populated on the finding by 0sec" : cvss.source === "impact-assessment" ? "exploitability metrics derived from 0sec's reachability assessment; impact from category \u2014 verify against your deployment" : "heuristic from category + severity \u2014 override in the GHSA editor if the operator disagrees";
|
|
8818
|
-
const remediation = finding.remediation;
|
|
8819
|
-
const suggestedFixParts = [];
|
|
8820
|
-
if (remediation?.summary)
|
|
8821
|
-
suggestedFixParts.push(remediation.summary);
|
|
8822
|
-
if (remediation?.steps?.length) {
|
|
8823
|
-
suggestedFixParts.push(remediation.steps.map((step, i) => `${i + 1}. ${step}`).join("\n"));
|
|
8824
|
-
}
|
|
8825
|
-
if (remediation?.codeExample?.after) {
|
|
8826
|
-
const lang = remediation.codeExample.language || "";
|
|
8827
|
-
suggestedFixParts.push(remediation.codeExample.before ? `**Before:**
|
|
8828
|
-
|
|
8829
|
-
\`\`\`${lang}
|
|
8830
|
-
${remediation.codeExample.before}
|
|
8831
|
-
\`\`\`
|
|
8832
|
-
|
|
8833
|
-
**After:**
|
|
8834
|
-
|
|
8835
|
-
\`\`\`${lang}
|
|
8836
|
-
${remediation.codeExample.after}
|
|
8837
|
-
\`\`\`` : `\`\`\`${lang}
|
|
8838
|
-
${remediation.codeExample.after}
|
|
8839
|
-
\`\`\``);
|
|
8840
|
-
} else if (ctx.siblingFix) {
|
|
8841
|
-
const ref = `${ctx.siblingFix.fileRef.file}${ctx.siblingFix.fileRef.line ? `:${ctx.siblingFix.fileRef.line}` : ""}`;
|
|
8842
|
-
suggestedFixParts.push(`**Correct pattern already present in the repo at \`${ref}\`** *(extracted by 0sec):*
|
|
8843
|
-
|
|
8844
|
-
\`\`\`${ctx.siblingFix.language}
|
|
8845
|
-
${ctx.siblingFix.snippet}
|
|
8846
|
-
\`\`\``);
|
|
8847
|
-
}
|
|
8848
|
-
const suggestedFix = suggestedFixParts.length > 0 ? suggestedFixParts.join("\n\n") : "_To fill in: copy-paste the correct pattern from a sibling handler in the same repo._";
|
|
8849
|
-
const evidenceAnalysis = finding.evidence?.analysis?.trim() ?? "";
|
|
8850
|
-
const out = [];
|
|
8851
|
-
out.push("# Title", "");
|
|
8852
|
-
out.push(finding.title, "");
|
|
8853
|
-
out.push("# Severity", "");
|
|
8854
|
-
out.push(`**${severity}** \u2014 ${cvss.vector} (~${cvss.score.toFixed(1)})`, "");
|
|
8855
|
-
out.push(`_CVSS source: ${cvssSource}._`, "");
|
|
8856
|
-
const impactAssessment = finding.impactAssessment;
|
|
8857
|
-
if (impactAssessment) {
|
|
8858
|
-
out.push("# Impact", "");
|
|
8859
|
-
out.push(`**Attacker gains:** ${weaponizabilityLabel(impactAssessment.weaponizability)}`, "");
|
|
8860
|
-
out.push(`**Attack prerequisites:** ${reachabilityLabel(impactAssessment.reachability_tier)}`, "");
|
|
8861
|
-
if (impactAssessment.blast_radius) {
|
|
8862
|
-
out.push(`**Blast radius:** ${impactAssessment.blast_radius}`, "");
|
|
8863
|
-
}
|
|
8864
|
-
if (impactAssessment.rationale) {
|
|
8865
|
-
out.push(`_${impactAssessment.rationale}_`, "");
|
|
7790
|
+
function mergePersonaHeaders(stepHeaders, target) {
|
|
7791
|
+
const merged = {};
|
|
7792
|
+
let personaName;
|
|
7793
|
+
for (const [k, v] of Object.entries(stepHeaders)) {
|
|
7794
|
+
if (k.toLowerCase() === PERSONA_HEADER.toLowerCase()) {
|
|
7795
|
+
personaName = v;
|
|
7796
|
+
continue;
|
|
8866
7797
|
}
|
|
7798
|
+
merged[k] = v;
|
|
8867
7799
|
}
|
|
8868
|
-
|
|
8869
|
-
|
|
8870
|
-
|
|
8871
|
-
if (
|
|
8872
|
-
|
|
8873
|
-
|
|
8874
|
-
|
|
8875
|
-
|
|
8876
|
-
|
|
8877
|
-
const canaryPositive = ctx.patchStatus?.status === "still-vulnerable";
|
|
8878
|
-
const behaviouralPositive = ctx.pocExecution?.overallVerdict === "exploit_still_works";
|
|
8879
|
-
if (canaryPositive && behaviouralPositive) {
|
|
8880
|
-
out.push(`> Code-verified by ${bits.join(", ")}.`, "");
|
|
8881
|
-
} else {
|
|
8882
|
-
out.push(`_Generated by ${bits.join(", ")}._`, "");
|
|
7800
|
+
if (!personaName)
|
|
7801
|
+
return merged;
|
|
7802
|
+
const persona = target.personas?.[personaName];
|
|
7803
|
+
if (!persona)
|
|
7804
|
+
return merged;
|
|
7805
|
+
if (persona.headers) {
|
|
7806
|
+
for (const [k, v] of Object.entries(persona.headers)) {
|
|
7807
|
+
if (!(k in merged))
|
|
7808
|
+
merged[k] = v;
|
|
8883
7809
|
}
|
|
8884
7810
|
}
|
|
8885
|
-
|
|
8886
|
-
|
|
8887
|
-
if (evidenceAnalysis && evidenceAnalysis !== finding.description.trim()) {
|
|
8888
|
-
out.push("## Analysis", "");
|
|
8889
|
-
out.push(evidenceAnalysis, "");
|
|
8890
|
-
}
|
|
8891
|
-
const pocStepsBlock = renderPocSteps(finding);
|
|
8892
|
-
const hasRequest = !!finding.evidence?.request?.trim();
|
|
8893
|
-
const hasResponse = !!finding.evidence?.response?.trim();
|
|
8894
|
-
const hasScreenshots = !!ctx.screenshots && ctx.screenshots.length > 0;
|
|
8895
|
-
if (pocStepsBlock.length === 0 && !hasRequest && !hasResponse && !hasScreenshots) {
|
|
8896
|
-
throw new EmptyPocError(finding.id);
|
|
8897
|
-
}
|
|
8898
|
-
out.push("## PoC", "");
|
|
8899
|
-
if (pocStepsBlock.length > 0) {
|
|
8900
|
-
const redactedSteps = redactSensitiveHeaders(pocStepsBlock.join("\n")).split("\n");
|
|
8901
|
-
out.push(...redactedSteps);
|
|
8902
|
-
}
|
|
8903
|
-
if (hasScreenshots) {
|
|
8904
|
-
for (const shot of ctx.screenshots) {
|
|
8905
|
-
const width = shot.width ? ` width="${shot.width}"` : "";
|
|
8906
|
-
out.push(`<img${width} alt="${shot.alt}" src="${shot.relativePath}" />`, "");
|
|
8907
|
-
if (shot.caption) {
|
|
8908
|
-
out.push(`> ${shot.caption}`, "");
|
|
8909
|
-
}
|
|
8910
|
-
}
|
|
8911
|
-
}
|
|
8912
|
-
if (hasRequest) {
|
|
8913
|
-
out.push("**Request:**", "");
|
|
8914
|
-
out.push(indentEvidenceBlock(redactSensitiveHeaders(finding.evidence.request), "http"), "");
|
|
8915
|
-
}
|
|
8916
|
-
if (hasResponse) {
|
|
8917
|
-
out.push("**Response:**", "");
|
|
8918
|
-
out.push(indentEvidenceBlock(redactSensitiveHeaders(finding.evidence.response), "http"), "");
|
|
8919
|
-
}
|
|
8920
|
-
out.push("## Suggested fix", "");
|
|
8921
|
-
out.push(suggestedFix, "");
|
|
8922
|
-
out.push("## Patch status", "");
|
|
8923
|
-
if (ctx.patchStatus) {
|
|
8924
|
-
out.push(formatPatchStatusSection(ctx.patchStatus), "");
|
|
8925
|
-
} else {
|
|
8926
|
-
out.push("_Pass `--repo <path>` to `0sec-cli disclose` to auto-verify this against the target's current HEAD or a specific tag._", "");
|
|
7811
|
+
if (persona.cookies && !("cookie" in lowerKeys(merged))) {
|
|
7812
|
+
merged["Cookie"] = persona.cookies;
|
|
8927
7813
|
}
|
|
8928
|
-
|
|
8929
|
-
const verdict = ctx.pocExecution.overallVerdict === "exploit_still_works" ? "**Behavioural check: exploit still reproducible.**" : ctx.pocExecution.overallVerdict === "exploit_broken" ? "**Behavioural check: exploit no longer reproducible.**" : "**Behavioural check: could not run.**";
|
|
8930
|
-
out.push(verdict, "");
|
|
8931
|
-
out.push(`> Verdict: \`${ctx.pocExecution.overallVerdict}\` (${ctx.pocExecution.steps.length} step${ctx.pocExecution.steps.length === 1 ? "" : "s"} executed).`, "");
|
|
8932
|
-
}
|
|
8933
|
-
out.push("## Credits", "");
|
|
8934
|
-
out.push("Discovered by **0sec**, 0sec's AI-assisted security engine ([0sec.ai](https://0sec.ai)).", "", "Reporter: _(your github handle)_", "");
|
|
8935
|
-
return {
|
|
8936
|
-
filename,
|
|
8937
|
-
markdown: out.join("\n").replace(/\n{3,}/g, "\n\n"),
|
|
8938
|
-
cvssVector: cvss.vector,
|
|
8939
|
-
cvssScore: cvss.score,
|
|
8940
|
-
primaryCwe: cwes[0]?.id ?? "",
|
|
8941
|
-
severity: finding.severity
|
|
8942
|
-
};
|
|
8943
|
-
}
|
|
8944
|
-
function buildAffectedLine(finding, ctx) {
|
|
8945
|
-
if (ctx.versionRange)
|
|
8946
|
-
return formatVersionRangeLine(ctx.versionRange);
|
|
8947
|
-
if (ctx.target) {
|
|
8948
|
-
return `\`${ctx.target}\`${ctx.targetRef ? ` at \`${ctx.targetRef}\`` : ""}${ctx.commitHash ? ` (commit \`${ctx.commitHash.slice(0, 12)}\`)` : ""}`;
|
|
8949
|
-
}
|
|
8950
|
-
return "_Affected component/version: to be filled in by the operator before submission._";
|
|
8951
|
-
}
|
|
8952
|
-
function buildImpactNarrative(finding) {
|
|
8953
|
-
const a = finding.impactAssessment;
|
|
8954
|
-
if (!a) {
|
|
8955
|
-
return `This ${finding.category.replace(/-/g, " ")} issue is rated **${severityHeading(finding.severity)}**. ` + finding.description.trim();
|
|
8956
|
-
}
|
|
8957
|
-
const parts = [];
|
|
8958
|
-
parts.push(`An attacker gains **${weaponizabilityLabel(a.weaponizability)}**. Attack prerequisites: ${reachabilityLabel(a.reachability_tier)}.`);
|
|
8959
|
-
if (a.blast_radius)
|
|
8960
|
-
parts.push(`**Blast radius:** ${a.blast_radius}`);
|
|
8961
|
-
if (a.rationale)
|
|
8962
|
-
parts.push(a.rationale);
|
|
8963
|
-
return parts.join("\n\n");
|
|
7814
|
+
return merged;
|
|
8964
7815
|
}
|
|
8965
|
-
function
|
|
8966
|
-
const
|
|
8967
|
-
|
|
8968
|
-
|
|
8969
|
-
return
|
|
8970
|
-
2. Trigger the ${finding.category.replace(/-/g, " ")} condition described above.
|
|
8971
|
-
3. Result: ${weaponizabilityLabel(a.weaponizability)}${a.blast_radius ? ` \u2014 ${a.blast_radius}` : ""}.`;
|
|
7816
|
+
function lowerKeys(obj) {
|
|
7817
|
+
const out = {};
|
|
7818
|
+
for (const [k, v] of Object.entries(obj))
|
|
7819
|
+
out[k.toLowerCase()] = v;
|
|
7820
|
+
return out;
|
|
8972
7821
|
}
|
|
8973
|
-
function
|
|
8974
|
-
|
|
8975
|
-
if (block.length === 0)
|
|
7822
|
+
async function readBodyCapped(response) {
|
|
7823
|
+
if (!response.body)
|
|
8976
7824
|
return "";
|
|
8977
|
-
|
|
7825
|
+
const reader = response.body.getReader();
|
|
7826
|
+
const decoder = new TextDecoder("utf-8", { fatal: false });
|
|
7827
|
+
let captured = "";
|
|
7828
|
+
let truncated = false;
|
|
7829
|
+
while (true) {
|
|
7830
|
+
const { value, done } = await reader.read();
|
|
7831
|
+
if (done)
|
|
7832
|
+
break;
|
|
7833
|
+
if (value) {
|
|
7834
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
7835
|
+
if (captured.length + chunk.length > MAX_CAPTURE_BYTES) {
|
|
7836
|
+
captured += chunk.slice(0, MAX_CAPTURE_BYTES - captured.length);
|
|
7837
|
+
truncated = true;
|
|
7838
|
+
try {
|
|
7839
|
+
await reader.cancel();
|
|
7840
|
+
} catch {
|
|
7841
|
+
}
|
|
7842
|
+
break;
|
|
7843
|
+
}
|
|
7844
|
+
captured += chunk;
|
|
7845
|
+
}
|
|
7846
|
+
}
|
|
7847
|
+
return truncated ? captured + TRUNCATION_MARKER : captured;
|
|
8978
7848
|
}
|
|
8979
|
-
function
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
8987
|
-
|
|
8988
|
-
|
|
8989
|
-
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
|
|
8993
|
-
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9002
|
-
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
|
|
9014
|
-
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
|
|
9019
|
-
|
|
9020
|
-
|
|
9021
|
-
|
|
9022
|
-
|
|
9023
|
-
|
|
9024
|
-
|
|
9025
|
-
|
|
9026
|
-
|
|
9027
|
-
|
|
9028
|
-
|
|
9029
|
-
|
|
9030
|
-
|
|
9031
|
-
|
|
9032
|
-
|
|
9033
|
-
const
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
|
|
7849
|
+
function spawnAndCapture(cmd, args, opts) {
|
|
7850
|
+
return new Promise((resolveP) => {
|
|
7851
|
+
let child;
|
|
7852
|
+
try {
|
|
7853
|
+
child = deps.spawn(cmd, args, {
|
|
7854
|
+
env: opts.env,
|
|
7855
|
+
cwd: opts.cwd,
|
|
7856
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
7857
|
+
});
|
|
7858
|
+
} catch (err) {
|
|
7859
|
+
resolveP({
|
|
7860
|
+
exitCode: null,
|
|
7861
|
+
stdout: "",
|
|
7862
|
+
stderr: "",
|
|
7863
|
+
timedOut: false,
|
|
7864
|
+
error: errMessage(err)
|
|
7865
|
+
});
|
|
7866
|
+
return;
|
|
7867
|
+
}
|
|
7868
|
+
let stdout = "";
|
|
7869
|
+
let stderr = "";
|
|
7870
|
+
let stdoutTruncated = false;
|
|
7871
|
+
let stderrTruncated = false;
|
|
7872
|
+
let timedOut = false;
|
|
7873
|
+
let settled = false;
|
|
7874
|
+
const timer = setTimeout(() => {
|
|
7875
|
+
timedOut = true;
|
|
7876
|
+
try {
|
|
7877
|
+
child.kill("SIGKILL");
|
|
7878
|
+
} catch {
|
|
7879
|
+
}
|
|
7880
|
+
}, opts.timeoutMs);
|
|
7881
|
+
child.stdout?.on("data", (chunk) => {
|
|
7882
|
+
const s = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
7883
|
+
if (stdout.length + s.length > MAX_CAPTURE_BYTES) {
|
|
7884
|
+
if (!stdoutTruncated) {
|
|
7885
|
+
stdout += s.slice(0, MAX_CAPTURE_BYTES - stdout.length);
|
|
7886
|
+
stdoutTruncated = true;
|
|
7887
|
+
}
|
|
7888
|
+
return;
|
|
7889
|
+
}
|
|
7890
|
+
stdout += s;
|
|
7891
|
+
});
|
|
7892
|
+
child.stderr?.on("data", (chunk) => {
|
|
7893
|
+
const s = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
7894
|
+
if (stderr.length + s.length > MAX_CAPTURE_BYTES) {
|
|
7895
|
+
if (!stderrTruncated) {
|
|
7896
|
+
stderr += s.slice(0, MAX_CAPTURE_BYTES - stderr.length);
|
|
7897
|
+
stderrTruncated = true;
|
|
7898
|
+
}
|
|
7899
|
+
return;
|
|
7900
|
+
}
|
|
7901
|
+
stderr += s;
|
|
7902
|
+
});
|
|
7903
|
+
const settle = (exit, errorMsg) => {
|
|
7904
|
+
if (settled)
|
|
7905
|
+
return;
|
|
7906
|
+
settled = true;
|
|
7907
|
+
clearTimeout(timer);
|
|
7908
|
+
resolveP({
|
|
7909
|
+
exitCode: exit,
|
|
7910
|
+
stdout: stdoutTruncated ? stdout + TRUNCATION_MARKER : stdout,
|
|
7911
|
+
stderr: stderrTruncated ? stderr + TRUNCATION_MARKER : stderr,
|
|
7912
|
+
timedOut,
|
|
7913
|
+
error: errorMsg
|
|
7914
|
+
});
|
|
7915
|
+
};
|
|
7916
|
+
child.on("error", (err) => {
|
|
7917
|
+
settle(null, errMessage(err));
|
|
7918
|
+
});
|
|
7919
|
+
child.on("close", (code) => {
|
|
7920
|
+
settle(code);
|
|
7921
|
+
});
|
|
7922
|
+
});
|
|
9040
7923
|
}
|
|
9041
|
-
function
|
|
9042
|
-
|
|
9043
|
-
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9049
|
-
|
|
9050
|
-
|
|
9051
|
-
|
|
9052
|
-
return "P5 (Informational)";
|
|
7924
|
+
function finaliseProcessStep(step, spawned, start) {
|
|
7925
|
+
const durationMs = Date.now() - start;
|
|
7926
|
+
if (spawned.timedOut) {
|
|
7927
|
+
return {
|
|
7928
|
+
stepId: step.id,
|
|
7929
|
+
kind: "errored",
|
|
7930
|
+
observedStdout: spawned.stdout,
|
|
7931
|
+
observedStderr: spawned.stderr,
|
|
7932
|
+
durationMs,
|
|
7933
|
+
error: `timeout after ${durationMs}ms`
|
|
7934
|
+
};
|
|
9053
7935
|
}
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
default:
|
|
9064
|
-
return "Low \u2014 informational / minor impact";
|
|
7936
|
+
if (spawned.error && spawned.exitCode === null) {
|
|
7937
|
+
return {
|
|
7938
|
+
stepId: step.id,
|
|
7939
|
+
kind: "errored",
|
|
7940
|
+
observedStdout: spawned.stdout,
|
|
7941
|
+
observedStderr: spawned.stderr,
|
|
7942
|
+
durationMs,
|
|
7943
|
+
error: spawned.error
|
|
7944
|
+
};
|
|
9065
7945
|
}
|
|
9066
|
-
|
|
9067
|
-
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
const
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
return {
|
|
9077
|
-
cvss,
|
|
9078
|
-
cwes,
|
|
9079
|
-
severity,
|
|
9080
|
-
title: finding.title,
|
|
9081
|
-
summary: finding.description.trim(),
|
|
9082
|
-
impact: buildImpactNarrative(finding),
|
|
9083
|
-
attackScenario: buildAttackScenario(finding),
|
|
9084
|
-
steps,
|
|
9085
|
-
poc,
|
|
9086
|
-
affected: buildAffectedLine(finding, ctx),
|
|
9087
|
-
remediation: buildRemediation(finding, ctx),
|
|
9088
|
-
references: buildReferences(finding, cwes),
|
|
9089
|
-
severityCvss31: renderCvssSection({ vector: cvss.vector, score: cvss.score, severity }),
|
|
9090
|
-
severityCvss40: renderCvssSection({
|
|
9091
|
-
vector: cvss4.vector,
|
|
9092
|
-
score: cvss4.score,
|
|
9093
|
-
severity: cvss4.severity
|
|
9094
|
-
})
|
|
7946
|
+
const verdict = evaluateExpect(step.expect, {
|
|
7947
|
+
exitCode: spawned.exitCode,
|
|
7948
|
+
stdout: spawned.stdout
|
|
7949
|
+
});
|
|
7950
|
+
const result = {
|
|
7951
|
+
stepId: step.id,
|
|
7952
|
+
kind: verdict.kind,
|
|
7953
|
+
observedStdout: spawned.stdout,
|
|
7954
|
+
observedStderr: spawned.stderr,
|
|
7955
|
+
durationMs
|
|
9095
7956
|
};
|
|
7957
|
+
if (spawned.exitCode !== null)
|
|
7958
|
+
result.observedExit = spawned.exitCode;
|
|
7959
|
+
if (verdict.error)
|
|
7960
|
+
result.error = verdict.error;
|
|
7961
|
+
return result;
|
|
9096
7962
|
}
|
|
9097
|
-
function
|
|
9098
|
-
|
|
9099
|
-
|
|
9100
|
-
|
|
7963
|
+
function evaluateExpect(expect, obs) {
|
|
7964
|
+
if (!expect) {
|
|
7965
|
+
return { kind: "passed" };
|
|
7966
|
+
}
|
|
7967
|
+
switch (expect.type) {
|
|
7968
|
+
case "exit-zero": {
|
|
7969
|
+
if (obs.exitCode === 0)
|
|
7970
|
+
return { kind: "passed" };
|
|
7971
|
+
return {
|
|
7972
|
+
kind: "failed",
|
|
7973
|
+
error: `expected exit-zero, got exitCode=${String(obs.exitCode ?? "unknown")}`
|
|
7974
|
+
};
|
|
7975
|
+
}
|
|
7976
|
+
case "http-status": {
|
|
7977
|
+
const wanted = Array.isArray(expect.status) ? expect.status : [expect.status];
|
|
7978
|
+
if (typeof obs.status === "number" && wanted.includes(obs.status)) {
|
|
7979
|
+
return { kind: "passed" };
|
|
7980
|
+
}
|
|
7981
|
+
return {
|
|
7982
|
+
kind: "failed",
|
|
7983
|
+
error: `expected http-status in [${wanted.join(",")}], got ${String(obs.status ?? "no-response")}`
|
|
7984
|
+
};
|
|
7985
|
+
}
|
|
7986
|
+
case "body-contains": {
|
|
7987
|
+
const haystack = obs.body ?? obs.stdout ?? "";
|
|
7988
|
+
if (haystack.includes(expect.text))
|
|
7989
|
+
return { kind: "passed" };
|
|
7990
|
+
return {
|
|
7991
|
+
kind: "failed",
|
|
7992
|
+
error: `expected body-contains '${expect.text}', not found in observed output`
|
|
7993
|
+
};
|
|
7994
|
+
}
|
|
7995
|
+
case "body-matches": {
|
|
7996
|
+
const haystack = obs.body ?? obs.stdout ?? "";
|
|
7997
|
+
let re;
|
|
7998
|
+
try {
|
|
7999
|
+
re = new RegExp(expect.pattern);
|
|
8000
|
+
} catch (err) {
|
|
8001
|
+
return { kind: "errored", error: `invalid regex: ${errMessage(err)}` };
|
|
8002
|
+
}
|
|
8003
|
+
if (re.test(haystack))
|
|
8004
|
+
return { kind: "passed" };
|
|
8005
|
+
return {
|
|
8006
|
+
kind: "failed",
|
|
8007
|
+
error: `expected body-matches /${expect.pattern}/, no match in observed output`
|
|
8008
|
+
};
|
|
8009
|
+
}
|
|
8010
|
+
case "file-exists": {
|
|
8011
|
+
return {
|
|
8012
|
+
kind: "errored",
|
|
8013
|
+
error: "file-exists predicate cannot be evaluated against a network target; rewrite as a shell action with `[ -e <path> ]`"
|
|
8014
|
+
};
|
|
8015
|
+
}
|
|
8016
|
+
default: {
|
|
8017
|
+
const _exhaustive = expect;
|
|
8018
|
+
return {
|
|
8019
|
+
kind: "errored",
|
|
8020
|
+
error: `unknown expect type: ${JSON.stringify(_exhaustive)}`
|
|
8021
|
+
};
|
|
8022
|
+
}
|
|
9101
8023
|
}
|
|
9102
|
-
return {
|
|
9103
|
-
platform,
|
|
9104
|
-
title: parts.title,
|
|
9105
|
-
markdown: out.join("\n").replace(/\n{3,}/g, "\n\n"),
|
|
9106
|
-
cvssVector: parts.cvss.vector,
|
|
9107
|
-
cvssScore: parts.cvss.score,
|
|
9108
|
-
severity: parts.severity,
|
|
9109
|
-
sections
|
|
9110
|
-
};
|
|
9111
8024
|
}
|
|
9112
|
-
function
|
|
9113
|
-
|
|
9114
|
-
|
|
9115
|
-
|
|
9116
|
-
|
|
9117
|
-
|
|
9118
|
-
|
|
9119
|
-
|
|
9120
|
-
|
|
9121
|
-
|
|
9122
|
-
"
|
|
9123
|
-
|
|
9124
|
-
|
|
9125
|
-
"
|
|
9126
|
-
|
|
9127
|
-
|
|
9128
|
-
|
|
9129
|
-
|
|
9130
|
-
|
|
9131
|
-
|
|
9132
|
-
|
|
9133
|
-
|
|
9134
|
-
|
|
9135
|
-
|
|
9136
|
-
|
|
9137
|
-
|
|
9138
|
-
|
|
9139
|
-
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
|
|
9143
|
-
|
|
9144
|
-
}
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
|
|
9150
|
-
|
|
9151
|
-
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
|
|
9159
|
-
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
9164
|
-
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
}
|
|
9168
|
-
|
|
9169
|
-
|
|
9170
|
-
|
|
9171
|
-
|
|
9172
|
-
|
|
9173
|
-
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
9180
|
-
|
|
9181
|
-
|
|
9182
|
-
|
|
9183
|
-
|
|
9184
|
-
"Domain / Endpoint",
|
|
9185
|
-
"Vulnerability Type",
|
|
9186
|
-
"Impact",
|
|
9187
|
-
"Steps to Reproduce",
|
|
9188
|
-
"Proof of Concept",
|
|
9189
|
-
"Severity",
|
|
9190
|
-
"Recommended Fix"
|
|
9191
|
-
],
|
|
9192
|
-
render(finding, ctx = {}) {
|
|
9193
|
-
const parts = buildCommonParts(finding, ctx);
|
|
9194
|
-
const primaryCwe = parts.cwes[0];
|
|
9195
|
-
const sections = [
|
|
9196
|
-
{ heading: "Summary", body: parts.summary },
|
|
9197
|
-
{ heading: "Domain / Endpoint", body: parts.affected },
|
|
9198
|
-
{
|
|
9199
|
-
heading: "Vulnerability Type",
|
|
9200
|
-
body: primaryCwe ? `${primaryCwe.id}: ${primaryCwe.name} (category: \`${finding.category}\`)` : `Category: \`${finding.category}\``
|
|
9201
|
-
},
|
|
9202
|
-
{ heading: "Impact", body: parts.impact },
|
|
9203
|
-
{ heading: "Steps to Reproduce", body: stepsBodyOrPoc(parts) },
|
|
9204
|
-
{ heading: "Proof of Concept", body: parts.poc || "_See Steps to Reproduce._" },
|
|
9205
|
-
{ heading: "Severity", body: parts.severityCvss31 },
|
|
9206
|
-
{ heading: "Recommended Fix", body: parts.remediation },
|
|
9207
|
-
{ heading: "References", body: parts.references }
|
|
9208
|
-
];
|
|
9209
|
-
return assembleReport("intigriti", parts, sections);
|
|
9210
|
-
}
|
|
9211
|
-
};
|
|
9212
|
-
var IMMUNEFI_TEMPLATE = {
|
|
9213
|
-
id: "immunefi",
|
|
9214
|
-
label: "Immunefi (web3)",
|
|
9215
|
-
description: "Immunefi web3 order: Bug Description \u2192 Impact (funds/assets at risk) \u2192 Impact-in-Detail \u2192 Attack Scenario \u2192 PoC \u2192 Affected Assets \u2192 Recommendation. Impact-based severity + CVSS 4.0.",
|
|
9216
|
-
requiredSections: [
|
|
9217
|
-
"Bug Description",
|
|
9218
|
-
"Impact",
|
|
9219
|
-
"Severity",
|
|
9220
|
-
"Attack Scenario",
|
|
9221
|
-
"Proof of Concept",
|
|
9222
|
-
"Affected Assets",
|
|
9223
|
-
"Recommendation"
|
|
9224
|
-
],
|
|
9225
|
-
render(finding, ctx = {}) {
|
|
9226
|
-
const parts = buildCommonParts(finding, ctx);
|
|
9227
|
-
const sections = [
|
|
9228
|
-
{ heading: "Bug Description", body: parts.summary },
|
|
9229
|
-
{ heading: "Impact", body: parts.impact },
|
|
9230
|
-
{
|
|
9231
|
-
heading: "Severity",
|
|
9232
|
-
body: `**${immunefiSeverity(finding.severity)}**
|
|
9233
|
-
|
|
9234
|
-
${parts.severityCvss40}
|
|
9235
|
-
|
|
9236
|
-
${parts.severityCvss31}`
|
|
9237
|
-
},
|
|
9238
|
-
{
|
|
9239
|
-
heading: "Attack Scenario",
|
|
9240
|
-
body: parts.attackScenario || stepsBodyOrPoc(parts)
|
|
9241
|
-
},
|
|
9242
|
-
{
|
|
9243
|
-
heading: "Proof of Concept",
|
|
9244
|
-
body: [parts.steps, parts.poc].filter(Boolean).join("\n\n") || "_Attach a runnable PoC / test before submission._"
|
|
9245
|
-
},
|
|
9246
|
-
{ heading: "Affected Assets", body: parts.affected },
|
|
9247
|
-
{ heading: "Recommendation", body: parts.remediation },
|
|
9248
|
-
{ heading: "References", body: parts.references }
|
|
9249
|
-
];
|
|
9250
|
-
return assembleReport("immunefi", parts, sections);
|
|
9251
|
-
}
|
|
9252
|
-
};
|
|
9253
|
-
var GENERIC_TEMPLATE = {
|
|
9254
|
-
id: "generic",
|
|
9255
|
-
label: "Generic / Default",
|
|
9256
|
-
description: "Platform-neutral, impact-first structure: Summary \u2192 Impact \u2192 Affected \u2192 Steps \u2192 PoC \u2192 Severity (CVSS) \u2192 Remediation \u2192 References.",
|
|
9257
|
-
requiredSections: [
|
|
9258
|
-
"Summary",
|
|
9259
|
-
"Impact",
|
|
9260
|
-
"Affected Assets",
|
|
9261
|
-
"Steps to Reproduce",
|
|
9262
|
-
"Proof of Concept",
|
|
9263
|
-
"Severity",
|
|
9264
|
-
"Remediation",
|
|
9265
|
-
"References"
|
|
9266
|
-
],
|
|
9267
|
-
render(finding, ctx = {}) {
|
|
9268
|
-
const parts = buildCommonParts(finding, ctx);
|
|
9269
|
-
const sections = [
|
|
9270
|
-
{ heading: "Summary", body: parts.summary },
|
|
9271
|
-
{ heading: "Impact", body: parts.impact },
|
|
9272
|
-
{ heading: "Affected Assets", body: parts.affected },
|
|
9273
|
-
{ heading: "Steps to Reproduce", body: stepsBodyOrPoc(parts) },
|
|
9274
|
-
{ heading: "Proof of Concept", body: parts.poc || "_See Steps to Reproduce._" },
|
|
9275
|
-
{ heading: "Severity", body: `${parts.severityCvss31}
|
|
9276
|
-
|
|
9277
|
-
_${cvssSourceLabel(parts.cvss)}_` },
|
|
9278
|
-
{ heading: "Remediation", body: parts.remediation },
|
|
9279
|
-
{ heading: "References", body: parts.references }
|
|
9280
|
-
];
|
|
9281
|
-
return assembleReport("generic", parts, sections);
|
|
9282
|
-
}
|
|
9283
|
-
};
|
|
9284
|
-
function cvssSourceLabel(cvss) {
|
|
9285
|
-
return cvss.source === "finding" ? "CVSS source: populated on the finding by 0sec." : cvss.source === "impact-assessment" ? "CVSS source: exploitability derived from 0sec's reachability assessment; impact from category \u2014 verify against your deployment." : "CVSS source: heuristic from category + severity \u2014 verify before submission.";
|
|
8025
|
+
function aggregateVerdict(graph, steps) {
|
|
8026
|
+
if (graph.length === 0) {
|
|
8027
|
+
return "could_not_run";
|
|
8028
|
+
}
|
|
8029
|
+
const byId = new Map(steps.map((s) => [s.stepId, s]));
|
|
8030
|
+
let reachedExploitOrVerify = false;
|
|
8031
|
+
for (const step of graph) {
|
|
8032
|
+
const result = byId.get(step.id);
|
|
8033
|
+
if (!result)
|
|
8034
|
+
continue;
|
|
8035
|
+
if (step.kind === "exploit" || step.kind === "verify") {
|
|
8036
|
+
reachedExploitOrVerify = true;
|
|
8037
|
+
}
|
|
8038
|
+
if (result.kind === "errored" && (step.kind === "setup" || step.kind === "auth" || step.kind === "prerequisite")) {
|
|
8039
|
+
return "could_not_run";
|
|
8040
|
+
}
|
|
8041
|
+
}
|
|
8042
|
+
const verifySteps = graph.filter((s) => s.kind === "verify");
|
|
8043
|
+
if (verifySteps.length > 0) {
|
|
8044
|
+
let anyFailed = false;
|
|
8045
|
+
let anyErrored = false;
|
|
8046
|
+
let allPassed = true;
|
|
8047
|
+
for (const v of verifySteps) {
|
|
8048
|
+
const result = byId.get(v.id);
|
|
8049
|
+
if (!result || result.kind === "skipped") {
|
|
8050
|
+
allPassed = false;
|
|
8051
|
+
anyErrored = true;
|
|
8052
|
+
continue;
|
|
8053
|
+
}
|
|
8054
|
+
if (result.kind === "failed") {
|
|
8055
|
+
anyFailed = true;
|
|
8056
|
+
allPassed = false;
|
|
8057
|
+
} else if (result.kind === "errored") {
|
|
8058
|
+
anyErrored = true;
|
|
8059
|
+
allPassed = false;
|
|
8060
|
+
}
|
|
8061
|
+
}
|
|
8062
|
+
if (allPassed)
|
|
8063
|
+
return "exploit_still_works";
|
|
8064
|
+
if (anyFailed)
|
|
8065
|
+
return "exploit_broken";
|
|
8066
|
+
if (anyErrored)
|
|
8067
|
+
return "could_not_run";
|
|
8068
|
+
}
|
|
8069
|
+
const exploitSteps = graph.filter((s) => s.kind === "exploit");
|
|
8070
|
+
if (exploitSteps.length > 0) {
|
|
8071
|
+
let anyFailed = false;
|
|
8072
|
+
let anyErrored = false;
|
|
8073
|
+
let allPassed = true;
|
|
8074
|
+
for (const e of exploitSteps) {
|
|
8075
|
+
const result = byId.get(e.id);
|
|
8076
|
+
if (!result || result.kind === "skipped") {
|
|
8077
|
+
allPassed = false;
|
|
8078
|
+
anyErrored = true;
|
|
8079
|
+
continue;
|
|
8080
|
+
}
|
|
8081
|
+
if (result.kind === "failed") {
|
|
8082
|
+
anyFailed = true;
|
|
8083
|
+
allPassed = false;
|
|
8084
|
+
} else if (result.kind === "errored") {
|
|
8085
|
+
anyErrored = true;
|
|
8086
|
+
allPassed = false;
|
|
8087
|
+
}
|
|
8088
|
+
}
|
|
8089
|
+
if (allPassed)
|
|
8090
|
+
return "exploit_still_works";
|
|
8091
|
+
if (anyFailed)
|
|
8092
|
+
return "exploit_broken";
|
|
8093
|
+
if (anyErrored)
|
|
8094
|
+
return "could_not_run";
|
|
8095
|
+
}
|
|
8096
|
+
return reachedExploitOrVerify ? "exploit_still_works" : "could_not_run";
|
|
9286
8097
|
}
|
|
9287
|
-
|
|
9288
|
-
|
|
9289
|
-
|
|
9290
|
-
|
|
9291
|
-
|
|
9292
|
-
|
|
9293
|
-
|
|
9294
|
-
|
|
9295
|
-
|
|
9296
|
-
label: t.label,
|
|
9297
|
-
description: t.description
|
|
9298
|
-
}));
|
|
9299
|
-
function reportTemplate(platform) {
|
|
9300
|
-
if (platform && platform in TEMPLATE_REGISTRY) {
|
|
9301
|
-
return TEMPLATE_REGISTRY[platform];
|
|
8098
|
+
function errMessage(err) {
|
|
8099
|
+
if (err instanceof Error)
|
|
8100
|
+
return err.message;
|
|
8101
|
+
if (typeof err === "string")
|
|
8102
|
+
return err;
|
|
8103
|
+
try {
|
|
8104
|
+
return JSON.stringify(err);
|
|
8105
|
+
} catch {
|
|
8106
|
+
return String(err);
|
|
9302
8107
|
}
|
|
9303
|
-
return GENERIC_TEMPLATE;
|
|
9304
|
-
}
|
|
9305
|
-
function renderPlatformReport(finding, platform, ctx = {}) {
|
|
9306
|
-
return reportTemplate(platform).render(finding, ctx);
|
|
9307
8108
|
}
|
|
9308
8109
|
|
|
9309
8110
|
export {
|
|
@@ -9311,27 +8112,14 @@ export {
|
|
|
9311
8112
|
hasKnownMarkerText,
|
|
9312
8113
|
detectKnownMarkers,
|
|
9313
8114
|
analyzeFindingForKnownMarkers,
|
|
9314
|
-
|
|
9315
|
-
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
renderCvssSection,
|
|
9325
|
-
extractFileRefs,
|
|
9326
|
-
verifyAgainstRef,
|
|
9327
|
-
formatPatchStatusSection,
|
|
9328
|
-
detectVersionRange,
|
|
9329
|
-
formatVersionRangeLine,
|
|
9330
|
-
EmptyPocError,
|
|
9331
|
-
redactSensitiveHeaders,
|
|
9332
|
-
redactAuthHeaders,
|
|
9333
|
-
renderAdvisoryMarkdown,
|
|
9334
|
-
REPORT_PLATFORMS,
|
|
9335
|
-
reportTemplate,
|
|
9336
|
-
renderPlatformReport
|
|
8115
|
+
MAX_CAPTURE_BYTES,
|
|
8116
|
+
DEFAULT_STEP_TIMEOUT_MS,
|
|
8117
|
+
acquireHostToken,
|
|
8118
|
+
markHostRateLimited,
|
|
8119
|
+
setRuntimeDeps,
|
|
8120
|
+
executePocSteps,
|
|
8121
|
+
resolveUrl,
|
|
8122
|
+
mergePersonaHeaders,
|
|
8123
|
+
evaluateExpect,
|
|
8124
|
+
aggregateVerdict
|
|
9337
8125
|
};
|