From 92b9ac373e8512b722f68451e43830df1bd46cf8 Mon Sep 17 00:00:00 2001 From: dotmantissa Date: Tue, 3 Nov 2026 17:39:03 +0100 Subject: [PATCH] ci: require security analysis and Rust invariants and advisory checks --- .github/CODEOWNERS | 21 + .github/dependabot.yml | 10 + .github/rustsec-native-host.json | 8 + .github/security-requirements.in | 2 + .github/security-requirements.txt | 1204 +++++++++++++++++ .github/security-rules/LICENSE | 1 + ...script__aws-lambda__security__pg-sqli.yaml | 63 + ...ipt__browser__security__dom-based-xss.yaml | 34 + ...ipt__browser__security__eval-detected.yaml | 35 + ...r__security__insecure-document-method.yaml | 40 + ...browser__security__insecure-innerhtml.yaml | 32 + ...ficient-postmessage-origin-validation.yaml | 51 + ...security__open-redirect-from-function.yaml | 58 + ...ipt__browser__security__open-redirect.yaml | 95 ++ ...t__browser__security__raw-html-concat.yaml | 167 +++ ...ipt__browser__security__raw-html-join.yaml | 43 + ...y__wildcard-postmessage-configuration.yaml | 26 + ...ang__security__detect-buffer-noassert.yaml | 32 + ..._lang__security__detect-child-process.yaml | 79 ++ ...urity__detect-disable-mustache-escape.yaml | 27 + ...security__detect-eval-with-expression.yaml | 88 ++ ...__security__detect-insecure-websocket.yaml | 32 + ...detect-no-csrf-before-method-override.yaml | 35 + ...g__security__detect-pseudoRandomBytes.yaml | 32 + ...ng__security__html-in-template-string.yaml | 36 + ...ang__security__insecure-object-assign.yaml | 33 + ...ript__lang__security__spawn-git-clone.yaml | 40 + .github/security-rules/provenance.json | 166 +++ .../rust__lang__security__args-os.yml | 21 + .../rust__lang__security__args.yml | 21 + .../rust__lang__security__current-exe.yml | 21 + .../rust__lang__security__insecure-hashes.yml | 25 + ...lang__security__reqwest-accept-invalid.yml | 20 + ..._lang__security__reqwest-set-sensitive.yml | 44 + ...rust__lang__security__rustls-dangerous.yml | 24 + .../rust__lang__security__ssl-verify-none.yml | 17 + .../rust__lang__security__temp-dir.yml | 23 + .../rust__lang__security__unsafe-usage.yml | 17 + ..._audit__react-dangerouslysetinnerhtml.yaml | 147 ++ ...eact__security__audit__react-href-var.yaml | 90 ++ ...ty__audit__react-jwt-decoded-property.yaml | 32 + ...ity__audit__react-jwt-in-localstorage.yaml | 38 + ...rity__audit__react-unsanitized-method.yaml | 148 ++ ...ty__audit__react-unsanitized-property.yaml | 162 +++ ...act__security__react-insecure-request.yaml | 62 + ...ecurity__react-markdown-insecure-html.yaml | 51 + .github/semgrep-project.yml | 14 + .github/workflows/verify.yml | 19 +- .semgrepignore | 13 + docs/CI_SECURITY.md | 17 + evidence/host-fixture.json | 8 +- fixtures/src/tests.rs | 163 ++- fixtures/src/tests/migrations.rs | 4 +- guard/src/lib.rs | 2 + migration/src/lib.rs | 4 + scripts/audit-rust.py | 43 + scripts/check-workflows.py | 52 + scripts/scan-security.py | 40 + scripts/test_security.py | 83 ++ 59 files changed, 3871 insertions(+), 44 deletions(-) create mode 100644 .github/rustsec-native-host.json create mode 100644 .github/security-requirements.in create mode 100644 .github/security-requirements.txt create mode 100644 .github/security-rules/LICENSE create mode 100644 .github/security-rules/javascript__aws-lambda__security__pg-sqli.yaml create mode 100644 .github/security-rules/javascript__browser__security__dom-based-xss.yaml create mode 100644 .github/security-rules/javascript__browser__security__eval-detected.yaml create mode 100644 .github/security-rules/javascript__browser__security__insecure-document-method.yaml create mode 100644 .github/security-rules/javascript__browser__security__insecure-innerhtml.yaml create mode 100644 .github/security-rules/javascript__browser__security__insufficient-postmessage-origin-validation.yaml create mode 100644 .github/security-rules/javascript__browser__security__open-redirect-from-function.yaml create mode 100644 .github/security-rules/javascript__browser__security__open-redirect.yaml create mode 100644 .github/security-rules/javascript__browser__security__raw-html-concat.yaml create mode 100644 .github/security-rules/javascript__browser__security__raw-html-join.yaml create mode 100644 .github/security-rules/javascript__browser__security__wildcard-postmessage-configuration.yaml create mode 100644 .github/security-rules/javascript__lang__security__detect-buffer-noassert.yaml create mode 100644 .github/security-rules/javascript__lang__security__detect-child-process.yaml create mode 100644 .github/security-rules/javascript__lang__security__detect-disable-mustache-escape.yaml create mode 100644 .github/security-rules/javascript__lang__security__detect-eval-with-expression.yaml create mode 100644 .github/security-rules/javascript__lang__security__detect-insecure-websocket.yaml create mode 100644 .github/security-rules/javascript__lang__security__detect-no-csrf-before-method-override.yaml create mode 100644 .github/security-rules/javascript__lang__security__detect-pseudoRandomBytes.yaml create mode 100644 .github/security-rules/javascript__lang__security__html-in-template-string.yaml create mode 100644 .github/security-rules/javascript__lang__security__insecure-object-assign.yaml create mode 100644 .github/security-rules/javascript__lang__security__spawn-git-clone.yaml create mode 100644 .github/security-rules/provenance.json create mode 100644 .github/security-rules/rust__lang__security__args-os.yml create mode 100644 .github/security-rules/rust__lang__security__args.yml create mode 100644 .github/security-rules/rust__lang__security__current-exe.yml create mode 100644 .github/security-rules/rust__lang__security__insecure-hashes.yml create mode 100644 .github/security-rules/rust__lang__security__reqwest-accept-invalid.yml create mode 100644 .github/security-rules/rust__lang__security__reqwest-set-sensitive.yml create mode 100644 .github/security-rules/rust__lang__security__rustls-dangerous.yml create mode 100644 .github/security-rules/rust__lang__security__ssl-verify-none.yml create mode 100644 .github/security-rules/rust__lang__security__temp-dir.yml create mode 100644 .github/security-rules/rust__lang__security__unsafe-usage.yml create mode 100644 .github/security-rules/typescript__react__security__audit__react-dangerouslysetinnerhtml.yaml create mode 100644 .github/security-rules/typescript__react__security__audit__react-href-var.yaml create mode 100644 .github/security-rules/typescript__react__security__audit__react-jwt-decoded-property.yaml create mode 100644 .github/security-rules/typescript__react__security__audit__react-jwt-in-localstorage.yaml create mode 100644 .github/security-rules/typescript__react__security__audit__react-unsanitized-method.yaml create mode 100644 .github/security-rules/typescript__react__security__audit__react-unsanitized-property.yaml create mode 100644 .github/security-rules/typescript__react__security__react-insecure-request.yaml create mode 100644 .github/security-rules/typescript__react__security__react-markdown-insecure-html.yaml create mode 100644 .github/semgrep-project.yml create mode 100644 .semgrepignore create mode 100644 docs/CI_SECURITY.md create mode 100644 scripts/audit-rust.py create mode 100644 scripts/check-workflows.py create mode 100644 scripts/scan-security.py create mode 100644 scripts/test_security.py diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 67d6346..534836f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -15,3 +15,24 @@ /guard/ @dotmantissa /migration/ @dotmantissa /sdk/src/generated/ @dotmantissa + +# Security policy and value-moving source always require owner review. +/.semgrepignore @dotmantissa +/src/ @dotmantissa +/sdk/src/ @dotmantissa +/api/ @dotmantissa +/embed/src/ @dotmantissa +/copy/src/ @dotmantissa +/package.json @dotmantissa +/sdk/package.json @dotmantissa +/embed/package.json @dotmantissa +/fixtures/ @dotmantissa +/tests/ @dotmantissa +/test/ @dotmantissa + +# Build/test configuration and nested manifests are also part of the trust boundary. +**/package.json @dotmantissa +**/Cargo.toml @dotmantissa +/tsconfig*.json @dotmantissa +/playwright*.ts @dotmantissa +/vitest*.ts @dotmantissa diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8004983..eb726f2 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,3 +5,13 @@ updates: schedule: interval: weekly open-pull-requests-limit: 5 + - package-ecosystem: cargo + directory: / + schedule: + interval: weekly + open-pull-requests-limit: 5 + - package-ecosystem: pip + directory: /.github + schedule: + interval: weekly + open-pull-requests-limit: 5 diff --git a/.github/rustsec-native-host.json b/.github/rustsec-native-host.json new file mode 100644 index 0000000..d007e73 --- /dev/null +++ b/.github/rustsec-native-host.json @@ -0,0 +1,8 @@ +{ + "advisory": "RUSTSEC-2026-0387", + "package": "crypto-bigint", + "version": "0.5.5", + "expires": "2027-01-01", + "reason": "Only pinned Soroban native test host through elliptic-curve 0.13.8 / k256 / p256. Absent from normal guard and migration wasm32v1-none graphs, checked on every run. Fixtures use mocked owner authorization and public-input host verification; no production secret scalar operations are performed here. Patched crypto-bigint >=0.7.6 requires an upstream major-version transition. Preserve deployed guest hashes and review upstream upgrade before expiry.", + "upstream": "https://github.com/RustCrypto/crypto-bigint/pull/1365" +} diff --git a/.github/security-requirements.in b/.github/security-requirements.in new file mode 100644 index 0000000..9df718d --- /dev/null +++ b/.github/security-requirements.in @@ -0,0 +1,2 @@ +semgrep==1.183.0 +PyYAML==6.0.3 diff --git a/.github/security-requirements.txt b/.github/security-requirements.txt new file mode 100644 index 0000000..0a62193 --- /dev/null +++ b/.github/security-requirements.txt @@ -0,0 +1,1204 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile .tooling/publish/frontend/.github/security-requirements.in --python .tooling/cicd/scan-env/bin/python --generate-hashes --output-file .tooling/publish/frontend/.github/security-requirements.txt +annotated-types==0.8.0 \ + --hash=sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7 \ + --hash=sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0 + # via pydantic +anyio==4.16.0 \ + --hash=sha256:59bb03251907983d1603d27c3087ddb1e93299ea2163adcdba37899a4fb12ffb \ + --hash=sha256:c66ae634e0b8228396b801741beb3294326d4b6102f7bba4041c0dfb58c29026 + # via + # httpx + # mcp + # sse-starlette + # starlette +attrs==26.1.0 \ + --hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \ + --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32 + # via + # glom + # jsonschema + # referencing + # semgrep +boltons==21.0.0 \ + --hash=sha256:65e70a79a731a7fe6e98592ecfb5ccf2115873d01dbc576079874629e5c90f13 \ + --hash=sha256:b9bb7b58b2b420bbe11a6025fdef6d3e5edc9f76a42fb467afe7ca212ef9948b + # via + # face + # glom + # semgrep +bracex==3.2.1 \ + --hash=sha256:07a9b2100ceecc0c24afa1a1714bf8d4a6abb43d592939455f662b682ac9baa4 \ + --hash=sha256:e8622d46b60ef6062b4091033f97a304e1b205e70c0285743c5038b73886a47e + # via wcmatch +certifi==2026.10.23 \ + --hash=sha256:a9895e6e2758b371e0545e321a3a8fd1fcfd9829ada8824a936dfb16aaaf36cd \ + --hash=sha256:e9b54de76e530bb6cf0ccd036787103acb58fd42ba930ea8bf948ddbaa2f61d1 + # via + # httpcore + # httpx + # requests + # semgrep +cffi==2.1.1 \ + --hash=sha256:046bfc24911b37851ee1b51aab8bffe713d89c68c6a057b09484ce9fd5f69b4e \ + --hash=sha256:06c72bb76605a4b0cd0aad6930b69d4baf7dd5d806cfc409b824191099700e66 \ + --hash=sha256:0beceaabe56af686895136a2de78db54ecd8e4046b236b8fd6d6cb61389e9bf2 \ + --hash=sha256:154852545011f779917b11c78db2358d095da62a9a172b78ad0a583ee5adc0d0 \ + --hash=sha256:194cffa889098ced9976c3fc6340305e43f6303657d298da55366907c05c22d6 \ + --hash=sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971 \ + --hash=sha256:1a18a57b58cfb21fc28d72e876acf10eaed67a1ed96226f92af4df681d571c4c \ + --hash=sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d \ + --hash=sha256:1dea0e4d7d4f11f619fe8c1d76caf49e24405b4b5743c0e3be16a500ecd930c9 \ + --hash=sha256:208f941bb9d18e768138677f0a6d2ce01f590df56043dda1df1535ac57c88517 \ + --hash=sha256:210019b6c7cf07f081b4c54635c8cf744377001350e29cc0f81c4377b4797735 \ + --hash=sha256:246fa40ce8645a614ff682e0b70f37134e460eaf93a775e0cbe3cca585a67a80 \ + --hash=sha256:25792eac27877609e7bb06d42ff88278a6624fff2ba9bbb523c09616b117e80f \ + --hash=sha256:27350daa11d4f10c540e6e89dada4c54feb7256ad03e9a4dc075ebad7ba360d1 \ + --hash=sha256:28907ab9bfb6aa13184cfc17c6b8e1023c5ab6fd7076d8c20a35e59fe04f8f29 \ + --hash=sha256:2ae64be792b8966f2c69538199728b290e34726562896df1e5dc8ffd8d8188e8 \ + --hash=sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c \ + --hash=sha256:3143d81e29e1e20a9ce10901ec369012947876596f75a222235965f2b7ae832e \ + --hash=sha256:3222ba5d678f80a030e6afbcc33dc1ae5cb45facabb61cee2c7016b8432fde48 \ + --hash=sha256:3311ed60d36f83378794e1009ac6258bafbf81f7888b4caa7b35a521e3f95813 \ + --hash=sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac \ + --hash=sha256:34e261f78cb6ceaaa36f42f2613f4380d94d9c759a9c73c769ee6e0247364632 \ + --hash=sha256:363e05fa78e15116c3c32c210ee36884fd6b9afa6d440e47112c3bd511d64cb6 \ + --hash=sha256:398aff33cee2767e3e781d2554c54bd0dff386bb437581e0d8011fde1a942ec1 \ + --hash=sha256:3d22a20b1fb1632cc72c22f95f7b0d2961c3e1c235f245ba4c606c4771035659 \ + --hash=sha256:42a494cee34437f05546455144f2b5d9ac09b1face62bcfce597d2e521066688 \ + --hash=sha256:42e2f76b9455f5a9a844f770bf3e200ed3da0e15f5df3db9c31fe80b04b3d004 \ + --hash=sha256:42f6930c31dc7f50732c9ae793c2786c7b6b044195967bbdde40bb9be81c4cc0 \ + --hash=sha256:456a61fa52d579ebf9df2e9552ead5129855dbaff6c1e5a9b1bc408809bdc062 \ + --hash=sha256:471cee653ae88de62096552e6d24ccb4a5adb8c8c9f10b5054d0122c15bf2779 \ + --hash=sha256:49cbc70e6542d4ccccb936558d1064a8012541e78f821f955cff24e357776c94 \ + --hash=sha256:4a7c934f7360e8cd64fe9efadcbd10c7c6364f531e432b9a4bf5ccbc9e0e8b50 \ + --hash=sha256:4be96343e422f2dfcd12ab5c9f5aebe03f82f737c6bffeca6830b3875cb44aab \ + --hash=sha256:4f42141fc14250de6dde5ee7ea4432be017252d91f19c5ad043c084cea629cac \ + --hash=sha256:507a24c282e0f42f8ed737cf048572cbf580468da5555764a8331735e9c736b6 \ + --hash=sha256:51b31d1c98274844cfd7838ce00bfc27c7423a4dc00fc0772fc3331c2cc90676 \ + --hash=sha256:58acb8ab8e295e6c5ea12f888cbb13cf21511ef2a3303a23f4325c29d17fe5c1 \ + --hash=sha256:5a59cc1c4442bc3d5c703bf720b51138d0bfc173618807c9ee2490a7541dd3d9 \ + --hash=sha256:5bb4e7ea95dcd6a014a6fef62e62467d67d8e582326443f3d68e71d6320a9fcf \ + --hash=sha256:5c58fe613dc5e5336357eff555824a314d8e43282600435c8d1cb6a7a2fedd13 \ + --hash=sha256:5e7cecbaadb83884793e05828cee59b210b24583b9c7425d0ba6a754fe22eb4e \ + --hash=sha256:616f097f2fe415bc92a247f02e11f634e1f9e9a83d327e3c915c15089c87869e \ + --hash=sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973 \ + --hash=sha256:64faea20f4e2613363a1a9b9c7dd73058f3ecd00133a511e72ad7c511658f527 \ + --hash=sha256:661c298b4821edebead0c91edd2b00374d67ad7c5a1f7a91d4442633b79d6a72 \ + --hash=sha256:68e62fe11f30d5ca8289242866f0a5291402d8529ca2178ab8afc5c9694ae890 \ + --hash=sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c \ + --hash=sha256:6e192623c49c94421616a5778fba35cf0d5a8d000650c1967ef4448ee5cdd990 \ + --hash=sha256:7225e4514edb64eb6740324353e0da0711954fd8d7da4576755b1c6e09b697cd \ + --hash=sha256:75f80557d1389eddbd0de2681f6a390a0c5338c31ddaa821381c203fc3fd50d9 \ + --hash=sha256:770de9db11e84213beec501cfcaa013b019820ca881e03344dea5844f7876d94 \ + --hash=sha256:7750c6449dff7864bb9bb27ddfb0267756189201a3afc911d82b3caacd70dfc3 \ + --hash=sha256:7bde5e4cc5c10140859842b9d383af292b22639a4dffb725314baf45968cef80 \ + --hash=sha256:7ce713ace7c0e4520535b42b77eaa742c16dab813978064913e5a3cf82973b41 \ + --hash=sha256:7da0c5eff80f0197f3b3d1232ec5a682a9325f4ae9016a78f5f5ca35f9ced1f5 \ + --hash=sha256:7dbb61fe3a7699468030f71bbe5f8a0e326a151daa91beb11a6fc1f980c55e1c \ + --hash=sha256:811bd1e21d32de12efca32393a0ab3f5133b54fce9bd44b8bd77ab07da14bf6a \ + --hash=sha256:8ef53b2de9bcb9197d31854256575d59dbac0cba72ac627bb291ef5eceb74be4 \ + --hash=sha256:937c0052c05a31ca1daf18de3158eed4dbfcb9cc107adbea227728d647be701e \ + --hash=sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6 \ + --hash=sha256:9f8d177621de5cb38ee3e731eda45d421db093ec0739f46a5594babda7987a98 \ + --hash=sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b \ + --hash=sha256:a48d62ab9d6f4f98c983223a547af44be6ca3691074c31cecced6facd3ba2dc1 \ + --hash=sha256:a4f00aa42f75d6e4595e8866e748cc1705adc0cddfeb2ca86d0d03993d63ba03 \ + --hash=sha256:a6e721d4b0e45d5b65e87534470e67b18dcd092c83f68fba09f152b9cbc061af \ + --hash=sha256:a730a083190634c65cca36ba5f489531576ebd79bcd5c8e172130f6453127231 \ + --hash=sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2 \ + --hash=sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3 \ + --hash=sha256:ab36d55f9ed2d067327667c2fea18dda018eb628dd6347aa01dda6cf1f5d3836 \ + --hash=sha256:ad2c86c495b899d862ea0f4b42891b8713a3bd45dd4105c7fd51c2a72f39f3a5 \ + --hash=sha256:aeae0e330c9f6acd681f647d46cefd30c29f93e3392882e792e82080c9691399 \ + --hash=sha256:b0431303acaea1089ad4b3e9ce4e6518193def1118d4073ca848635ee4ea2e96 \ + --hash=sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e \ + --hash=sha256:baed1e86cc735622097354b9d1281406caf42ff42a886d29faa8e8d1630333be \ + --hash=sha256:c1453022f490d2459a11819d83ad1d586e9ff65a12ac3e705ffebd46d3685dcf \ + --hash=sha256:c26608d2222fb1e94487e4a387d85f13eb55d5ed725cb25a0c589ac4ee60e7bc \ + --hash=sha256:c7659f22557c5a0bc4855cd635f55edec690cc008a40768527762cb9fb263455 \ + --hash=sha256:c8c69575568085ba0b1b10c0249d779a214aea6f6522e949a0fc9fb0fcb449d0 \ + --hash=sha256:c8d2c9fd1f2d16f780d15127abb050d13d1a76c03a4bd87d7e4980e45e511e12 \ + --hash=sha256:ca82be1a1d406ecfe1d25dc16cb33488e5a16bf4438c9fb590484ea29d92478b \ + --hash=sha256:cc572dace3f60ef98d7b12ff411d20f5362feb31a0439eab0085bbfd349982d7 \ + --hash=sha256:d18e5ac0f2f03f4f518d3e23db0f0cad7faa1da8620e9c09461d443bbf6e6692 \ + --hash=sha256:d28630f5854ab07ab1fd4aba756de52326c82e6be15d414b12793f1975048b54 \ + --hash=sha256:d9c275eaacd24aa73f94ffd6de08fc3f932424d8b6c376f4bed7cde376fe7bc3 \ + --hash=sha256:da0e573f9f97159390c89d9f1a9e41908b66d408cc5b58d08cf3847d844c531b \ + --hash=sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be \ + --hash=sha256:dddad92b554513a31f272570678ba307fb9f618f05e3d4a5eacafff9eae03e1d \ + --hash=sha256:df423d40ee8654634421812bc3b196da3f9bd7d32929da813f8394c4348a5358 \ + --hash=sha256:df913725b79db7bcf03448f36b7bf8815363417d5b58deecf9305e3e30f0f21a \ + --hash=sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7 \ + --hash=sha256:e2d65b31f36619cda3999b78b2aa9632e76b78448e7a56fc4240824200e7c4fc \ + --hash=sha256:e6e8cff14d6fb0be70a09c0bdc58096f501952d04624ebf867e0e56da2df8960 \ + --hash=sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125 \ + --hash=sha256:f24fb43132a4c6b4cb4eb029492919b2db645be6808d738f244fd146c03c32cb \ + --hash=sha256:f53e442b08449d42821fa4a4fba000095af9f62742a500f978a9f557ec44339a \ + --hash=sha256:f5cfbc5fe74540d335175b656c725d74d90e3730c626d92575eea35029d9afaa \ + --hash=sha256:f81b3b8f3d4e343550fa4baa0e479bba9f2d29ce9c2e9b51d1ce1718d7442fcf \ + --hash=sha256:f8ec5e643a9a937f64e1999eb9f75d072263751912dc5cd06d3c85f8f44be7c3 \ + --hash=sha256:fb92203a88b3d3053034db775110081c49d28be6551923805e039924093761e4 \ + --hash=sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264 + # via cryptography +charset-normalizer==3.5.2 \ + --hash=sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e \ + --hash=sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf \ + --hash=sha256:04851f73ae72b8413dddadb16a49dfee95263553741fd42d546f7d66907e6be5 \ + --hash=sha256:0521c5665880b33d603717defa76c094048900010897909952397feb3039da56 \ + --hash=sha256:0774bf9bf620249fee3e0b8b9fd3065de213be30f3aa94ce2494b3b638949e26 \ + --hash=sha256:0891b9d3903c5571c03771ca669a4b0ec5618ca722a5c957d3d29cd4e5062848 \ + --hash=sha256:0c951d5e6dd9c2ff60609476752bee49da4206adde960ebc247766937f72e718 \ + --hash=sha256:0fed1d06615f022ee3b13caf5e8b180cfea32bb2c5aded8a9d44277afc040f93 \ + --hash=sha256:114e4d0c92d618409ed82a99e22b5c5e768fe995f2973f78265f4524f49d4640 \ + --hash=sha256:11912e4bb14baae7c5d8791aa55ba0a3a03ec6729073307b0f57270abaa713d3 \ + --hash=sha256:11a4d68a6ecda3292cb1e50239e111543ba5d709bb62a6b4ea1afcfa729d8875 \ + --hash=sha256:124fbf1a8ff966d87ae05bb8bd45a71f966055ed8bba320d0c7cf450bc5f4d0e \ + --hash=sha256:1461ac396c4fdb983a675f20aa555624f0ee18ac83d832b9244ffff3d8055275 \ + --hash=sha256:1503bccbeb36d5527790c3930327704c39af22de3112f1b1666a9f3ce15ee204 \ + --hash=sha256:15bb4005af6320d259dc7593ca84a38d7fe06a421dbcf7b910ae23979101e787 \ + --hash=sha256:15c44f7edfd477b06f517a5cc317fc1707edb9de2c865f43d4b6513907473234 \ + --hash=sha256:16fa0eccf81304b79c5cd87f9271c3b85dd9dd99245e4422ae9c0dd45e0f99d3 \ + --hash=sha256:183b88127acdb4fabe59d951ab424faf1af7b63cdbb5f776186c1ea2ffcaed98 \ + --hash=sha256:195c26fb65950f8fce54e26349852b7bdd7c5f120aeefbcc440b8a20faaed4a3 \ + --hash=sha256:1afb975bd5d68d5ce9f6b6d44fdf2f7e34b895a35e95708a7a91b20a3b51d187 \ + --hash=sha256:1b4cbc7c3491ccb4aa17fcd8165649d01cf39f76de1696da8631b5f71b85401d \ + --hash=sha256:1bc0baf5ef96b6ede57d47f4b8fe4d9d84019c3bfcbeb20a41edc6a6ee341f1f \ + --hash=sha256:1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7 \ + --hash=sha256:1db38f4c5496827c1a501846d64d14c3b80c7e6714e406cd7dc36a9899fa1011 \ + --hash=sha256:211d5a3eb6af8f513b8d4ca19a8c1b7accab1b5f0d3175f9826b03c1a920dc1f \ + --hash=sha256:23851fb4e1b85ed3f6c2a27b777cdfe2e19fb5b38429a8faf38c7542b7665869 \ + --hash=sha256:254eb48b9fa5ee9898a3c445825a1f340fe53712a098904b39b0bddba8ea3cb1 \ + --hash=sha256:2625388c6c754520c37abaf3b41eb34d1cc4a373f457898f08606c8e362b891d \ + --hash=sha256:281cb91036248400f4cc957495cccd44c275c2e0c5854f7e45ac5cf7dc193847 \ + --hash=sha256:28a15fdad492a99b6eccfaaed66ef3f74050680545ea61ec8b2f4c538f1f1320 \ + --hash=sha256:28b4f0d66fb834ff90f28209ac7bce77868c45d8c93e26f906709d9b7c2e1af9 \ + --hash=sha256:2a925889534b3748302dae5dead07cc13480de1dac3aea80a941b729b471ef93 \ + --hash=sha256:2b7b3bbfb4fe8ef40600792d762fbaa9057559f9d3fad209525b7a22b99e91fd \ + --hash=sha256:2c9ad19a6cfcd5ea5c0d41161d22f9df1dcc277e9bef2751391334546a314c00 \ + --hash=sha256:2cc961b171b3f3440f410489ab3573e86aea8736134ebbb40ea1338b7f0831bc \ + --hash=sha256:2ce45c6627b22c47e390bc91a41c3d13032192e699fa0bea96e9671b373d69b0 \ + --hash=sha256:2e06a3a98f916dd41d27f3105e02e7a40181c98c94b9158733d03a6f80506c09 \ + --hash=sha256:304d5463e65a35d7bb0850550e0780395395f6fcf452f04db7d5ca7cecc425ac \ + --hash=sha256:304d8e4d493af723536393eee0c689eb7813f4a474c8b479dee63f1fdd98f621 \ + --hash=sha256:30fcd120b732aa79317f08dee04d7de0847822e4cf7ee0e9f445bb958832252c \ + --hash=sha256:31f3930700408d211f13378ccbe1c40845d8da54bd0681fac3a9b5aae81c7aa8 \ + --hash=sha256:34276fd796040bf0993ab33a369aa572e6979c7aab225a88893667ad8eac8f7a \ + --hash=sha256:355ad8011081dec5412240c087a9a0c9d4d5039f3ed11a3f13e18c2b29b56c51 \ + --hash=sha256:38a873987f3be698494da8b2e3085e29da02da7b633dce73e79c699a113d7bf0 \ + --hash=sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef \ + --hash=sha256:3d14b50de6bf4d0edf857a9386836846f982b8f524e188e2e68b96d702bcf4aa \ + --hash=sha256:3d21b8b13c7592db2ac5e544a6d83187b995257472b0c9e8351b6d507ae37ed6 \ + --hash=sha256:3d31298449090ab8d47b7b1b2a555ff73cac7ed438a08b7ac160980c7ebed649 \ + --hash=sha256:3ddacd27458c45bdacd6bd6db644bfb730efbf9e830310186e3045c9c5be8fb2 \ + --hash=sha256:3df041de8887954562c9b261cba85ca0e9ded74048daf125f45edcfaa4832229 \ + --hash=sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e \ + --hash=sha256:4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd \ + --hash=sha256:443eae2bf318abeaf6f15d785138f71fd6de770e99a92158b8b814265e079115 \ + --hash=sha256:447441e76ec720b15e64418d32e092297340387053047c7c694f579efb0ee1d9 \ + --hash=sha256:4495c5002a7b28557e7e222e77e0b661183e432b7d6d2e788101e3f240e05b8c \ + --hash=sha256:44bd4fbb29dfbeba60e7d2bd000c59e4b21ddb3cc53912b14048d37092706d7c \ + --hash=sha256:4685902cf26edf013ed7a3da0f426ebba7a00ebb9541386d835afbf002c11cab \ + --hash=sha256:498dc3188ca05a68231ac3fdbfc7f57eb67e1343c30e0fea17f8218c1599b253 \ + --hash=sha256:4c2b5031f63e331e3839b40aed2dd6f191e9c07edbde303e7876846ea1946995 \ + --hash=sha256:4d48f2d08b9de5864e2c8744d4461b862fb149a18274abc8b698c45975573438 \ + --hash=sha256:4f87960d57feabfb618e4e0af6e7371645fa26a277860739d6e5d6e0012c92f0 \ + --hash=sha256:50e3adfb96fc189eb27b1cf62d3b598b89b4bb0420d93a3d3e42e137409011be \ + --hash=sha256:51cf45226a9b588d0d2b4880c62d686934b63ab0bd79ca23ab0e9762eb27441b \ + --hash=sha256:52aa6992700996af31f375de0c6bacd402b0097fe40b53c426b9f51a90ebabc7 \ + --hash=sha256:55ea99acb17b9325618de155a0cd6a2e8f5d10be008113e1d433bbb58db543b2 \ + --hash=sha256:56bc200a365efb37383b7852e4cc5898d3b2da5987289b543956cf8cad71018a \ + --hash=sha256:588461c2e8384d309bd63e5826019b6977bc66d629b99ac8737bb795d7b2cb5a \ + --hash=sha256:58ca3755ee7ff7f59b57789ec9833c9de9ea275405cdd240eda1f193112e398a \ + --hash=sha256:58f361dcbab699cf8f42db3f47c8e7fd1036f138c23a5d08de9fde5f425a730c \ + --hash=sha256:598a11a2c7ebaa5334bf698bf29568c9c390abac6a154d8170fedecd1cea38c5 \ + --hash=sha256:59f63901b0031c3136cf64704dcb21de0bbae62ce2c9529bc39d27665463de37 \ + --hash=sha256:5cde776b7cc66e4f6c99612cea4aa7269aa65863f7a15841b2c264f103822f4e \ + --hash=sha256:5e2b6b57e9733d39f0c9fd3185efa6b8e29652c4cd8fe94180272cf6ed9a78c4 \ + --hash=sha256:5fb29fb8cd1a46c27a1bf9613ad5ec2599310d46b4025d9556404a6b6a292800 \ + --hash=sha256:6045373d5a89a5ec71afde535db987ca28e76dfa276c2d4c818265b375d4b055 \ + --hash=sha256:619799369eeef6366ed3e8755a5670f4f2f0fb6b30a0fd7264dc0fdc2357058e \ + --hash=sha256:62588a277bfb59def052abd940703fa35107152bf479781a878617d60faf8fb5 \ + --hash=sha256:62603db9a7caa0802eaa28c1c46fecd7b3a263a774069c24c3c28c302448721c \ + --hash=sha256:65cd72beeeca9d3aaea1201e5923859f308f952f9c71de93f06063c79f0f7a3b \ + --hash=sha256:68eb192d85ab8e5f6ec69c2bc6ac0179fbf04a5ac1569d12fbef74883fe102d0 \ + --hash=sha256:6bd128f206a7752ae1f2ab6c61bf8a24ba28913a10df8b14c2637b973ff97a80 \ + --hash=sha256:6be488a102b8cf28d0391d8c4ba7748938ae28b78ad901f8585520fca33ead1a \ + --hash=sha256:7218e8f32b0956cfcd048fd42d9d5779809745ca1d86113ca56f66e7ae1549c4 \ + --hash=sha256:7441d755b7ab94f8d4eb3e43ec05482d760842fd263d003a99102d742cd835e2 \ + --hash=sha256:749e97e1b32313717a565abbe321bc2190bc8b35f1a67e4cdbc7c56c8d8ffe58 \ + --hash=sha256:75a3ceed0724d625d64b86ca20aba182e4df462e04c2414fc941c0f523f06aac \ + --hash=sha256:780fbe7cab297b81dad9fb8dc5eb003c0468ffb0d9e5f65068c53a34661a96bc \ + --hash=sha256:78456a747de8dc58360ffa581f30a002baf5aa28cb262536545e91f113ed7639 \ + --hash=sha256:7967d08cf06dee78443b874f98c98036f624f3a4e73e11f9f64f5be4d25393cf \ + --hash=sha256:7a881931aa470808df94a8c380eed2bbbc76cd9dc622310f99665658c821eb6d \ + --hash=sha256:7dcd882da75ef9adf94903b1e3b9419e8aa8fb4c7396822b834b9ef7fb96954f \ + --hash=sha256:7e841fb9010836c992c9f12fcbd43a831de93a5f726fc1ccd8ca1d0268c5014c \ + --hash=sha256:7fdde2c9fd9e3eca40631e024664cf2584272cc8f96308cbe5fdfc930f51d8bc \ + --hash=sha256:8024d00c3faf3fc0c16e07a69f4405e8eac7cc0ab15f65fe6cf43827c4cf72b4 \ + --hash=sha256:80d02b6f04e92601a081dd97b23d3128033098bff5d35d392ddcc0476ea11253 \ + --hash=sha256:838dcc90063569a0448120554591a1d6c4a4ffe11babf048908793154ab86ade \ + --hash=sha256:849df64e889b2e17230d58410a03dba311a65b163508fd33679b2b737d4b7858 \ + --hash=sha256:87475fabc8d9996fd9c27debb395e642e8c838d78a00b6e932227a0e06b81e26 \ + --hash=sha256:87e50a3e7cb90af586b6c5faf23e302a970415ac73bd7bd90a515a04b427ef96 \ + --hash=sha256:89b53f3cda69831909888e0494f4fa0bcd3537e3e138dabeb620bd6ad946bae8 \ + --hash=sha256:8a893cc101149f80a653f82062ebc95b34525a2614382e1da5458fe7c6997249 \ + --hash=sha256:8b2bfab86aa71ae13aa41a6a26aab338e0db2b8bc75434b05aea89e011ff35a4 \ + --hash=sha256:8d86d6fc60743dc916eb79e2eb1ec4818e21e427731543af40a3021851174a13 \ + --hash=sha256:915563965d418f986e7e145accc592eae9e1a1be3566ff98a05d7a9ec42a76e1 \ + --hash=sha256:92888bb3187c5ba50500b00b3b310c9f2c651709d28036077680cb5255450a03 \ + --hash=sha256:93223adc95033dd47133a46ccfc316a0139176fd79085762e27202ec56018f03 \ + --hash=sha256:9373ad13ef0d2c0fb761e04e55bfdee5a08b52cef2c882c8fbe9935b1517152e \ + --hash=sha256:9409a8bf35cf78353942504b24a57de3d75b708997a1e4bd8db71ac8633ce364 \ + --hash=sha256:9b7f416ff0978e2f2249330527f0ad6fa02f4932e6199692d3b52da2048c19e4 \ + --hash=sha256:9bde855991b7e362c146535e3136a50bfaffc0487d38b33ca7e5edefc6e23849 \ + --hash=sha256:9cae88599c7219005d879f98e5ed53341e9a122af585e1091200358a3003d2a0 \ + --hash=sha256:9cf9b1a857e25c4baceeb3624e92a56df3668f398c4acba74e174d81fb4d1d3a \ + --hash=sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036 \ + --hash=sha256:a090bb2c68df85450502e3e20d665e3a5af9c65a84d6508ed477badd49166fd3 \ + --hash=sha256:a192e2c40070d92c3ccf777e3a5c4ff515573cd2bb7ed0c537fdadbbec5bbf21 \ + --hash=sha256:a19a731138fc27d5682277d3b9df22855cea1239bce7fcec5f78f42ef2d1f3c3 \ + --hash=sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e \ + --hash=sha256:a815775b6c38d4e0ff7bcffbeba67feded90202bb6a226b8dd35f1c855217413 \ + --hash=sha256:a89012d6d5476ee112d20d998570ed58df2260a852afb1758809cd6900411d21 \ + --hash=sha256:ae4f5fea5b8b8ccff88238cc8569303e5ee95efae67fa62922a311397a71f346 \ + --hash=sha256:b6856554c4f44d79fc2307d5768854310a8f0096e501c75637542c82292b0429 \ + --hash=sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685 \ + --hash=sha256:b736353c0a625bbd5fcec108576e2385db3496f4f771f785ff32e108d3c3bc45 \ + --hash=sha256:b7fd005a73d9e657273b7a10dc71a9e03c8fb9ee6999798d6918ce095b81ac7f \ + --hash=sha256:b91363207bd9dc966a691e959bb47f64b30f7ac4b072be9968b366982f7db77c \ + --hash=sha256:ba0b1d2620edf869789c3879223f52bf2afc5d31b3cb47cc57b3a12c05e2aa9d \ + --hash=sha256:bbbfc8e28816f19d7c0f1816664980c0a9875d01b27cdf8eedddb639d9e108ad \ + --hash=sha256:bd16aabe4a02a297c23417aa17ac6299dbd8c49f673bcd645b4929b11f5a4400 \ + --hash=sha256:c0afc6800ba57ccc350374c5bd6150419915d95ce93cdbab2d783d75eaf30ecb \ + --hash=sha256:c6708715abcf3c73b99508253e961a9967f02fe536532834149574eda6de0d1c \ + --hash=sha256:c7c9ab723cde841fefb34efbad91e87f00a674b1fe1cd0784fde742bf2c154dc \ + --hash=sha256:c8f3d67aeaf55f017982b73683f0e7342ba2f6635a78f69ce89ebb26aa411e5c \ + --hash=sha256:c9790464842f85f437dbbb54417eda1e0e6bfc52dd8d22d6fd1c994b73b2dc74 \ + --hash=sha256:ca403d7e4798f525fdfc78e258820419cbbd0f0ecbab9de7840e3c017cf6b8cf \ + --hash=sha256:d008d90a7f2471519aef0c90dfbe73b3e6e4d5e66ac48e19154c17e89e98b604 \ + --hash=sha256:d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f \ + --hash=sha256:d1befeed746d247c81127bb14de9dc3d30edb6e5976d34f83f86ed262b1d9105 \ + --hash=sha256:d2374b62878abb00cd8309b32af6c0b715cd02dec0ca74ef12e5069bdc64144a \ + --hash=sha256:d376bbd28b3a8999db1a103b3b388aee6f1ddeb3e51bc2172993efdcd86e064d \ + --hash=sha256:d4a7319f304a774bed22115bc891618e45f85065ab44ea6acd07d274e750519a \ + --hash=sha256:d6734d2ef8a50fbf8445c139477da401f50d62a0606bf00e20ec6d87773fefb1 \ + --hash=sha256:d760fe2a4d7c3b226cb9026d6a842868d52a7901bd98420e1baf14e80da85cf5 \ + --hash=sha256:d913de495d90407cd859d263bee2e5d1a4ed3eb6573c04e70d9ec619a7cbed7f \ + --hash=sha256:db19d07e2e0129e974a0e65d0064fc222a446cd5122c2fd4184d2af9fc734a9e \ + --hash=sha256:dca9ab98072a5a54ebacebdc45f53e645336b320c667410b061be1ca588ae709 \ + --hash=sha256:ddc7dacc8ece3a182e7f15cb862d1fd616b46d076cb1ae9dd232b2c38b655874 \ + --hash=sha256:ddf19c062bea7a0cc80f519243d2c01dd091be0cf952a0750d4ad576709559f5 \ + --hash=sha256:def79fa35ef0cef8d2accec024f4fdc7ead3012ff02f5215c783f39f03ef8cfc \ + --hash=sha256:df29a0a7107f7011e77f4eebdddec4c7331e24d787a0b21a46d63bdf7445da95 \ + --hash=sha256:e09a3942ecbdee5cce73ea9d42da82b81b72ac1bf031ce069b93b5adf4eac8cd \ + --hash=sha256:e242bb1c5e76e97dfa9e7f209a71e93a01d7f19ffdd5cfbb2e2d55b4f08f8ab0 \ + --hash=sha256:e243bd13217235fc7290c621941c3f5cc8b66e4872495be821d7436ba2fb838d \ + --hash=sha256:e2af3aad578aa6bd1384bcf4750fc285e5a9de53f40b7d41e5a0bf748edeb2b3 \ + --hash=sha256:e4e81e09c1578b8df602e3db08b0b3ea0a6947ad612f52bf8dc5ea8d47691f0c \ + --hash=sha256:e54da4baf05720032d527874d40b65fa4d7e5c6c6a43d0c3adbeffcaf275a2b3 \ + --hash=sha256:e80e6c2f55656b4824d72065abb4ddd6a525c74bd78a0aab5d9fc2cf4fb5af50 \ + --hash=sha256:ed2a239c0ea213acc1908150a3037257083c7c083128f1a4cec2ec4b97dca491 \ + --hash=sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5 \ + --hash=sha256:ee21e28f0430bd6dc9086c6e525d5e818a44a5ad19720c8a0ef766792f3eb5e5 \ + --hash=sha256:ee43c17b173d46a3212baa6ead3ae258eeabdae48c263a01ccf0218c366dd655 \ + --hash=sha256:ef4fcbf3327382cd4c9f540babd61248208af7b93eec4de397b4d5f58a09e288 \ + --hash=sha256:eff0ac9dbe711a4aee69bf04a83896aa9b85f19641264053a9f6d48573abb7dd \ + --hash=sha256:f0aa869112ef88429ae17820d99c3dd9504c9e9c671d3c246f3d7442cb051084 \ + --hash=sha256:f3c96f633825733f735c5a9cf21d21a257d8e1edf0b1cee0a064b9c424ca0f7d \ + --hash=sha256:f5833ad231be5eb6553de524a70f48d71b2c8563101750531e0b80184e175cd4 \ + --hash=sha256:f5ec61164adcec446f8969a3358ec3f9b26bbda3b9213e5586d219afa8df2915 \ + --hash=sha256:f7d486c83842422badd511868fd8a9a20e9407ace71564b6af47ce7e60a336c1 \ + --hash=sha256:fb9e68df06293761f9fe66ade60a9bc6d0f5e42b8acf2939a9158af86ab0e5bd \ + --hash=sha256:fc14a032f813bf5fe624d991960ea83e9715adc27e4c1830a2361eb1d02ac341 \ + --hash=sha256:fcff63213e8e6e47770541a4607175404f47cbb3ebea7b6058cc82d524a0e424 \ + --hash=sha256:fd1fbe0f116b6e55da77aca2c6ddcddcfac2186cbf78bdebf40fc156efca389d \ + --hash=sha256:fe9753dfee015c570d73df76f899f18444d41388bffcde097deba51c4fadbb9f + # via requests +click==8.4.2 \ + --hash=sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6 \ + --hash=sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76 + # via + # click-option-group + # semgrep + # uvicorn +click-option-group==0.5.9 \ + --hash=sha256:ad2599248bd373e2e19bec5407967c3eec1d0d4fc4a5e77b08a0481e75991080 \ + --hash=sha256:f94ed2bc4cf69052e0f29592bd1e771a1789bd7bfc482dd0bc482134aff95823 + # via semgrep +colorama==0.4.6 \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via semgrep +cryptography==50.0.2 \ + --hash=sha256:0ddc924c04591c2811ca024d62ecad4f7f6f08af8939c211438f48a16bd23602 \ + --hash=sha256:0ec5f09541743261e66e291b4a0cbf0fb2997aeaab6d9e9c740b9dba1b58d1c2 \ + --hash=sha256:0ecbc5652bdb6fc9eaf89a7d196e20941adfe812f43bc4ca05d9150496821047 \ + --hash=sha256:1981f1db4630889b9ef7803fadef12b056f428cb6b85c27ba57b774793b6093c \ + --hash=sha256:1ba34f04897fcdaa73f74145c25f3ec146fbd56593853e88adc2e811303c5f42 \ + --hash=sha256:241449bf940a5d27309bd317e6f9a2af6932113818bb2b8f5c59ddc7ef16da18 \ + --hash=sha256:25784ce8b9621c90c643efb9e1e2162ab3b0224cae446ad5e70e7fcb1ce18b51 \ + --hash=sha256:3dc4fd8058cea1644971207d530e1a03a184a805ffc8ebdddf0599d78a331b81 \ + --hash=sha256:4061c0079120205fb760c58acab6443e217307dcf05e3702cf970e0689972856 \ + --hash=sha256:4a20ce1e5cb4284a86692fdcba7cb8754185c6b2e5c56fcef3751cf451d3cdc2 \ + --hash=sha256:4e81d95e5bafc2d6e34e4bed780e53e4d5b9a2f928573428aa4d35fbec1eb0de \ + --hash=sha256:58a0c478eeca76fe5e07993c5a0703def34a6dc6a0cda4f5564639b33112ffe7 \ + --hash=sha256:58ddb5a8e3179d12f19e4ea34d2d32e9d63a4baa142c875c1eb59f41b7243acd \ + --hash=sha256:630ebfea3bf689d075f82316324ff7433dc447fe6bc1bfc76524b74b4a9567d2 \ + --hash=sha256:6f8700550aa1474a91e5dc07049c46f98b423b5b1ddd0483e0b51362eeeaf5be \ + --hash=sha256:78198641e5be9521beea5aa782bb551a58068d10e6eb04c9c680c1b69f2e7d45 \ + --hash=sha256:79def8d059362e7831389ed3be0ecdf58a89386e1271e35dd9f5af84e81bffd0 \ + --hash=sha256:7a8701d6b584d76e909e3d305b7d126b41439876a5aaf76cddc67fc230eafa2e \ + --hash=sha256:7afa5a6602a9f29af1f3a2965f831bae7c9d5d597b7cbb716d41ab3b7d89879c \ + --hash=sha256:7b46165bb56eb4704e2eaaf86f3c940d19154535d9b0ca7d6d590b04060e00d5 \ + --hash=sha256:7b75de3c8b3be1cdb1052747c929440c3eea46c1bc2cb8a6e3a48388e9b7b452 \ + --hash=sha256:7c6d0330c472d96f6a6afe24d80dfdf15176c33096f0a4397ae4c60f3dd3be48 \ + --hash=sha256:828d49b0ff5a0e3975865571c5d91dbbdd0d38d8289b249a163e9425413a5e05 \ + --hash=sha256:84f964e537f916e2cc85199e5a88742e964939b575ac8598b3f9d6cc416cdaf1 \ + --hash=sha256:85d0d9a31b9098e98534226d5686b47264b95e62ce459dc2e62fdfc809f9fe93 \ + --hash=sha256:87e9ce85beb6b328ba370cc6e6aea483c92617b4c95b1d33a49297eb662bfb04 \ + --hash=sha256:8c71ba2cd31fc93748c38e1b613200ff1c2665cbfd5341fe3a61cfde35a1430e \ + --hash=sha256:92e665960f25fcdc73725b9cec7a3824f279ba97a98653afe9ffac2e43668f67 \ + --hash=sha256:94e5e9f108ee10471288214d3d233fbfbb492840a8457eb85178d643ddeb32c7 \ + --hash=sha256:9c8402a82ea0dc4ceeab793db05f0fafa8ca139ca34fcde5df0f596103c74107 \ + --hash=sha256:9dab55f57c74c3cad24c323bacbbd04be4705ba6eb0d92e920b1fc4837ed5079 \ + --hash=sha256:a582ab2ae1d34f67112cadc86702774c9ea4374df6bca6afe672817203c99134 \ + --hash=sha256:a6557e5f38e065ca9fbdaf7cfc7435ecb1d113aa81a022d1b51921ee7432e227 \ + --hash=sha256:a9f7355e6fab51f6c369b86fb7571cffa05edee2c2121e0380a37fb9ac1cd5c1 \ + --hash=sha256:ab50ee449bf968271e820086f10a33d101dd060370abc10bcd22279be2656539 \ + --hash=sha256:ac9ed99d81760c62fe89d5f0815cdfa1ba9a35141cf30f1c2d044f04b4803d2e \ + --hash=sha256:b13478603dcd0a2479ff8e87e2c19a7d525734686fe3c49542472293a204212d \ + --hash=sha256:c423ab384a46c4dff7217b2ea5ba2e11cffdeab6441acd04cf65a369caf0366c \ + --hash=sha256:c5e67125c7dca78d199ec4e116aa93dbb83494808ecbb8211a2cb09b1bf41dbd \ + --hash=sha256:c71be1cbfa5cd9a41ee452acf1eccd82b2c05950358b106ec8ceb83411d1a020 \ + --hash=sha256:cbc8738fd8526d80f35cb3a40d41f41a2e7030bb3b18b09a6778ef63d291c2fd \ + --hash=sha256:ce47f66801c20ec6c6632453bb5960fe38939e9306970b48b3a5a26de7745d94 \ + --hash=sha256:d370b8d1dfcdf7130178137f6fbee6140774a1acc6cacefc4b42643ec11d0a3a \ + --hash=sha256:d38cdff612d06fa6a32840d5e1b1f7a27cee4a349aa9085d94a67789d6bfd408 \ + --hash=sha256:d8947001be83df1394050758ce0e745dd74fb134eef0a4b5124208dfc3a68c37 \ + --hash=sha256:deb9fde5c60e437ee4821bc9bc39ff31b42135c27e1dc61ef0a629389c1de62e \ + --hash=sha256:dfe9763530994147d9af1def057a5b9658b00e8f8fe8743d144d1e0911c2e454 \ + --hash=sha256:e105ab60406787da31fccc883fc0f733af1efd78f0136a4599692c4083a73d0c \ + --hash=sha256:e275096ea1e60cc595cda2836fd4a6c725d1125108b868be17f53684d164e2cc \ + --hash=sha256:edc3342adf8f697fc5f59c887a304356f147b397809440ed64e2fa6af2f50f37 \ + --hash=sha256:ee247f5c245c9a2fe7c8e2214e295918838e44e00a45a6718451e4004219e767 \ + --hash=sha256:eef4c2f3423810b3070ab391f85436d2f8bbfcb286ac15cbc73190b3563b1f1a \ + --hash=sha256:f21e8a22c8605750c7af886bab299a363721264061b4ac0a30efb73cfd58efc5 \ + --hash=sha256:f265528741e048bce55c3463ed721fb0aa45a5888d8add8cfeccb3035451bbdc \ + --hash=sha256:f2f9bd7f90c64fe89253f0a2c05e3c4856072660429ce8831b4235bf29403a67 \ + --hash=sha256:f785f6161f202ab04d8ca194158968798e480ca058943907972da5f12e2881e8 \ + --hash=sha256:f9f6143a8c75945eb960d9eb98905a441394abfa24afaae239d514ffb2586480 \ + --hash=sha256:fa8f5efb344d6908a1ce62f4a24e2e5780f825d6f53f5f50ec5ffacac72936cb \ + --hash=sha256:fdd28f912fccfec1846a94e2e1e8f9b0012f557f0c46fe4f3eb0d7a87afcf90b + # via pyjwt +exceptiongroup==1.2.2 \ + --hash=sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b \ + --hash=sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc + # via semgrep +face==26.0.1 \ + --hash=sha256:8183d94bc248baaea855a9f8445f97a22a9988908e60abddccc6e251da77c4c6 \ + --hash=sha256:ab0a83c37c9789dce658a67a9a80eafaa113c9ec37c5a9d950ff5480542a062d + # via glom +glom==25.12.0 \ + --hash=sha256:1ae7da88be3693df40ad27bdf57a765a55c075c86c971bcddd67927403eb0069 \ + --hash=sha256:b9f21e77f71a6576a43864e85066b8cc3f0f778d0d50961563f8981377a6dcb1 + # via semgrep +googleapis-common-protos==1.76.0 \ + --hash=sha256:59e13344a9f3651aa201a03e2bee815a3bf43a4baf1f9ff8a9b62a840ce25fac \ + --hash=sha256:71db0e44a1d4c2dd024ebad44ca67129cc1e2892e4861df466764749d5ef8642 + # via opentelemetry-exporter-otlp-proto-http +h11==0.16.0 \ + --hash=sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1 \ + --hash=sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86 + # via + # httpcore + # uvicorn +httpcore==1.0.9 \ + --hash=sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55 \ + --hash=sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8 + # via httpx +httpx==0.28.1 \ + --hash=sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc \ + --hash=sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad + # via mcp +httpx-sse==0.4.3 \ + --hash=sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc \ + --hash=sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d + # via mcp +idna==3.20 \ + --hash=sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44 \ + --hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c + # via + # anyio + # httpx + # requests +importlib-metadata==8.7.1 \ + --hash=sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb \ + --hash=sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151 + # via opentelemetry-api +jsonschema==4.25.1 \ + --hash=sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63 \ + --hash=sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85 + # via + # mcp + # semgrep +jsonschema-specifications==2025.9.1 \ + --hash=sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe \ + --hash=sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d + # via jsonschema +markdown-it-py==4.2.0 \ + --hash=sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49 \ + --hash=sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a + # via rich +mcp==1.29.0 \ + --hash=sha256:52d01f334de1868cc3bb2d6604931126a67631f99a6c5d3b82ba47290315ec36 \ + --hash=sha256:f5a075bb611f23d6f4d080c6a1699fa62772eebc562ba9e66b306ddde1c755f7 + # via semgrep +mdurl==0.1.2 \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba + # via markdown-it-py +opentelemetry-api==1.37.0 \ + --hash=sha256:540735b120355bd5112738ea53621f8d5edb35ebcd6fe21ada3ab1c61d1cd9a7 \ + --hash=sha256:accf2024d3e89faec14302213bc39550ec0f4095d1cf5ca688e1bfb1c8612f47 + # via + # opentelemetry-exporter-otlp-proto-http + # opentelemetry-instrumentation + # opentelemetry-instrumentation-requests + # opentelemetry-instrumentation-threading + # opentelemetry-sdk + # opentelemetry-semantic-conventions + # semgrep +opentelemetry-exporter-otlp-proto-common==1.37.0 \ + --hash=sha256:53038428449c559b0c564b8d718df3314da387109c4d36bd1b94c9a641b0292e \ + --hash=sha256:c87a1bdd9f41fdc408d9cc9367bb53f8d2602829659f2b90be9f9d79d0bfe62c + # via opentelemetry-exporter-otlp-proto-http +opentelemetry-exporter-otlp-proto-http==1.37.0 \ + --hash=sha256:54c42b39945a6cc9d9a2a33decb876eabb9547e0dcb49df090122773447f1aef \ + --hash=sha256:e52e8600f1720d6de298419a802108a8f5afa63c96809ff83becb03f874e44ac + # via semgrep +opentelemetry-instrumentation==0.58b0 \ + --hash=sha256:50f97ac03100676c9f7fc28197f8240c7290ca1baa12da8bfbb9a1de4f34cc45 \ + --hash=sha256:df640f3ac715a3e05af145c18f527f4422c6ab6c467e40bd24d2ad75a00cb705 + # via + # opentelemetry-instrumentation-requests + # opentelemetry-instrumentation-threading +opentelemetry-instrumentation-requests==0.58b0 \ + --hash=sha256:672a0be0bb5b52bea0c11820b35e27edcf4cd22d34abe4afc59a92a80519f8a8 \ + --hash=sha256:ae9495e6ff64e27bdb839fce91dbb4be56e325139828e8005f875baf41951a2e + # via semgrep +opentelemetry-instrumentation-threading==0.58b0 \ + --hash=sha256:eacc072881006aceb5b9b6831bcdce718c67ef6f31ac0b32bd6a23a94d979b4a \ + --hash=sha256:f68c61f77841f9ff6270176f4d496c10addbceacd782af434d705f83e4504862 + # via semgrep +opentelemetry-proto==1.37.0 \ + --hash=sha256:30f5c494faf66f77faeaefa35ed4443c5edb3b0aa46dad073ed7210e1a789538 \ + --hash=sha256:8ed8c066ae8828bbf0c39229979bdf583a126981142378a9cbe9d6fd5701c6e2 + # via + # opentelemetry-exporter-otlp-proto-common + # opentelemetry-exporter-otlp-proto-http +opentelemetry-sdk==1.37.0 \ + --hash=sha256:8f3c3c22063e52475c5dbced7209495c2c16723d016d39287dfc215d1771257c \ + --hash=sha256:cc8e089c10953ded765b5ab5669b198bbe0af1b3f89f1007d19acd32dc46dda5 + # via + # opentelemetry-exporter-otlp-proto-http + # semgrep +opentelemetry-semantic-conventions==0.58b0 \ + --hash=sha256:5564905ab1458b96684db1340232729fce3b5375a06e140e8904c78e4f815b28 \ + --hash=sha256:6bd46f51264279c433755767bb44ad00f1c9e2367e1b42af563372c5a6fa0c25 + # via + # opentelemetry-instrumentation + # opentelemetry-instrumentation-requests + # opentelemetry-sdk +opentelemetry-util-http==0.58b0 \ + --hash=sha256:6c6b86762ed43025fbd593dc5f700ba0aa3e09711aedc36fd48a13b23d8cb1e7 \ + --hash=sha256:de0154896c3472c6599311c83e0ecee856c4da1b17808d39fdc5cce5312e4d89 + # via opentelemetry-instrumentation-requests +packaging==26.3 \ + --hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \ + --hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c + # via + # opentelemetry-instrumentation + # semgrep +peewee==3.19.0 \ + --hash=sha256:de220b94766e6008c466e00ce4ba5299b9a832117d9eb36d45d0062f3cfd7417 \ + --hash=sha256:f88292a6f0d7b906cb26bca9c8599b8f4d8920ebd36124400d0cbaaaf915511f + # via semgrep +protobuf==6.33.6 \ + --hash=sha256:0cd27b587afca21b7cfa59a74dcbd48a50f0a6400cfb59391340ad729d91d326 \ + --hash=sha256:77179e006c476e69bf8e8ce866640091ec42e1beb80b213c3900006ecfba6901 \ + --hash=sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3 \ + --hash=sha256:9720e6961b251bde64edfdab7d500725a2af5280f3f4c87e57c0208376aa8c3a \ + --hash=sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135 \ + --hash=sha256:bd56799fb262994b2c2faa1799693c95cc2e22c62f56fb43af311cae45d26f0e \ + --hash=sha256:c96c37eec15086b79762ed265d59ab204dabc53056e3443e702d2681f4b39ce3 \ + --hash=sha256:e2afbae9b8e1825e3529f88d514754e094278bb95eadc0e199751cdd9a2e82a2 \ + --hash=sha256:e9db7e292e0ab79dd108d7f1a94fe31601ce1ee3f7b79e0692043423020b0593 \ + --hash=sha256:f443a394af5ed23672bc6c486be138628fbe5c651ccbc536873d7da23d1868cf + # via + # googleapis-common-protos + # opentelemetry-proto +pycparser==3.12 \ + --hash=sha256:a076f3f489b39b43ed13563a1dafe42447445bec2e294154ec5c57fcdda4c85e \ + --hash=sha256:f03387877eab82ce01bbdfd0ba7252ee55a90b1c708d5129e2ce915475cf1db6 + # via cffi +pydantic==2.14.2 \ + --hash=sha256:7efbf7507b937931cd32a5755acb00ea1cf5ccb1d4e8067a5850d5069e382118 \ + --hash=sha256:fb7b2db6cefe8414dd612edeede49c4c433acb0432b0f92b95024e45f66c505d + # via + # mcp + # pydantic-settings +pydantic-core==2.50.2 \ + --hash=sha256:01eb0282d0b3a065d55956d1be9ce398c46db3dd6d277a6cb2358c8aa8c53179 \ + --hash=sha256:04cf672960b8c4fc28bb159c8cdd101fbd311c520237a5c0360448b851adfb41 \ + --hash=sha256:0b94a515f44f1ebcb25395bcdba506c4cdaf6d3fcb0466b9658521b41e5ff057 \ + --hash=sha256:0d090ae76d5b09c003600c7779b3adcf3d1b49268f616c5c51d844e54c8e318d \ + --hash=sha256:126f158474346f457c0759c29c1a6334acd5f7f99dd272bb27d19314f3d81b4d \ + --hash=sha256:150f6e101f575c21a4ecfed1be1c05bb89a0ad49cb9c846ed377583bd71b32c2 \ + --hash=sha256:16ec8e07c37f02dcf68939cc7f202ba9a148cc155ee2acf22d337e10b24c2cb7 \ + --hash=sha256:18f008ef58cd30782f81b6e0119e20b7e884edcefbc2d370162ebe033f6e5c99 \ + --hash=sha256:196b87b48b2695426920e8470d20f9e99f019ebd86f15808aa018b68086840cd \ + --hash=sha256:1a5e859f5a8a6d834b0a13acaa0eaddf1a9b4b015fcda13bab7b471e18299d32 \ + --hash=sha256:1ac5b99bc7b0a68ec64f5f75a6828a7bab5535c8df0cdc07901deb50e0815910 \ + --hash=sha256:1b0e8dc3932cf4e9ed5727570325cacc716b9409ffc794a221c0ccc72e8eb775 \ + --hash=sha256:1b9f652e17a13bbc09b45f74c3c326cca72059ce4dcdef687fcb04389db413a9 \ + --hash=sha256:1db9cab6197e797824f0479dd2ae5fd2e272aa61c61b7faa5a6e450ca7a0d3b7 \ + --hash=sha256:1fdf5b52ed22f1404c2433d0b46df2d86d9befb742d0b9b4042a2325c43cdb97 \ + --hash=sha256:2115d7ca6d58554af8a14da3dd32d361a4fe999fae52f115a6155679b5b00e72 \ + --hash=sha256:21a902e546032c82b7275552345a2342d862e0541aea7226c91067c396e68b3f \ + --hash=sha256:21ea3b00f1e87c66f3f9e92f9f6fec20495ac0e60d7d2e68ba1fc49739d7cf40 \ + --hash=sha256:23385c4626f8b5a7792aa381ea573d9432cfbf4c21375a0a5eed2a4fb64e0e58 \ + --hash=sha256:240fec32a74af0979f7253532859b3fd209ad5eea822416bb010929dba445c3d \ + --hash=sha256:24120c644322a35b5eb765416ac8442214c45689e255f5fc6e761e7e7c743c8b \ + --hash=sha256:26b778d4ebb75f181d36220ff0f54a513fc46f053d9b09ce79993c2f00bc45cc \ + --hash=sha256:2d4a043c820363359e40ac96270e1915e5376e116be1f59cee0701775de3e376 \ + --hash=sha256:31a1fb3ffbd1195b24490f671d12623dd4c9bfa56d6af0a299fa43b516134f5b \ + --hash=sha256:33c6800ab9563adaa0d7893e9cd8f5b972ef1e6a23df70498e05c24f3fcec5e1 \ + --hash=sha256:3435c443da7510a6de1a30c68beae338852a11f0440cc8320ea756a162f38dbe \ + --hash=sha256:36917e29c0b815d6b940bc91560fcf453b5b85d55c579796373f0ea11d1c111a \ + --hash=sha256:36d8b9725684ca3bf658b90a101d335fc8cae405bb22196b7b5ef41344913756 \ + --hash=sha256:3939538e640c94ab779a05f2d45dafedd01d65d93e1290797f3ac5b59fcb6455 \ + --hash=sha256:3b1bb3950e0794a795c9344d818d5b476189b0c9c9755e8eb8fde87c3acee17a \ + --hash=sha256:3bfe12243b3ded517c6734d91f127489e2f51bf95cb533b53130fe360333db80 \ + --hash=sha256:3fbcd402e4b607d4b8de5d4591215f31f042af03f9d09e58f693a6221e32833f \ + --hash=sha256:41ed8abeffda6a880207fdc0cd1343a448cec3cc6b38b53f730c0745f745292d \ + --hash=sha256:43a8fd56f3c681f3cda2d5c842ad28e88241df742dfcbe8fd1dd437a3056e1f6 \ + --hash=sha256:48e944091b7bff233920bed8a60b0ed6c96c73d3c5836bf51c4b9a4bfb58e4ca \ + --hash=sha256:4ac996e42a93d80122a23edce44e02c6b9c4913f5c6198a077da31475341a39a \ + --hash=sha256:4e9392ddf67fe97ab9889f796d468c9908a8754b8b6c7520eb03a65012b9a1e7 \ + --hash=sha256:4ea01f30e119f1ec7a2034e85c40f491d469896aef02cd6436fd9292fe1be3fb \ + --hash=sha256:4eb54c25e3463d73e1e4ed439ffc45d1d7e590df40bc7bb06f11a906afd996c3 \ + --hash=sha256:4ee64baeab403b9de9c92846c5c1abec28ffb046cbc023bfae059897841f88af \ + --hash=sha256:523fe6574aea50f456cbc301c1cdddcbf237939f7657f9af99b4f0f71942b59c \ + --hash=sha256:5299296ff5cafcb69851fd652de8f9268a0bb036bcbedbfcaa94cf743baf3986 \ + --hash=sha256:53bd25e8ab54c02bb4c55d4848c1d36f75f3b9a7356e83179fe27794d9e9e6c4 \ + --hash=sha256:57bccd3e1128736c792094da1feac6da46ec3feb1957ef649a9b3e4f8de6fa04 \ + --hash=sha256:596921489390a002d6a5e303384a0f1f98384f8bb550fbf38a1aafa6093da0f9 \ + --hash=sha256:5ab5738c39b25b5dc5a721270e2269a2f5e86e614375e6c07ee6caab8cbc0f2f \ + --hash=sha256:5c12a5a080570a91bbcbf6d10db008b80e3f5dea015ef2f0137bbec70f24f3f3 \ + --hash=sha256:5d3cd8be71c4da3c9b42cc92f17e5e3036bdca98bf18555a0e072c3fe87abbb4 \ + --hash=sha256:61e13100b30d8d25fc0d1f0297014b32941bf0975a3584bd08f3adebb68d1ead \ + --hash=sha256:6258754c473b3045a7aa30b833a8a331a1ab36c6147cb230789861d80bb26f83 \ + --hash=sha256:6a438cb8a3f87f2c49e82e43fb19511d4d5043f53e0787dc4df937ccb904373a \ + --hash=sha256:6c25b8826be85714b27dafe908d3461e1b09e3e31c0279a7029040c832c781ef \ + --hash=sha256:6d47b2d0e00e030e0ebdb08115a37da7294e7a6d196d134a77ed7ee6c142284b \ + --hash=sha256:6e731bf5a5e8e25398544d7709e39068ec4230b0177e4db7fa955692fd415ba3 \ + --hash=sha256:6eb6ff07964f39e33c6f57fefe939514e76b8c0d4a694e5663e2e04e80cc1798 \ + --hash=sha256:6f5a432c6c1ef18a1a02a04b3616b8d3f2f88b13faa46caae1ac6559ab202234 \ + --hash=sha256:6ffb4dce3ecb2cd563aa30f9eb5088a1cf1f4f688b90cbb374fa96e49fc50b02 \ + --hash=sha256:701bc55d08c22f981973ca4f6fdf4ea102ee1ee3a21b818b66fdb161ea711a4a \ + --hash=sha256:713d7c33c0e231e3786eb0ec95885814dd65d5f3a09754399b6acbf5e9365f11 \ + --hash=sha256:71615edeaf1ae70f5f3f558426072eede0168b7e5190fd9633878e29a0b85732 \ + --hash=sha256:783abdfac21247d33bec40aa683d26bba30d61655c40de38b2decc4797aabf92 \ + --hash=sha256:7c539d452cba22f250103c7d1c00cbe9038eb705e657476e701c43374efd9f2e \ + --hash=sha256:7c6e1bd6cadae13958e52897ef020e85c9916a95917149fca463bb0c0421a7c6 \ + --hash=sha256:7f9821dfc0c473c96ad55ce4189c7cb4f9c94e7d4f563afb874173243dec1162 \ + --hash=sha256:823b222c4fc861a82c650998a6117ecbd150cc71bf8b78f9a31bf3f48c456108 \ + --hash=sha256:83d6f42ae6eba44548a1a3d4f900a5b1500fdd14f09f04754a8800ab0d544432 \ + --hash=sha256:8431ecb131489cbdaf6f51f7ade47475f73aff4f1912552f75ba19a6cfe233a8 \ + --hash=sha256:848984e231190ae49bc8b5229e64d2a6fba4231dc6046e1b6b28ddc060bc7601 \ + --hash=sha256:86e7abd24a67f61a4bfe8df059b67a2bdd8bf33705178e98463195d140bd3780 \ + --hash=sha256:8772c2c0091e6fc2d0499151793d31bf811826986b0727052935a95104845544 \ + --hash=sha256:8835566b3e94026da3ce2249f9ee35c9d2ebe4cd131f6a39bfc82708d3010a46 \ + --hash=sha256:89213368eef163350af37127939ace099010e8102757905c3e329f1175950ed8 \ + --hash=sha256:91238117cd296352f54f24117ff5a227bdea428865dba1244aa0cdd1424c0bc2 \ + --hash=sha256:91315aea7adb51821d4a3378ede953bfdd76e3bf71551de4a82d7638cef7dc02 \ + --hash=sha256:91c92856b846aa690ea6239ffd6c5003c5e3e296a69095570bf4efee5bfa0bdc \ + --hash=sha256:928a44ad1e21a7e923eb924d601605f0694cd187d2ce5d40bf7ad76650f4627d \ + --hash=sha256:92acf02c770b9d5c4e9a3e8d64e9d95ae26456a86ebb7b7cf64a97f899e5871b \ + --hash=sha256:92ada606285dab054e40848a951f583c537cde1e54701ea1305ec0096877012d \ + --hash=sha256:93bedc68c4138088ea3c042189c01d2945f530f0dcc36e1ea02df8418bd4f1cd \ + --hash=sha256:93eb41d626d9a2749a678823c70bba8c25033cef474ae8001fd7621adbbd8437 \ + --hash=sha256:95838be125133fa314753f8cc5168f7c41e3a9dd5eef5383dbbbeed511bd4853 \ + --hash=sha256:9667637665acba166a7dbbc786f14c50512d3a01f7199e0e1a13b929e92d7c7a \ + --hash=sha256:98722314e12a8e4fa346e0afd3fff2098b5732875ff45592b450a7b589b43c4f \ + --hash=sha256:99e1d482138a71902415ba375bb4627679a5fefd3bd07803c3a8f37632f4981d \ + --hash=sha256:9a87744e683d9a13f60b7fa5242c17f8d283ffa94ad727cb19063b48c3d34960 \ + --hash=sha256:9a8a62281fd9c6a373b3fd3d473685e6838d43341eecde5f47729748e2c11ee3 \ + --hash=sha256:9b01a092955c1c7530196ad526755cff4f2d11f37ca9a6fc9ebe37ca49a48977 \ + --hash=sha256:9b2383933b1dd7a8c93e02f99ebfd305f1286057172483b8e6898bed3fef69d3 \ + --hash=sha256:9e7460abce637f90e37f8c443559fbd687c38884d05cb69ef265e634945f4324 \ + --hash=sha256:9eff570402175c7d5fff8497d5a9c05580664a79bb66c07b8f205d17f69e580b \ + --hash=sha256:9fcde11462e0faab4c2a2ae8cd4516f7dd8239eec583bd88c5524d8064ad2d0c \ + --hash=sha256:a1b4d60bad57d6e0e7cd30cc4d1dc646d258dd6dfb7935ce76c7dd72dd1e98b0 \ + --hash=sha256:a3317630e2791f56071b82f89bb71624146125e4311e6643f708c6ba744b5ac5 \ + --hash=sha256:a53d5f11cd6d15569ba3e53f3498077f0d5e633f6ec604d2ea613e895017ebee \ + --hash=sha256:a55c1163e829a08707b4a92c8ee02a5a3a3847ced74aa4da94e3e975ffe1ec63 \ + --hash=sha256:a59db03b80a156a6fbeae41096866d1cb89cdf31031ba44c768a804538880636 \ + --hash=sha256:a786cf782ebb2e45a43c7118d75d452aac982b79577dfe804d8dbf2878f0b589 \ + --hash=sha256:a88851e8e332588cb8cced8b5318d1163c7d0bb87830aa8dcafbc4ae9602b73c \ + --hash=sha256:adec010c824290d4ca87047e8d8bfa4f85ac29f545f326cd5321696805d311ed \ + --hash=sha256:aff31602e8518594e6f6bc670cdb27e37cb7dbeb2d5d0b76a7707b70fe951ddf \ + --hash=sha256:b0b25d647036972c2951059046cb498f72b7af5a2def27bf8e5f44c3067ab7dd \ + --hash=sha256:b0e6a2152706d84f7da8b9d34dcecc7e9bde678af32c40bd5b405f427ae0fbdb \ + --hash=sha256:b1adf2f37521b578c438f6ec61d1c1d0c20b076863ddd5d8b6f3ab658857db3f \ + --hash=sha256:b29b7c5adf4b2be7c941f7f76432aa3269cd5052ff8610376b8ece24d7b02c51 \ + --hash=sha256:b2dd65864aad38dbcc57c3d0e2c978d4286e063378137d8fc0c9fcd558943285 \ + --hash=sha256:b381574614245f18fdb2d6d1aa8f149e225869c47b5ee7f81812de8977817314 \ + --hash=sha256:b3e681208e2d39fde13fbea449ef2736a85ec1ea2afa41e9193a8c536e71dafe \ + --hash=sha256:b5675a12a7b67063fe3ca187e735b0463cf13fabc10166ae4d4b2f775fd0632d \ + --hash=sha256:b583ddeee6a6bb5bbc04462167c68034913221139d52d9f155ca6d1637a2fdcf \ + --hash=sha256:b62c89545d21d930c333208fd548e7b4f262228ba3a322fd75c987a75ab11f31 \ + --hash=sha256:b7abcfaf66c1dc14c5ed928c349614f223c972a8b021b4be9548dbea6c817371 \ + --hash=sha256:b958c217c6e56bef261f516e4caf5d490b079ad6a428752afada5a764cca6c71 \ + --hash=sha256:bb6d49f00e2babd40af4889d6b9f4bf50879f522dd4e2e22cb705cac5e0c5e8e \ + --hash=sha256:bd1fe69056a19c377a6c6de2c1240fb8676ba0512a969965efb486510c5e0f1f \ + --hash=sha256:bd6ecae08c0d871cf93b6f0d4ee76b06c65be44ea22311981a022b2f1948cf9d \ + --hash=sha256:bf7f99a0e6616cea754e2334d129091f3260d011369d9b8c658522bfb2427619 \ + --hash=sha256:c1b65a42afc73b39e6ae908ec7b9c3b9898676a7b15ce4c66d4965f7071007c8 \ + --hash=sha256:c324a7e0c0012e3974053f81a270d8f1aa23227571f4ddd3254c911bb356459b \ + --hash=sha256:cb8d2d7b07cbe2d7488de7e53671f836c4f4a8032dcda079df33dc1b7e2397c0 \ + --hash=sha256:cc488daac19e6f5292180fac5e0ef7efffabeef4e096af9a17a75a7d3d6781f6 \ + --hash=sha256:d18d56c1ec63b304f4bb3c7db7e0d311e61cca1b1c944590a4b13ac39b2ca92b \ + --hash=sha256:d3d049b557875f9d15230eec8a731749a7a873d8ed6a051903b05bdf46e0e65f \ + --hash=sha256:d684ff87d00de2f6abcbbfa9b0fdce8b513dd799a900809dcfa7eb62ad69832a \ + --hash=sha256:d71a9a9352acbcb5c73d39dd003383599428067b6eda5cf7c5d335a7a0da37e1 \ + --hash=sha256:d79aaa468193c1bed6b0560d3c5c9f9e369e3efb0b128b38a2537e2d51d42773 \ + --hash=sha256:d93c066a38f83376b5bc020e563666784d1b680a70d6ceb625fdb541af7a312e \ + --hash=sha256:e2e6240a0a5ad847017b3d65187877fdb7a11d5a58d43c30736f9f523478913b \ + --hash=sha256:e3d824b6152e1c0fd58dc6266f2de470eb7b2286135294f5f7cd26a0f0693738 \ + --hash=sha256:e5c801bdf3cc92274b8fc2c7023c8751e5ae81260c009ac558ff55ce712a2d45 \ + --hash=sha256:e80c47314c7233e7105a7efcfffd89d56e479e558189d1959eeeaf2639a27680 \ + --hash=sha256:ea71b94a2eb5d2fc102926321f56d2ee8eddfad2673eadb1d23e9f287a492715 \ + --hash=sha256:eec187d2876abb6a74203efbe2aa796455c1809334acf4e739dde35da8cfb69f \ + --hash=sha256:efad0bdc67d3b119c3bab6b94d341a27333c2bb89ed75dfa182a4a06cd0ea329 \ + --hash=sha256:f078e276848bc23d1f92f46fc88d5b9cbb824b9acc60d9e07116620e502e16a9 \ + --hash=sha256:f07c965a8aa6d62145f122641f292129984f39a3e3697585b19298a1488287db \ + --hash=sha256:f142cd663d1148ed32993ed9a58e5c67ea312f446a01a6c13a956945aafc9f23 \ + --hash=sha256:f47c1349c3b4274aeb18459d54244881a5c0dee0fdccedffca45704ba5c9e0a0 \ + --hash=sha256:f5ba7ef10ce82737e173fa95cafa1c8210918f7e653715b2c7a7a31877a74848 \ + --hash=sha256:f73930dacad5e611fe019e18df6f53c30629b1843d038d303b8dec86a32493bd \ + --hash=sha256:f81df206b937d0dca5efb38c25fc99037d82dbcd3740e34c3f81997d2322ac1c \ + --hash=sha256:fd9aa71a800c87c0f7ab53fa38009169a23a82c685989626ca74a4bd483e1b67 + # via pydantic +pydantic-settings==2.16.2 \ + --hash=sha256:3dc08ffabed2bbd5dc2dd55ead7b78b4e4c5cd776aecd04310db5f1224caaf46 \ + --hash=sha256:8d523e5c129b097686bde019bd6109bff53f4c8c3f63f1ddf9933ffa42e5ab4f + # via mcp +pygments==2.21.0 \ + --hash=sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9 \ + --hash=sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c + # via rich +pyjwt==2.15.1 \ + --hash=sha256:42d59d631f7768a1028a64c7ff581a9bf7519804daf91fc5b6c56e30eec5e193 \ + --hash=sha256:4f259e80cdfb6b3fc18a7de51fd1ef9ec79652f25019bae68975ca2468a34df8 + # via + # mcp + # semgrep +python-dotenv==1.2.4 \ + --hash=sha256:42269a8a5b3fd54ffa6f3d84b18abed50064717576b4ecf03dc4a55d8aa04fdc \ + --hash=sha256:f0d53e69935a851c0dcc78f3ab7aaccd8cabef0b92382b576b824212902873c0 + # via pydantic-settings +python-multipart==0.0.33 \ + --hash=sha256:8f16c07b36add9da6b2ee87d3efcaf0a45a6de9c3d0a5dd94e9ccf7675a7bc45 \ + --hash=sha256:b8112424a6abd162ec08d390565dd113ad699f2fe6fef3c987b8bbcbfe9e390d + # via mcp +pyyaml==6.0.3 \ + --hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \ + --hash=sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a \ + --hash=sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3 \ + --hash=sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956 \ + --hash=sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6 \ + --hash=sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c \ + --hash=sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65 \ + --hash=sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a \ + --hash=sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0 \ + --hash=sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b \ + --hash=sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1 \ + --hash=sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6 \ + --hash=sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7 \ + --hash=sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e \ + --hash=sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007 \ + --hash=sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310 \ + --hash=sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4 \ + --hash=sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9 \ + --hash=sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295 \ + --hash=sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea \ + --hash=sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0 \ + --hash=sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e \ + --hash=sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac \ + --hash=sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9 \ + --hash=sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7 \ + --hash=sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35 \ + --hash=sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb \ + --hash=sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b \ + --hash=sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69 \ + --hash=sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5 \ + --hash=sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b \ + --hash=sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c \ + --hash=sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369 \ + --hash=sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd \ + --hash=sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824 \ + --hash=sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198 \ + --hash=sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065 \ + --hash=sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c \ + --hash=sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c \ + --hash=sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764 \ + --hash=sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196 \ + --hash=sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b \ + --hash=sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00 \ + --hash=sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac \ + --hash=sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8 \ + --hash=sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e \ + --hash=sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28 \ + --hash=sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3 \ + --hash=sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5 \ + --hash=sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4 \ + --hash=sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b \ + --hash=sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf \ + --hash=sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5 \ + --hash=sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702 \ + --hash=sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8 \ + --hash=sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788 \ + --hash=sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da \ + --hash=sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d \ + --hash=sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc \ + --hash=sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c \ + --hash=sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba \ + --hash=sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f \ + --hash=sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917 \ + --hash=sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5 \ + --hash=sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26 \ + --hash=sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f \ + --hash=sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b \ + --hash=sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be \ + --hash=sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c \ + --hash=sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3 \ + --hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \ + --hash=sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926 \ + --hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0 + # via -r .tooling/publish/frontend/.github/security-requirements.in +referencing==0.37.0 \ + --hash=sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231 \ + --hash=sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8 + # via + # jsonschema + # jsonschema-specifications +requests==2.34.2 \ + --hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \ + --hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed + # via + # opentelemetry-exporter-otlp-proto-http + # semgrep +rich==15.0.0 \ + --hash=sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb \ + --hash=sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36 + # via semgrep +rpds-py==2026.9.1 \ + --hash=sha256:00ba2d8c7dd4ee537978ddf4b3fbd712bef2d8751603f7f3146b3f4287768e25 \ + --hash=sha256:01445c8d194aa032a08e944f16567672da1c62dbdbefd8b6d0693032e290cf68 \ + --hash=sha256:028ad274ea951dac64491b5d1e65712a4aeabfdbdb9fccf797b57bd899b0c495 \ + --hash=sha256:0483515261947e4e8b8e1375bf7463e7eb6ccfb3d86e7b554d90cd5285f20f32 \ + --hash=sha256:068c37bba854ec2fe42f7365c640af11dd9895890ccbf2df5070d0c059bd7f96 \ + --hash=sha256:074a4d198bc34d9a8ea425114fc3ded6d11ec01f6a314a8db67454a5152d8834 \ + --hash=sha256:07deecbfce94c78473018bc7d10b337cc651d12df87a1eb2cb3e4024bc9c33d0 \ + --hash=sha256:08dae4a4095150a7c4545a1fb40b98e1ab1744fbc2770d92c977b9dadaa49ab6 \ + --hash=sha256:0da298fb372dc192610a4b9ecbc68a0cd8b675bbbd1fc519d01b41cfd658333e \ + --hash=sha256:0f045bb053c9057720d72c56dffe30dffdc05997b2897a827b9325f0ab6623fa \ + --hash=sha256:10e208f2425d973938afcd56e28a7c4be32e27b6a60b5d381f49fb9d8acf9759 \ + --hash=sha256:136a1c3fe4402b7008bc81cb62ee538481795b61a7e83df88dff3b3f02b726ff \ + --hash=sha256:159a7aab5c5e8b112c8830f54717ce56da1252ebdbb526f5be2df2309280b9e7 \ + --hash=sha256:172e47169583f46ce118cbec68e6795d0da0f4606b488b6434f8276bca0a058c \ + --hash=sha256:1c2d1f6da5128eabf34e963d7163a818846075a52568250d006c4c953b40f903 \ + --hash=sha256:1d55198263bb51f557550c6ed2e6d1cb6a6fed6eb5c9120b741c5926bef8a45d \ + --hash=sha256:1d77b649e6f7cdf12ca5c2a98dad0ad37f9ea9b6f960408a92f0cb12bb3d04d9 \ + --hash=sha256:1e8d4d79d828299bf44a55db22a9388ab967b49d17132c88eab0f4360b48da8e \ + --hash=sha256:22ffd29a63d71fb1b81552c21f2c2b734949b7ac751a9be70675a939a900839b \ + --hash=sha256:2693b2728bbcc48d09a981a356954b0c47c53ff25b545856f28a889ea619f69a \ + --hash=sha256:270bdcdaac5d5b6f73c5e22e7e135c7f2a50e789f71d9e241d5be8d90026e19a \ + --hash=sha256:2711d29b653b3bce48a63d18b9c6b53274669e6d6c4094dddeb4d9a0e45128b2 \ + --hash=sha256:2c16ab111bc27c646ba8aa005d0527754edc538ebb636f0b1bf8e244b48d1945 \ + --hash=sha256:306ee1850d8105b5baf977e78d45fcadd12c1a54678d614c9baf217708446e91 \ + --hash=sha256:3231c4c0e521dafa5be0c9f114ee2c2ad46650836f2d72caa86801950c3e7044 \ + --hash=sha256:3890a6aa36e6baa53d5258a2a25d3ef8b37ad165a6ab27a892d7c3e3a432cd69 \ + --hash=sha256:3a72c11530d71abfb66c8d7696a2f86c43e63fca8b948f1a784ac490f4ec688e \ + --hash=sha256:3b5a6f40f0a1486b4b36c888123afc67acdbd9f33235927acf5ff295429a0ba3 \ + --hash=sha256:3c91c210ae7645626c608400e3519b4a642f837cce09ca830db3beb2e9f274d4 \ + --hash=sha256:3cd182d7291d29b92c521a0069d9c01ba6193628a9a105531d11b40a6d731a33 \ + --hash=sha256:3e524c7874ac72884d28e16dd5b8d839fd09e0fe76b020d3fbca23212a7b8c52 \ + --hash=sha256:3e93b2cd69a9830be33e03945cd7cda940a0a8bfcfbff41d6144f0cb0d3d8bd9 \ + --hash=sha256:3edae8c5ddfdb6985d49ae9d150516e5076888879022f91a26c2de9276ce0bdb \ + --hash=sha256:3f0e9ac28fc067d4d34b88ae43c48e9489455c97fee9633d851f7eeed5a05d35 \ + --hash=sha256:42e75466f83cd43f6026c81eab74246efb2bdadafb307b85700632d06c68f299 \ + --hash=sha256:44b32a7c4f0da3d28af31c259e38ddcff096f855e205ed0671d02fcf44f1ea1c \ + --hash=sha256:457866b85daf5034296666168b84a69e0b2e89dc4f1af102b46f6448a60b9063 \ + --hash=sha256:45bc6bccf78b20fd834237d18db64965d7ee68ba7f60440a26c7ab71e7b8d51a \ + --hash=sha256:46d80bc76b51a6c24f9944368c28d38b8bcbcea1da4f2f8d3ebc31a67e8c6ec6 \ + --hash=sha256:4793ef7f78268b124b73fa933440f01d258bbae01de9fa53e9080c9ab0425a12 \ + --hash=sha256:492e5e428cbe126221611f47e068f01660352feec4ad18bc0f5ea9b2ae88fb14 \ + --hash=sha256:4b26b03d9d2658ee2fa234f8f4f19f38a09773fe5261028025032e26d4d35af0 \ + --hash=sha256:4c0d2cb595a420b34d5086db0add011e26e2c09d6a024afbac4228bf8f863a30 \ + --hash=sha256:4cfaf02209061880210819934de2f4f6aa83dc04dafe6770276acc240a56da31 \ + --hash=sha256:501909f2e4a1e2dee528ef766fe3c469060ebc17e54a8383d404ba07a81a6f02 \ + --hash=sha256:50906f5aea24b5a865cbd0a589698288631d9f3a54c3a937c83aefa95a0d14af \ + --hash=sha256:54ac2158a6f96cfbabff0b2eedaf94b90c5ec7ca8317fcadc61e1c2b2e0ff6ef \ + --hash=sha256:56c6952a9b15047466d0c2347c446a761d4527f89976156341e68f0ce5cc08b0 \ + --hash=sha256:56cd8b3f77d7b6812f533b662186a1f28316931166ddc00fb893b1b0db7e9888 \ + --hash=sha256:57492a550a1d88d29d003247e5f78dd8cf04a701fac0e4c8db8745a6d2504e0a \ + --hash=sha256:5943980471829f6de242a20b109de3111ba6b77e3af0ffc587028ac854b05e6c \ + --hash=sha256:5c6ee90dee3e85e055ddfd502d611643d9b0fd94c818220bda84ec3dacd9b27b \ + --hash=sha256:5c90e7fa02e8f5de0d10c17595c568ada48c5302e749462c0ea1a4c362111a86 \ + --hash=sha256:5ce8943f79c2210f7abcc28e86367b03b28d95027fd01c46d2472373ae70c86f \ + --hash=sha256:617f59cde379b4f648a09797b7f683d04b90a46344cddab85639da5aff0f5531 \ + --hash=sha256:6307a0da524939decb8ca4a3933b8ab62525794411d6984fca6726e732804af6 \ + --hash=sha256:684fd492fff4fead00587544e059be2bbcb6f93454f21fa2a91b66fc7508be82 \ + --hash=sha256:6b5b393eda5ea42cca1c1a6665f2a4882b4fd5d1777e41ce0545a107fb008c9d \ + --hash=sha256:6b723eb406dec5bc9ec516c73ab9c3239a3284e017f7eb89ee2b3258bd504fb7 \ + --hash=sha256:6b9bf3135b4ad5981df9a73d71a35272d650a2985ae9c2746357b24d59de2448 \ + --hash=sha256:6beb738155fe8ab8091afdfa5a3226b21c2b1593f1e50ebb90eb25b44dbc0391 \ + --hash=sha256:6c0dbbcc19735fe5f8b0a54c07659d154a9e69f47e15d0a6ab7299215daf62cb \ + --hash=sha256:6cdc537c8633d7fd92a82e2e0d2ab74320a3f63d5e59fb9cf08711e08fe151c4 \ + --hash=sha256:6eae33003518fd4cb4f83a218d5371469dd3001aa3b87128c005b07762f7fe5e \ + --hash=sha256:740d0a99cf9de0b17a3943388e9294a59becf75e7c43421f387bd3c7a9901f7c \ + --hash=sha256:75c38c50ab9aca840225d9a9a3810bf11d04bd5c1f186cabbb8aee56db3e9b15 \ + --hash=sha256:761fdae6728ceb99ab182fad2f0cc1e262f610834dc891aea1d1a2a2e634776f \ + --hash=sha256:7664419f27db41d4f1c43a78dccda7dd6e8ef2428df3ee01d0c2a07a6b071297 \ + --hash=sha256:76d3af9732d2dab69f28179b40ba2d87e2f1d5824b4a694780aa787d685e8f36 \ + --hash=sha256:78326f4cb4427a56ba4996c0762b63be45f06b85f086526420d2b3a66e40f84d \ + --hash=sha256:7868b85224291c6cb6759f9b5adb9745f486d226f62b16a614dd5a2a5ab2b35b \ + --hash=sha256:815d26356930846a40c7bc1366e7b1b0320ab8a063e66c11298a208bed0fd237 \ + --hash=sha256:8171b44a054e5c67fd748ada04187f1250bf35b95f85e52ab64bcf3331a923bb \ + --hash=sha256:821b2755db9194409254012f429c56643416fb96ef9be090be82ec8826b7f477 \ + --hash=sha256:837c6b305e26fe0f75b15c92cf3b2ba29e0ae19dc40b1c557b026cb426347d0c \ + --hash=sha256:839dde845559254f34885267c6878f60d61d5205180226d976fe488d45fa128e \ + --hash=sha256:84a6ecc0c940169190d2c23bd969debd48c94dbc855acd60188a68d71d421608 \ + --hash=sha256:8601470267d938bcb7f3ab1a336100af51a4fd5b6ed030ef52461bb3ef5e7e07 \ + --hash=sha256:88b5268892fde430d5531f95bc560b6efbbd67c929662c586afd729a96e7461c \ + --hash=sha256:8aa5dda18d39b6143eb24809d158f9252c88f402749b6f1b62a506cc7d96cc35 \ + --hash=sha256:926bdd3e3b5998ddf70cc64bc8cf57209571f9044542913afb673799fec77dd0 \ + --hash=sha256:96beca19ec79de272e8668585380ff9092c47077c1d7a1e098e00bbd921f4785 \ + --hash=sha256:9a0460d43603d1fd9ef59c30278531e15d78581721ddb538fa560aa7817ea4ad \ + --hash=sha256:a03d57b86d2a51d0a66c92177e2be154ad015f357791d306e714569999cdb4cc \ + --hash=sha256:a36b70596407634ca82d4b989a3729074a008537a0522e4c8046a67c729103e9 \ + --hash=sha256:a3a52a3ba86436ab3aef510fbe21512abc2ddd1993005dfe50514bd2284ef025 \ + --hash=sha256:a3dbc5ed9514908d5046107d7b1346bde71eea61de6e0e4919c19354f97e769f \ + --hash=sha256:a431156bb41865fc14cd5d79bb9d7bbed83110b0159e34e62ae30951f96c0009 \ + --hash=sha256:a575404ebc9cf2e91edd32eaf570ec1430eb900d4f56724ba7dd4bc1fc9c176d \ + --hash=sha256:a5cf77eb04f20b720be95265a3e00eb2a14814074255cc27069c551b2db53118 \ + --hash=sha256:a8763f20692da7df39b0afdd1ba3042b004c50a45994f76c2d9a25641f7673db \ + --hash=sha256:ab4b2fda7c2b542f7f9d886cc6a838c5079d2b76f72e6081411faba11adde2c9 \ + --hash=sha256:addeda51556dac7c1a2f14cda62db8b621cd12afba3091d03a96c72932387eab \ + --hash=sha256:b242c27c8f836305a4a72df9cdd564386ac57b807bd252a063223331c9316b37 \ + --hash=sha256:b4f062343e7ad3fa94f2c66e5ae667dee47ee74dd41a9057c4fbe163236a123d \ + --hash=sha256:b5b8b0753718d258fd454283fbd57e14545d3b40583fa672e27cb4f987626bcc \ + --hash=sha256:be3e47e2d91aa3942ff9bf4077a505226005abfc39b6f7554a91c1b9393986b9 \ + --hash=sha256:befc2d6a953e563f8a7bfd87a42c22ebf8a3e980dcb7b6a4d17b70b0e914e8a3 \ + --hash=sha256:bf35d0568abda97233239ce32896d3ad53fccc537832c104e30c94aa5fb93569 \ + --hash=sha256:c933c6678c6f116ff8af47a4c6db0868b8ace74af0343016c0ef00f00272ea69 \ + --hash=sha256:c9d1aca01f49170fdcf5c92761b1fafe97f554b721ca4570c5949fff778f0d4b \ + --hash=sha256:cdeaa99ce822dca76cfb1b993e9120c5ea212f2eb66d48950ad63c349668a018 \ + --hash=sha256:ce4d4f52e2a4324396caddbd45a97d8d7be5f42edd25d2355282a9c34f9b2f7f \ + --hash=sha256:d1028417bb44037eb3069c1009bd7b7277212876cda22fbe565b0bca9fab6d2c \ + --hash=sha256:d151e148117294133bf8af7eeace085e7e87432db15ab6adf640330298a47f6f \ + --hash=sha256:d7841166b7fa64c9c56404617ae4341448847482d45933b13135d26c130519e5 \ + --hash=sha256:d7fca4eb6df565e2a928f1c7dad92d27db8f9df0f449e76423ed5d7e713ed445 \ + --hash=sha256:d95a354e02393eada6d7351184671aced9d4cce109dabf927cb7aa99624352a1 \ + --hash=sha256:d9edf30457d74eebfd76b045535e36f1cd89062566a128a0db2145ca042d787e \ + --hash=sha256:dbc2673f9223d420c91145599b3ba45a8a50c207d1976908e5fb5ddb0c9b9429 \ + --hash=sha256:e01b3c878c8641913e688edd1b3f08658c6783d29cf6b826bd3c0d1ae7a1ffaa \ + --hash=sha256:e21c1429e205828ea886a2293a4a2c8e01f4c25d9893ca330e97a6cf73f52e7b \ + --hash=sha256:e43d4a1f673e8a1cbd8533e809e02b4bf9d4f2280269bb640436556312121250 \ + --hash=sha256:e6d198bad4e49dd6732fbd636e2fc5c082f45c8cad0b4acb756b00c82c76072e \ + --hash=sha256:e6ea1cda8d8c688278430e4268a42f5e5da3bdd74578dfadc0820c3f1766ce83 \ + --hash=sha256:ea394a937f17a54c51239348bdbe2e3518124c8d4a8951ba04a311d3095bd18f \ + --hash=sha256:eac2f5dbafd585dfe31f86a23ebf0d3ba480a9d49ebc87947267b5608d4ea0cd \ + --hash=sha256:eb61be926bb81567c1f48bdc8aa22b9855048dc2efd53871f9f7e6e9a5632346 \ + --hash=sha256:eba5d173f7d5708b22a93815017a4611873ed54db9f268077c0dd1ed99cfc858 \ + --hash=sha256:ec450527cbf485e13c8d3602a54f428ab0432fdade0ede75efd74b735421c871 \ + --hash=sha256:eef6a03b0b6d08d0835ccfa8ec8d1bc70525e3801387567137b50c557695e6da \ + --hash=sha256:ef0d8c843e2827d6c120ab4687e9423fb1d893db1df27b7c1506615bcb9734a0 \ + --hash=sha256:ef6b65b03247c54692ad4fd9ee97cb772781927db72e3cb05e70b3db6d1ff14f \ + --hash=sha256:f3d6ed6a98cfd19155996605474982cc470d7601746a6439078f1a5a3fa8b050 \ + --hash=sha256:fce4b85234a0cbad67bf8e6e1201ee815d172c9aebad75f25645bc4d834f8e31 \ + --hash=sha256:fda1d96e542c37b6c804547dbf489c129fe7c97183a76a5ec275909ba1a063df \ + --hash=sha256:fdcd198979b4ecffcc1beba366a7fbcf4eb41243691a82fe52ceb0b902f09c12 \ + --hash=sha256:fe5ad0664ec772b02c45859041aa17655709cced7a31005817fbbbd988c25567 + # via + # jsonschema + # referencing +ruamel-yaml==0.19.1 \ + --hash=sha256:27592957fedf6e0b62f281e96effd28043345e0e66001f97683aa9a40c667c93 \ + --hash=sha256:53eb66cd27849eff968ebf8f0bf61f46cdac2da1d1f3576dd4ccee9b25c31993 + # via semgrep +ruamel-yaml-clib==0.2.15 \ + --hash=sha256:014181cdec565c8745b7cbc4de3bf2cc8ced05183d986e6d1200168e5bb59490 \ + --hash=sha256:04d21dc9c57d9608225da28285900762befbb0165ae48482c15d8d4989d4af14 \ + --hash=sha256:05c70f7f86be6f7bee53794d80050a28ae7e13e4a0087c1839dcdefd68eb36b6 \ + --hash=sha256:0ba6604bbc3dfcef844631932d06a1a4dcac3fee904efccf582261948431628a \ + --hash=sha256:11e5499db1ccbc7f4b41f0565e4f799d863ea720e01d3e99fa0b7b5fcd7802c9 \ + --hash=sha256:1b45498cc81a4724a2d42273d6cfc243c0547ad7c6b87b4f774cb7bcc131c98d \ + --hash=sha256:1bb7b728fd9f405aa00b4a0b17ba3f3b810d0ccc5f77f7373162e9b5f0ff75d5 \ + --hash=sha256:1f66f600833af58bea694d5892453f2270695b92200280ee8c625ec5a477eed3 \ + --hash=sha256:27dc656e84396e6d687f97c6e65fb284d100483628f02d95464fd731743a4afe \ + --hash=sha256:2812ff359ec1f30129b62372e5f22a52936fac13d5d21e70373dbca5d64bb97c \ + --hash=sha256:2b216904750889133d9222b7b873c199d48ecbb12912aca78970f84a5aa1a4bc \ + --hash=sha256:331fb180858dd8534f0e61aa243b944f25e73a4dae9962bd44c46d1761126bbf \ + --hash=sha256:3cb75a3c14f1d6c3c2a94631e362802f70e83e20d1f2b2ef3026c05b415c4900 \ + --hash=sha256:3eb199178b08956e5be6288ee0b05b2fb0b5c1f309725ad25d9c6ea7e27f962a \ + --hash=sha256:424ead8cef3939d690c4b5c85ef5b52155a231ff8b252961b6516ed7cf05f6aa \ + --hash=sha256:45702dfbea1420ba3450bb3dd9a80b33f0badd57539c6aac09f42584303e0db6 \ + --hash=sha256:468858e5cbde0198337e6a2a78eda8c3fb148bdf4c6498eaf4bc9ba3f8e780bd \ + --hash=sha256:46895c17ead5e22bea5e576f1db7e41cb273e8d062c04a6a49013d9f60996c25 \ + --hash=sha256:46e4cc8c43ef6a94885f72512094e482114a8a706d3c555a34ed4b0d20200600 \ + --hash=sha256:480894aee0b29752560a9de46c0e5f84a82602f2bc5c6cde8db9a345319acfdf \ + --hash=sha256:4b293a37dc97e2b1e8a1aec62792d1e52027087c8eea4fc7b5abd2bdafdd6642 \ + --hash=sha256:4be366220090d7c3424ac2b71c90d1044ea34fca8c0b88f250064fd06087e614 \ + --hash=sha256:4d1032919280ebc04a80e4fb1e93f7a738129857eaec9448310e638c8bccefcf \ + --hash=sha256:4d3b58ab2454b4747442ac76fab66739c72b1e2bb9bd173d7694b9f9dbc9c000 \ + --hash=sha256:4dcec721fddbb62e60c2801ba08c87010bd6b700054a09998c4d09c08147b8fb \ + --hash=sha256:512571ad41bba04eac7268fe33f7f4742210ca26a81fe0c75357fa682636c690 \ + --hash=sha256:542d77b72786a35563f97069b9379ce762944e67055bea293480f7734b2c7e5e \ + --hash=sha256:56ea19c157ed8c74b6be51b5fa1c3aff6e289a041575f0556f66e5fb848bb137 \ + --hash=sha256:5d3c9210219cbc0f22706f19b154c9a798ff65a6beeafbf77fc9c057ec806f7d \ + --hash=sha256:5fea0932358e18293407feb921d4f4457db837b67ec1837f87074667449f9401 \ + --hash=sha256:617d35dc765715fa86f8c3ccdae1e4229055832c452d4ec20856136acc75053f \ + --hash=sha256:64da03cbe93c1e91af133f5bec37fd24d0d4ba2418eaf970d7166b0a26a148a2 \ + --hash=sha256:65f48245279f9bb301d1276f9679b82e4c080a1ae25e679f682ac62446fac471 \ + --hash=sha256:6f1d38cbe622039d111b69e9ca945e7e3efebb30ba998867908773183357f3ed \ + --hash=sha256:713cd68af9dfbe0bb588e144a61aad8dcc00ef92a82d2e87183ca662d242f524 \ + --hash=sha256:71845d377c7a47afc6592aacfea738cc8a7e876d586dfba814501d8c53c1ba60 \ + --hash=sha256:753faf20b3a5906faf1fc50e4ddb8c074cb9b251e00b14c18b28492f933ac8ef \ + --hash=sha256:7e74ea87307303ba91073b63e67f2c667e93f05a8c63079ee5b7a5c8d0d7b043 \ + --hash=sha256:88eea8baf72f0ccf232c22124d122a7f26e8a24110a0273d9bcddcb0f7e1fa03 \ + --hash=sha256:923816815974425fbb1f1bf57e85eca6e14d8adc313c66db21c094927ad01815 \ + --hash=sha256:9b6f7d74d094d1f3a4e157278da97752f16ee230080ae331fcc219056ca54f77 \ + --hash=sha256:a8220fd4c6f98485e97aea65e1df76d4fed1678ede1fe1d0eed2957230d287c4 \ + --hash=sha256:ab0df0648d86a7ecbd9c632e8f8d6b21bb21b5fc9d9e095c796cacf32a728d2d \ + --hash=sha256:ac9b8d5fa4bb7fd2917ab5027f60d4234345fd366fe39aa711d5dca090aa1467 \ + --hash=sha256:badd1d7283f3e5894779a6ea8944cc765138b96804496c91812b2829f70e18a7 \ + --hash=sha256:bdc06ad71173b915167702f55d0f3f027fc61abd975bd308a0968c02db4a4c3e \ + --hash=sha256:bf0846d629e160223805db9fe8cc7aec16aaa11a07310c50c8c7164efa440aec \ + --hash=sha256:bfd309b316228acecfa30670c3887dcedf9b7a44ea39e2101e75d2654522acd4 \ + --hash=sha256:c583229f336682b7212a43d2fa32c30e643d3076178fb9f7a6a14dde85a2d8bd \ + --hash=sha256:cb15a2e2a90c8475df45c0949793af1ff413acfb0a716b8b94e488ea95ce7cff \ + --hash=sha256:d290eda8f6ada19e1771b54e5706b8f9807e6bb08e873900d5ba114ced13e02c \ + --hash=sha256:da3d6adadcf55a93c214d23941aef4abfd45652110aed6580e814152f385b862 \ + --hash=sha256:dcc7f3162d3711fd5d52e2267e44636e3e566d1e5675a5f0b30e98f2c4af7974 \ + --hash=sha256:def5663361f6771b18646620fca12968aae730132e104688766cf8a3b1d65922 \ + --hash=sha256:e5e9f630c73a490b758bf14d859a39f375e6999aea5ddd2e2e9da89b9953486a \ + --hash=sha256:e9fde97ecb7bb9c41261c2ce0da10323e9227555c674989f8d9eb7572fc2098d \ + --hash=sha256:ef71831bd61fbdb7aa0399d5c4da06bea37107ab5c79ff884cc07f2450910262 \ + --hash=sha256:f4421ab780c37210a07d138e56dd4b51f8642187cdfb433eb687fe8c11de0144 \ + --hash=sha256:f6d3655e95a80325b84c4e14c080b2470fe4f33b6846f288379ce36154993fb1 \ + --hash=sha256:fd4c928ddf6bce586285daa6d90680b9c291cfd045fc40aad34e445d57b1bf51 \ + --hash=sha256:fe239bdfdae2302e93bd6e8264bd9b71290218fff7084a9db250b55caaccf43f + # via semgrep +semantic-version==2.10.0 \ + --hash=sha256:bdabb6d336998cbb378d4b9db3a4b56a1e3235701dc05ea2690d9a997ed5041c \ + --hash=sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177 + # via semgrep +semgrep==1.183.0 \ + --hash=sha256:204dce82a74be29cf6d84aa6a32b2244ff7429fafd3d77e0ea44996d0398ba4a \ + --hash=sha256:8e9d96b976d6cb8e1240d454e50245decd52d1329d84540df26c7f06787439f7 \ + --hash=sha256:a06b09d20c5595a31be210283b8ce50251305d49fb6e9214b50329a119779751 \ + --hash=sha256:b058cc62ca32af79d2eaf44c3ff0931bfecc74857107eaf6b1b0ebb6676604ec \ + --hash=sha256:d6c85da0e679423faa82e31191460b4746124f73b29af8e864ba10a421f91037 \ + --hash=sha256:f36115c4d0cb43056ceb308273421a2f6a35e055e7e029601e130850f836646e \ + --hash=sha256:fa13eb666ea84cb9d11cea244cb106fefde57ffe51e251a0f91c7de1c4da0944 + # via -r .tooling/publish/frontend/.github/security-requirements.in +sse-starlette==3.6.0 \ + --hash=sha256:623151d6c20dc0eebf1b3379c27faae91fff883bac7ab6665f16f46440a88b3a \ + --hash=sha256:e4dfa4d237d2712cb2b4d4918eda9b457cd6b44bbecdc838af75de836565bafd + # via mcp +starlette==1.10.0 \ + --hash=sha256:478c0ab3b4ced6e82719849c118fa406f0278a3499c1a898cd15cd31bdc38ce4 \ + --hash=sha256:b8399098d4c1e3522734f7235dc79b1fc967f96cf139c81e0fa30479e0685f9b + # via + # mcp + # sse-starlette +tomli==2.4.1 \ + --hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \ + --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \ + --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \ + --hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \ + --hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \ + --hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \ + --hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \ + --hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \ + --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \ + --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \ + --hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \ + --hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \ + --hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \ + --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \ + --hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \ + --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \ + --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \ + --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \ + --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \ + --hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \ + --hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \ + --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \ + --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \ + --hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \ + --hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \ + --hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \ + --hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \ + --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \ + --hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \ + --hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \ + --hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \ + --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \ + --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \ + --hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \ + --hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \ + --hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \ + --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \ + --hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \ + --hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \ + --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \ + --hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \ + --hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \ + --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \ + --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \ + --hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \ + --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \ + --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049 + # via semgrep +typing-extensions==4.16.0 \ + --hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \ + --hash=sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5 + # via + # anyio + # mcp + # opentelemetry-api + # opentelemetry-exporter-otlp-proto-http + # opentelemetry-sdk + # opentelemetry-semantic-conventions + # pydantic + # pydantic-core + # pydantic-settings + # referencing + # semgrep + # starlette + # typing-inspection +typing-inspection==0.4.4 \ + --hash=sha256:547274fa6b0a561ccf549cc9524b999a578e737d015d8709d021f9d0d13bea47 \ + --hash=sha256:65b8397ba37ccbce054456aaccddfc91e6e3083c92824df348d96ca832f3f147 + # via + # mcp + # pydantic + # pydantic-settings +urllib3==2.8.0 \ + --hash=sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3 \ + --hash=sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63 + # via + # requests + # semgrep +uvicorn==0.54.0 \ + --hash=sha256:505bdb0f318731d45f1f712071fc781a8981f6847a31c902c9f5e652d4f67faf \ + --hash=sha256:a2e33cbfaa0306f8e6b0c13e0cb89d7d7a2da3e62b90c66e18c33d9807b28620 + # via mcp +wcmatch==8.5.2 \ + --hash=sha256:17d3ad3758f9d0b5b4dedc770b65420d4dac62e680229c287bf24c9db856a478 \ + --hash=sha256:a70222b86dea82fb382dd87b73278c10756c138bd6f8f714e2183128887b9eb2 + # via semgrep +wrapt==1.17.3 \ + --hash=sha256:02b551d101f31694fc785e58e0720ef7d9a10c4e62c1c9358ce6f63f23e30a56 \ + --hash=sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828 \ + --hash=sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f \ + --hash=sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396 \ + --hash=sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77 \ + --hash=sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d \ + --hash=sha256:0f5f51a6466667a5a356e6381d362d259125b57f059103dd9fdc8c0cf1d14139 \ + --hash=sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7 \ + --hash=sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb \ + --hash=sha256:1f23fa283f51c890eda8e34e4937079114c74b4c81d2b2f1f1d94948f5cc3d7f \ + --hash=sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f \ + --hash=sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067 \ + --hash=sha256:24c2ed34dc222ed754247a2702b1e1e89fdbaa4016f324b4b8f1a802d4ffe87f \ + --hash=sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7 \ + --hash=sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b \ + --hash=sha256:30ce38e66630599e1193798285706903110d4f057aab3168a34b7fdc85569afc \ + --hash=sha256:33486899acd2d7d3066156b03465b949da3fd41a5da6e394ec49d271baefcf05 \ + --hash=sha256:343e44b2a8e60e06a7e0d29c1671a0d9951f59174f3709962b5143f60a2a98bd \ + --hash=sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7 \ + --hash=sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9 \ + --hash=sha256:3e62d15d3cfa26e3d0788094de7b64efa75f3a53875cdbccdf78547aed547a81 \ + --hash=sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977 \ + --hash=sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa \ + --hash=sha256:46acc57b331e0b3bcb3e1ca3b421d65637915cfcd65eb783cb2f78a511193f9b \ + --hash=sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe \ + --hash=sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58 \ + --hash=sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8 \ + --hash=sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77 \ + --hash=sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85 \ + --hash=sha256:55cbbc356c2842f39bcc553cf695932e8b30e30e797f961860afb308e6b1bb7c \ + --hash=sha256:59923aa12d0157f6b82d686c3fd8e1166fa8cdfb3e17b42ce3b6147ff81528df \ + --hash=sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454 \ + --hash=sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a \ + --hash=sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e \ + --hash=sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c \ + --hash=sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6 \ + --hash=sha256:656873859b3b50eeebe6db8b1455e99d90c26ab058db8e427046dbc35c3140a5 \ + --hash=sha256:65d1d00fbfb3ea5f20add88bbc0f815150dbbde3b026e6c24759466c8b5a9ef9 \ + --hash=sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd \ + --hash=sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277 \ + --hash=sha256:70d86fa5197b8947a2fa70260b48e400bf2ccacdcab97bb7de47e3d1e6312225 \ + --hash=sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22 \ + --hash=sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116 \ + --hash=sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16 \ + --hash=sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc \ + --hash=sha256:758895b01d546812d1f42204bd443b8c433c44d090248bf22689df673ccafe00 \ + --hash=sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2 \ + --hash=sha256:7e18f01b0c3e4a07fe6dfdb00e29049ba17eadbc5e7609a2a3a4af83ab7d710a \ + --hash=sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804 \ + --hash=sha256:88bbae4d40d5a46142e70d58bf664a89b6b4befaea7b2ecc14e03cedb8e06c04 \ + --hash=sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1 \ + --hash=sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba \ + --hash=sha256:a36692b8491d30a8c75f1dfee65bef119d6f39ea84ee04d9f9311f83c5ad9390 \ + --hash=sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0 \ + --hash=sha256:a7c06742645f914f26c7f1fa47b8bc4c91d222f76ee20116c43d5ef0912bba2d \ + --hash=sha256:a9a2203361a6e6404f80b99234fe7fb37d1fc73487b5a78dc1aa5b97201e0f22 \ + --hash=sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0 \ + --hash=sha256:ad85e269fe54d506b240d2d7b9f5f2057c2aa9a2ea5b32c66f8902f768117ed2 \ + --hash=sha256:af338aa93554be859173c39c85243970dc6a289fa907402289eeae7543e1ae18 \ + --hash=sha256:afd964fd43b10c12213574db492cb8f73b2f0826c8df07a68288f8f19af2ebe6 \ + --hash=sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311 \ + --hash=sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89 \ + --hash=sha256:caea3e9c79d5f0d2c6d9ab96111601797ea5da8e6d0723f77eabb0d4068d2b2f \ + --hash=sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39 \ + --hash=sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4 \ + --hash=sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5 \ + --hash=sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa \ + --hash=sha256:df7d30371a2accfe4013e90445f6388c570f103d61019b6b7c57e0265250072a \ + --hash=sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050 \ + --hash=sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6 \ + --hash=sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235 \ + --hash=sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056 \ + --hash=sha256:e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2 \ + --hash=sha256:e6f40a8aa5a92f150bdb3e1c44b7e98fb7113955b2e5394122fa5532fec4b418 \ + --hash=sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c \ + --hash=sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a \ + --hash=sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6 \ + --hash=sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0 \ + --hash=sha256:f9b2601381be482f70e5d1051a5965c25fb3625455a2bf520b5a077b22afb775 \ + --hash=sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10 \ + --hash=sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c + # via + # opentelemetry-instrumentation + # opentelemetry-instrumentation-threading +zipp==4.1.2 \ + --hash=sha256:b30cb6cd253122169c47de245ca24a86bac2a5d3802ba15bf7ba6414eb9e144d \ + --hash=sha256:cf474b90b07ea932637e17c6b9479de2b2882900b0d311bdaf4f5c000a15a97f + # via importlib-metadata diff --git a/.github/security-rules/LICENSE b/.github/security-rules/LICENSE new file mode 100644 index 0000000..cd16fde --- /dev/null +++ b/.github/security-rules/LICENSE @@ -0,0 +1 @@ +Semgrep Rules License v1.0. For more details, visit https://semgrep.dev/legal/rules-license diff --git a/.github/security-rules/javascript__aws-lambda__security__pg-sqli.yaml b/.github/security-rules/javascript__aws-lambda__security__pg-sqli.yaml new file mode 100644 index 0000000..c6bde56 --- /dev/null +++ b/.github/security-rules/javascript__aws-lambda__security__pg-sqli.yaml @@ -0,0 +1,63 @@ +rules: +- id: pg-sqli + message: >- + Detected SQL statement that is tainted by `$EVENT` object. This could lead to SQL injection if the + variable is user-controlled + and not properly sanitized. In order to prevent SQL injection, + use parameterized queries or prepared statements instead. + You can use parameterized statements like so: + `connection.query('SELECT $1 from table', [userinput])` + metadata: + references: + - https://node-postgres.com/features/queries + category: security + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + - A05:2025 - Injection + cwe: + - "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + technology: + - aws-lambda + - postgres + - pg + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: HIGH + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + exports.handler = function ($EVENT, ...) { + ... + } + - pattern-inside: | + function $FUNC ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern-inside: | + $FUNC = function ($EVENT, ...) {...} + ... + exports.handler = $FUNC + - pattern: $EVENT + pattern-sinks: + - patterns: + - focus-metavariable: $QUERY + - pattern-either: + - pattern: $DB.query($QUERY, ...) + - pattern-either: + - pattern-inside: | + require('pg') + ... + - pattern-inside: | + import 'pg' + ... diff --git a/.github/security-rules/javascript__browser__security__dom-based-xss.yaml b/.github/security-rules/javascript__browser__security__dom-based-xss.yaml new file mode 100644 index 0000000..fb29566 --- /dev/null +++ b/.github/security-rules/javascript__browser__security__dom-based-xss.yaml @@ -0,0 +1,34 @@ +rules: +- id: dom-based-xss + message: >- + Detected possible DOM-based XSS. This occurs because a portion of the URL is being used + to construct an element added directly to the page. For example, a malicious actor could + send someone a link like this: http://www.some.site/page.html?default= + which would add the script to the page. + Consider allowlisting appropriate values or using an approach which does not involve the URL. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + - A05:2025 - Injection + references: + - https://owasp.org/www-community/attacks/DOM_Based_XSS + category: security + technology: + - browser + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - javascript + - typescript + severity: ERROR + pattern-either: + - pattern: document.write(<... document.location.$W ...>) + - pattern: document.write(<... location.$W ...>) diff --git a/.github/security-rules/javascript__browser__security__eval-detected.yaml b/.github/security-rules/javascript__browser__security__eval-detected.yaml new file mode 100644 index 0000000..94a76f5 --- /dev/null +++ b/.github/security-rules/javascript__browser__security__eval-detected.yaml @@ -0,0 +1,35 @@ +rules: +- id: eval-detected + message: >- + Detected the use of eval(). eval() can be dangerous if used to evaluate + dynamic content. If this content can be input from outside the program, this + may be a code injection vulnerability. Ensure evaluated content is not definable + by external sources. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + - A05:2025 - Injection + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.2.4 Dynamic Code Execution Features + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v52-sanitization-and-sandboxing + version: '4' + category: security + technology: + - browser + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-not: eval("...") + - pattern: eval(...) diff --git a/.github/security-rules/javascript__browser__security__insecure-document-method.yaml b/.github/security-rules/javascript__browser__security__insecure-document-method.yaml new file mode 100644 index 0000000..9a5764a --- /dev/null +++ b/.github/security-rules/javascript__browser__security__insecure-document-method.yaml @@ -0,0 +1,40 @@ +rules: +- id: insecure-document-method + message: >- + User controlled data in methods like `innerHTML`, `outerHTML` or `document.write` is an anti-pattern + that can lead to XSS vulnerabilities + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + - A05:2025 - Injection + category: security + technology: + - browser + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: ERROR + patterns: + - pattern-either: + - pattern: | + $EL.innerHTML = $HTML; + - pattern: | + $EL.outerHTML = $HTML; + - pattern: document.write(...) + - pattern-not: | + $EL.innerHTML = "..."; + - pattern-not: | + $EL.outerHTML = "..."; + - pattern-not: document.write("...") diff --git a/.github/security-rules/javascript__browser__security__insecure-innerhtml.yaml b/.github/security-rules/javascript__browser__security__insecure-innerhtml.yaml new file mode 100644 index 0000000..ed4216d --- /dev/null +++ b/.github/security-rules/javascript__browser__security__insecure-innerhtml.yaml @@ -0,0 +1,32 @@ +rules: +- id: insecure-innerhtml + message: >- + User controlled data in a `$EL.innerHTML` is an anti-pattern that can lead to XSS vulnerabilities + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + - A05:2025 - Injection + category: security + technology: + - browser + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: ERROR + patterns: + - pattern: | + $EL.innerHTML = $HTML; + - pattern-not: | + $EL.innerHTML = "..."; diff --git a/.github/security-rules/javascript__browser__security__insufficient-postmessage-origin-validation.yaml b/.github/security-rules/javascript__browser__security__insufficient-postmessage-origin-validation.yaml new file mode 100644 index 0000000..80bd9a0 --- /dev/null +++ b/.github/security-rules/javascript__browser__security__insufficient-postmessage-origin-validation.yaml @@ -0,0 +1,51 @@ +rules: +- id: insufficient-postmessage-origin-validation + message: >- + No validation of origin is done by the addEventListener API. It may be possible to exploit this flaw + to perform Cross Origin attacks such as Cross-Site Scripting(XSS). + metadata: + owasp: + - A08:2021 - Software and Data Integrity Failures + - A08:2025 - Software or Data Integrity Failures + cwe: + - 'CWE-345: Insufficient Verification of Data Authenticity' + category: security + technology: + - browser + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + references: + - https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures + languages: + - javascript + - typescript + severity: WARNING + pattern-either: + - patterns: + - pattern: | + window.addEventListener('message', $FUNC, ...) + - metavariable-pattern: + patterns: + - pattern: | + function($OBJ) { ... } + - pattern-not: | + function($OBJ) { ... if (<... $OBJ.origin ...>) { ... } ... } + metavariable: $FUNC + - patterns: + - pattern-either: + - pattern-inside: | + function $FNAME($OBJ) { $CONTEXT } + ... + - pattern-inside: | + $FNAME = (...) => { $CONTEXT } + ... + - pattern: | + window.addEventListener('message', $FNAME,...) + - metavariable-pattern: + patterns: + - pattern-not: | + ... if (<... $OBJ.origin ...>) { ... } ... + metavariable: $CONTEXT diff --git a/.github/security-rules/javascript__browser__security__open-redirect-from-function.yaml b/.github/security-rules/javascript__browser__security__open-redirect-from-function.yaml new file mode 100644 index 0000000..4c05aad --- /dev/null +++ b/.github/security-rules/javascript__browser__security__open-redirect-from-function.yaml @@ -0,0 +1,58 @@ +rules: +- id: js-open-redirect-from-function + message: >- + The application accepts potentially user-controlled input `$PROP` which + can control the location of the current window context. This can lead two + types of vulnerabilities open-redirection and Cross-Site-Scripting + (XSS) with JavaScript URIs. It is recommended to validate + user-controllable input before allowing it to control the redirection. + metadata: + confidence: LOW + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + owasp: + - A01:2021 - Broken Access Control + - A01:2025 - Broken Access Control + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.1 Insecue Redirect + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v51-input-validation + version: '4' + category: security + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html + technology: + - browser + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + languages: + - javascript + - typescript + severity: INFO + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + function ... (..., $PROP, ...) { ... } + - focus-metavariable: $PROP + pattern-sinks: + - patterns: + - pattern-either: + - pattern: location.href = $SINK + - pattern: window.location.href = $SINK + - pattern: this.window.location.href = $SINK + - pattern: this.location.href = $SINK + - pattern: location.replace($SINK) + - pattern: window.location.replace($SINK) + - pattern: this.window.location.replace($SINK) + - pattern: this.location.replace($SINK) + - focus-metavariable: $SINK + - metavariable-pattern: + patterns: + - pattern-not: | + "..." + $VALUE + - pattern-not: | + `...${$VALUE}` + metavariable: $SINK diff --git a/.github/security-rules/javascript__browser__security__open-redirect.yaml b/.github/security-rules/javascript__browser__security__open-redirect.yaml new file mode 100644 index 0000000..9022802 --- /dev/null +++ b/.github/security-rules/javascript__browser__security__open-redirect.yaml @@ -0,0 +1,95 @@ +rules: +- id: js-open-redirect + message: >- + The application accepts potentially user-controlled input `$PROP` which + can control the location of the current window context. This can lead two + types of vulnerabilities open-redirection and Cross-Site-Scripting + (XSS) with JavaScript URIs. It is recommended to validate + user-controllable input before allowing it to control the redirection. + options: + interfile: true + metadata: + interfile: true + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + owasp: + - A01:2021 - Broken Access Control + - A01:2025 - Broken Access Control + asvs: + section: V5 Validation, Sanitization and Encoding + control_id: 5.5.1 Insecue Redirect + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x13-V5-Validation-Sanitization-Encoding.md#v51-input-validation + version: '4' + category: security + confidence: HIGH + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html + technology: + - browser + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: | + new URLSearchParams($WINDOW. ... .location.search).get('...') + - pattern: | + new URLSearchParams(location.search).get('...') + - pattern: | + new URLSearchParams($WINDOW. ... .location.hash.substring(1)).get('...') + - pattern: | + new URLSearchParams(location.hash.substring(1)).get('...') + - patterns: + - pattern-either: + - pattern-inside: | + $PROPS = new URLSearchParams($WINDOW. ... .location.search) + ... + - pattern-inside: | + $PROPS = new URLSearchParams(location.search) + ... + - pattern-inside: | + $PROPS = new URLSearchParams($WINDOW. ... .location.hash.substring(1)) + ... + - pattern-inside: | + $PROPS = new URLSearchParams(location.hash.substring(1)) + ... + - pattern: $PROPS.get('...') + - patterns: + - pattern-either: + - pattern-inside: | + $PROPS = new URL($WINDOW. ... .location.href) + ... + - pattern-inside: | + $PROPS = new URL(location.href) + ... + - pattern: $PROPS.searchParams.get('...') + - patterns: + - pattern-either: + - pattern: | + new URL($WINDOW. ... .location.href).searchParams.get('...') + - pattern: | + new URL(location.href).searchParams.get('...') + pattern-sinks: + - patterns: + - pattern-either: + - pattern: location.href = $SINK + - pattern: $THIS. ... .location.href = $SINK + - pattern: location.replace($SINK) + - pattern: $THIS. ... .location.replace($SINK) + - pattern: location = $SINK + - pattern: $WINDOW. ... .location = $SINK + - focus-metavariable: $SINK + - metavariable-pattern: + patterns: + - pattern-not: | + "..." + $VALUE + - pattern-not: | + `...${$VALUE}` + metavariable: $SINK diff --git a/.github/security-rules/javascript__browser__security__raw-html-concat.yaml b/.github/security-rules/javascript__browser__security__raw-html-concat.yaml new file mode 100644 index 0000000..b7bdb57 --- /dev/null +++ b/.github/security-rules/javascript__browser__security__raw-html-concat.yaml @@ -0,0 +1,167 @@ +rules: +- id: raw-html-concat + message: User controlled data in a HTML string may result in XSS + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + - A05:2025 - Injection + references: + - https://owasp.org/www-community/attacks/xss/ + category: security + technology: + - browser + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern: location.href + - pattern: location.hash + - pattern: location.search + - pattern: $WINDOW. ... .location.href + - pattern: $WINDOW. ... .location.hash + - pattern: $WINDOW. ... .location.search + pattern-sinks: + - patterns: + - pattern-either: + - patterns: + - pattern: $STRING + $EXPR + - pattern-not: $STRING + "..." + - metavariable-pattern: + patterns: + - pattern: <$TAG ... + - pattern-not: <$TAG ...>...... + metavariable: $STRING + language: generic + - patterns: + - pattern: $EXPR + $STRING + - pattern-not: '"..." + $STRING' + - metavariable-pattern: + patterns: + - pattern: '... - + User controlled data in a HTML string may result in XSS + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + - A05:2025 - Injection + references: + - https://owasp.org/www-community/attacks/xss/ + category: security + technology: + - browser + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - patterns: + - pattern: | + [..., $STRING, ...].join(...) + - metavariable-pattern: + metavariable: $STRING + language: generic + patterns: + - pattern-either: + - pattern: | + ... - + The target origin of the window.postMessage() API is set to "*". This could allow for information + disclosure due to the possibility of any origin allowed to receive the message. + metadata: + owasp: + - A08:2021 - Software and Data Integrity Failures + - A08:2025 - Software or Data Integrity Failures + cwe: + - 'CWE-345: Insufficient Verification of Data Authenticity' + category: security + technology: + - browser + subcategory: + - audit + likelihood: HIGH + impact: MEDIUM + confidence: MEDIUM + references: + - https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures + languages: + - javascript + - typescript + severity: WARNING + pattern: $OBJECT.postMessage(...,'*',...) diff --git a/.github/security-rules/javascript__lang__security__detect-buffer-noassert.yaml b/.github/security-rules/javascript__lang__security__detect-buffer-noassert.yaml new file mode 100644 index 0000000..131d20a --- /dev/null +++ b/.github/security-rules/javascript__lang__security__detect-buffer-noassert.yaml @@ -0,0 +1,32 @@ +rules: +- id: detect-buffer-noassert + message: >- + Detected usage of noassert in Buffer API, which allows the offset the be beyond + the + end of the buffer. This could result in writing or reading beyond the end of the + buffer. + metadata: + cwe: + - 'CWE-119: Improper Restriction of Operations within the Bounds of a Memory Buffer' + source-rule-url: https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-buffer-noassert.js + category: security + technology: + - javascript + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + references: + - https://cwe.mitre.org/data/definitions/119.html + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern: $OBJ.$API(..., true) + - metavariable-regex: + metavariable: $API + regex: (read|write)(U?Int8|(U?Int(16|32)|Float|Double)(LE|BE)) diff --git a/.github/security-rules/javascript__lang__security__detect-child-process.yaml b/.github/security-rules/javascript__lang__security__detect-child-process.yaml new file mode 100644 index 0000000..e35bcc1 --- /dev/null +++ b/.github/security-rules/javascript__lang__security__detect-child-process.yaml @@ -0,0 +1,79 @@ +rules: +- id: detect-child-process + message: >- + Detected calls to child_process from a function argument `$FUNC`. This could lead to a command injection + if the input is user controllable. Try to avoid calls to child_process, and if it is needed + ensure user input is correctly sanitized or sandboxed. + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + - A05:2025 - Injection + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Nodejs_Security_Cheat_Sheet.html#do-not-use-dangerous-functions + source-rule-url: https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-child-process.js + category: security + technology: + - javascript + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: HIGH + confidence: LOW + languages: + - javascript + - typescript + severity: ERROR + mode: taint + pattern-sources: + - patterns: + - pattern-inside: | + function ... (...,$FUNC,...) { + ... + } + - focus-metavariable: $FUNC + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $CP = require('child_process') + ... + - pattern-inside: | + import * as $CP from 'child_process' + ... + - pattern-inside: | + import $CP from 'child_process' + ... + - pattern-either: + - pattern: $CP.exec($CMD,...) + - pattern: $CP.execSync($CMD,...) + - pattern: $CP.spawn($CMD,...) + - pattern: $CP.spawnSync($CMD,...) + - pattern-not-inside: $CP.$EXEC("...",...) + - pattern-not-inside: $CP.$EXEC(["...",...],...) + - pattern-not-inside: | + $CMD = "..." + ... + - pattern-not-inside: | + $CMD = ["...",...] + ... + - focus-metavariable: $CMD + - patterns: + - pattern-either: + - pattern: child_process.exec($CMD,...) + - pattern: child_process.execSync($CMD,...) + - pattern: child_process.spawn($CMD,...) + - pattern: child_process.spawnSync($CMD,...) + - pattern-not-inside: child_process.$EXEC("...",...) + - pattern-not-inside: child_process.$EXEC(["...",...],...) + - pattern-not-inside: | + $CMD = "..." + ... + - pattern-not-inside: | + $CMD = ["...",...] + ... + - focus-metavariable: $CMD diff --git a/.github/security-rules/javascript__lang__security__detect-disable-mustache-escape.yaml b/.github/security-rules/javascript__lang__security__detect-disable-mustache-escape.yaml new file mode 100644 index 0000000..302d801 --- /dev/null +++ b/.github/security-rules/javascript__lang__security__detect-disable-mustache-escape.yaml @@ -0,0 +1,27 @@ +rules: +- id: detect-disable-mustache-escape + message: >- + Markup escaping disabled. This can be used with some template engines to escape + disabling of HTML entities, which can lead to XSS attacks. + metadata: + cwe: + - 'CWE-116: Improper Encoding or Escaping of Output' + owasp: + - A03:2021 - Injection + - A05:2025 - Injection + source-rule-url: https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-disable-mustache-escape.js + category: security + technology: + - mustache + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: WARNING + pattern: $OBJ.escapeMarkup = false diff --git a/.github/security-rules/javascript__lang__security__detect-eval-with-expression.yaml b/.github/security-rules/javascript__lang__security__detect-eval-with-expression.yaml new file mode 100644 index 0000000..ac58700 --- /dev/null +++ b/.github/security-rules/javascript__lang__security__detect-eval-with-expression.yaml @@ -0,0 +1,88 @@ +rules: +- id: detect-eval-with-expression + message: >- + Detected use of dynamic execution of JavaScript which may come from + user-input, which can lead to Cross-Site-Scripting (XSS). Where possible + avoid including user-input in functions which dynamically execute user-input. + metadata: + cwe: + - "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')" + owasp: + - A03:2021 - Injection + - A05:2025 - Injection + source-rule-url: https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-eval-with-expression.js + references: + - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#never_use_eval! + category: security + technology: + - javascript + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + confidence: MEDIUM + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + $PROP = new URLSearchParams($WINDOW. ... .location.search).get('...') + ... + - pattern-inside: | + $PROP = new URLSearchParams(location.search).get('...') + ... + - pattern-inside: | + $PROP = new URLSearchParams($WINDOW. ... .location.hash.substring(1)).get('...') + ... + - pattern-inside: | + $PROP = new URLSearchParams(location.hash.substring(1)).get('...') + ... + - focus-metavariable: $PROP + - patterns: + - pattern-either: + - pattern-inside: | + $PROPS = new URLSearchParams($WINDOW. ... .location.search) + ... + - pattern-inside: | + $PROPS = new URLSearchParams(location.search) + ... + - pattern-inside: | + $PROPS = new + URLSearchParams($WINDOW. ... .location.hash.substring(1)) + ... + - pattern-inside: | + $PROPS = new URLSearchParams(location.hash.substring(1)) + ... + - pattern: $PROPS.get('...') + - focus-metavariable: $PROPS + - patterns: + - pattern-either: + - pattern: location.href + - pattern: location.hash + - pattern: location.search + - pattern: $WINDOW. ... .location.href + - pattern: $WINDOW. ... .location.hash + - pattern: $WINDOW. ... .location.search + pattern-sinks: + - patterns: + - pattern-either: + - pattern: eval(<... $SINK ...>) + - pattern: window.eval(<... $SINK ...>) + - pattern: new Function(<... $SINK ...>) + - pattern: new Function(<... $SINK ...>)(...) + - pattern: setTimeout(<... $SINK ...>,...) + - pattern: setInterval(<... $SINK ...>,...) + - focus-metavariable: $SINK + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern: location.href = $FUNC(...) + - pattern: location.hash = $FUNC(...) + - pattern: location.search = $FUNC(...) + - pattern: $WINDOW. ... .location.href = $FUNC(...) + - pattern: $WINDOW. ... .location.hash = $FUNC(...) + - pattern: $WINDOW. ... .location.search = $FUNC(...) diff --git a/.github/security-rules/javascript__lang__security__detect-insecure-websocket.yaml b/.github/security-rules/javascript__lang__security__detect-insecure-websocket.yaml new file mode 100644 index 0000000..186e2a2 --- /dev/null +++ b/.github/security-rules/javascript__lang__security__detect-insecure-websocket.yaml @@ -0,0 +1,32 @@ +rules: +- id: detect-insecure-websocket + message: Insecure WebSocket Detected. WebSocket Secure (wss) should be used for all WebSocket connections. + metadata: + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + asvs: + section: 'V13: API and Web Service Verification Requirements' + control_id: 13.5.1 Insecure WebSocket + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x21-V13-API.md#v135-websocket-security-requirements + version: '4' + category: security + technology: + - regex + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + - A04:2025 - Cryptographic Failures + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + languages: + - regex + severity: ERROR + patterns: + - pattern-regex: \bws:\/\/ + - pattern-not-inside: \bws:\/\/localhost.* + - pattern-not-inside: \bws:\/\/127.0.0.1.* diff --git a/.github/security-rules/javascript__lang__security__detect-no-csrf-before-method-override.yaml b/.github/security-rules/javascript__lang__security__detect-no-csrf-before-method-override.yaml new file mode 100644 index 0000000..27c6193 --- /dev/null +++ b/.github/security-rules/javascript__lang__security__detect-no-csrf-before-method-override.yaml @@ -0,0 +1,35 @@ +rules: +- id: detect-no-csrf-before-method-override + message: >- + Detected use of express.csrf() middleware before express.methodOverride(). This + can + allow GET requests (which are not checked by csrf) to turn into POST requests + later. + metadata: + cwe: + - 'CWE-352: Cross-Site Request Forgery (CSRF)' + source-rule-url: https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-no-csrf-before-method-override.js + references: + - https://github.com/nodesecurity/eslint-plugin-security/blob/master/docs/bypass-connect-csrf-protection-by-abusing.md + category: security + technology: + - javascript + owasp: + - A01:2021 - Broken Access Control + - A05:2017 - Broken Access Control + - A01:2025 - Broken Access Control + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + pattern: | + express.csrf(); + ... + express.methodOverride(); diff --git a/.github/security-rules/javascript__lang__security__detect-pseudoRandomBytes.yaml b/.github/security-rules/javascript__lang__security__detect-pseudoRandomBytes.yaml new file mode 100644 index 0000000..9c9e8ac --- /dev/null +++ b/.github/security-rules/javascript__lang__security__detect-pseudoRandomBytes.yaml @@ -0,0 +1,32 @@ +rules: +- id: detect-pseudoRandomBytes + message: >- + Detected usage of crypto.pseudoRandomBytes, which does not produce secure random + numbers. + metadata: + cwe: + - 'CWE-338: Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)' + owasp: + - A02:2021 - Cryptographic Failures + - A04:2025 - Cryptographic Failures + source-rule-url: https://github.com/nodesecurity/eslint-plugin-security/blob/master/rules/detect-pseudoRandomBytes.js + asvs: + section: 'V6: Stored Cryptography Verification Requirements' + control_id: 6.3.1 Insecure Randomness + control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x14-V6-Cryptography.md#v63-random-values + version: '4' + category: security + technology: + - javascript + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + references: + - https://owasp.org/Top10/A02_2021-Cryptographic_Failures + languages: + - javascript + - typescript + severity: WARNING + pattern: crypto.pseudoRandomBytes diff --git a/.github/security-rules/javascript__lang__security__html-in-template-string.yaml b/.github/security-rules/javascript__lang__security__html-in-template-string.yaml new file mode 100644 index 0000000..130f2d7 --- /dev/null +++ b/.github/security-rules/javascript__lang__security__html-in-template-string.yaml @@ -0,0 +1,36 @@ +rules: +- id: html-in-template-string + message: >- + This template literal looks like HTML and has interpolated variables. + These variables are not HTML-encoded by default. If the variables contain + HTML tags, these may be interpreted by the browser, resulting in cross-site + scripting (XSS). + metadata: + cwe: + - 'CWE-116: Improper Encoding or Escaping of Output' + owasp: + - A03:2021 - Injection + - A05:2025 - Injection + category: security + technology: + - javascript + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: WARNING + patterns: + - pattern-either: + - pattern: | + `$HTML${$VAR}...` + - pattern: | + `...${$VAR}$HTML` + - metavariable-regex: + metavariable: $HTML + regex: .*- + Depending on the context, user control data in `Object.assign` can cause web response + to include data that it should not have or can lead to a mass assignment vulnerability. + metadata: + cwe: + - "CWE-601: URL Redirection to Untrusted Site ('Open Redirect')" + owasp: + - A01:2021 - Broken Access Control + - A01:2025 - Broken Access Control + references: + - https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html + - https://en.wikipedia.org/wiki/Mass_assignment_vulnerability + category: security + technology: + - javascript + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: LOW + languages: + - javascript + - typescript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern: JSON.parse(...) + - pattern-not: JSON.parse("...",...) + pattern-sinks: + - pattern: Object.assign(...) diff --git a/.github/security-rules/javascript__lang__security__spawn-git-clone.yaml b/.github/security-rules/javascript__lang__security__spawn-git-clone.yaml new file mode 100644 index 0000000..62e6c75 --- /dev/null +++ b/.github/security-rules/javascript__lang__security__spawn-git-clone.yaml @@ -0,0 +1,40 @@ +rules: +- id: spawn-git-clone + message: >- + Git allows shell commands to be specified in ext URLs for remote repositories. + For example, git clone 'ext::sh -c whoami% >&2' will execute the whoami command + to try to connect to a remote repository. + Make sure that the URL is not controlled by external input. + metadata: + cwe: + - "CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')" + owasp: + - A01:2017 - Injection + - A03:2021 - Injection + - A05:2025 - Injection + category: security + technology: + - git + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + references: + - https://owasp.org/Top10/A03_2021-Injection + languages: + - javascript + - typescript + severity: ERROR + patterns: + - pattern-either: + - pattern: spawn('git', ['clone',...,$F]) + - pattern: $X.spawn('git', ['clone',...,$F]) + - pattern: spawn('git', ['clone',...,$P,$F]) + - pattern: $X.spawn('git', ['clone',...,$P,$F]) + - pattern-not: spawn('git', ['clone',...,"..."]) + - pattern-not: $X.spawn('git', ['clone',...,"..."]) + - pattern-not: spawn('git', ['clone',...,"...","..."]) + - pattern-not: $X.spawn('git', ['clone',...,"...","..."]) diff --git a/.github/security-rules/provenance.json b/.github/security-rules/provenance.json new file mode 100644 index 0000000..0505d47 --- /dev/null +++ b/.github/security-rules/provenance.json @@ -0,0 +1,166 @@ +{ + "repository": "https://github.com/semgrep/semgrep-rules", + "commit": "16b9e6d45f10649f6a531ec4838ed9924372c3bc", + "files": { + "javascript__aws-lambda__security__pg-sqli.yaml": { + "source": "javascript/aws-lambda/security/pg-sqli.yaml", + "sha256": "267e1dea6127d5f6b311a048c8a9de8c7a88e756a90a31c5c2bd737715c919e8" + }, + "javascript__browser__security__dom-based-xss.yaml": { + "source": "javascript/browser/security/dom-based-xss.yaml", + "sha256": "d34055a348ee0d5e6f5587825bd14c9546997550e624e3966e5ef8438f86381d" + }, + "javascript__browser__security__eval-detected.yaml": { + "source": "javascript/browser/security/eval-detected.yaml", + "sha256": "356589363d16cda8bd2ca1d296ce2b6953105ee4c751ddbbc9bcde5849341811" + }, + "javascript__browser__security__insecure-document-method.yaml": { + "source": "javascript/browser/security/insecure-document-method.yaml", + "sha256": "c2071baab4896cb66b3337ef2d901c9c772a6cbcfd4b2c942efb74ee0be3b7f3" + }, + "javascript__browser__security__insecure-innerhtml.yaml": { + "source": "javascript/browser/security/insecure-innerhtml.yaml", + "sha256": "3f2854f92c3c8a1ba3a107a140a5b31789650851be57586fd21a409e129193e4" + }, + "javascript__browser__security__insufficient-postmessage-origin-validation.yaml": { + "source": "javascript/browser/security/insufficient-postmessage-origin-validation.yaml", + "sha256": "72e69717624b282e678e03aeab8416c883a9d0c286f0496af406a80fd4dcc2bf" + }, + "javascript__browser__security__open-redirect-from-function.yaml": { + "source": "javascript/browser/security/open-redirect-from-function.yaml", + "sha256": "6afe3ff95252261c3f3502bda97921193e821a6931119f945fa30aae3c122b8d" + }, + "javascript__browser__security__open-redirect.yaml": { + "source": "javascript/browser/security/open-redirect.yaml", + "sha256": "896332cf7d17f4ccea855006baebfddd83ccf90e07315958bb62bbc2916950f4" + }, + "javascript__browser__security__raw-html-concat.yaml": { + "source": "javascript/browser/security/raw-html-concat.yaml", + "sha256": "39c8c842711e452c1b4b0b03bc526652d69c887b6ac790215604ec4cde80a403" + }, + "javascript__browser__security__raw-html-join.yaml": { + "source": "javascript/browser/security/raw-html-join.yaml", + "sha256": "276ca2addaf9507ef1a792411ff8bc71f55f7c93ddbedee902b1a627c1fa271b" + }, + "javascript__browser__security__wildcard-postmessage-configuration.yaml": { + "source": "javascript/browser/security/wildcard-postmessage-configuration.yaml", + "sha256": "4bb9d0a44a38c433ebe1b3df30895576a056262c3e12da57cee9c6be9fc0d813" + }, + "javascript__lang__security__detect-buffer-noassert.yaml": { + "source": "javascript/lang/security/detect-buffer-noassert.yaml", + "sha256": "e6566d2c7138b038e1c3167f3e9ff98550cf81a2d70caa94a5362a55294077f6" + }, + "javascript__lang__security__detect-child-process.yaml": { + "source": "javascript/lang/security/detect-child-process.yaml", + "sha256": "baee696b05b3c38fa5a82435ae458026ec81ce9a6e6a73116d68dc963496296c" + }, + "javascript__lang__security__detect-disable-mustache-escape.yaml": { + "source": "javascript/lang/security/detect-disable-mustache-escape.yaml", + "sha256": "8d6d81249121230be2d11fd7a2cce2ce23837520f8e0fc1df45868ec159edb09" + }, + "javascript__lang__security__detect-eval-with-expression.yaml": { + "source": "javascript/lang/security/detect-eval-with-expression.yaml", + "sha256": "3b8fe2524b094c72c34aaa6d21b0408ffdac2471a335125cf726993253777951" + }, + "javascript__lang__security__detect-insecure-websocket.yaml": { + "source": "javascript/lang/security/detect-insecure-websocket.yaml", + "sha256": "65935c49d62e264a6b85a496455989137d7e82d4698855d511d173ed08ad3099" + }, + "javascript__lang__security__detect-no-csrf-before-method-override.yaml": { + "source": "javascript/lang/security/detect-no-csrf-before-method-override.yaml", + "sha256": "d361537a89c773a4940f107a2e787c6309d121e965a88f471b55d0db15ccb859" + }, + "javascript__lang__security__detect-pseudoRandomBytes.yaml": { + "source": "javascript/lang/security/detect-pseudoRandomBytes.yaml", + "sha256": "d3c2b2168e6b1efdfc305a783387634e3ead8e0db6d4bdd3417381e177da4058" + }, + "javascript__lang__security__html-in-template-string.yaml": { + "source": "javascript/lang/security/html-in-template-string.yaml", + "sha256": "1c32479fb6228a0a3a3618e6308b5bdfec14f05f7cf12a2321519b4095cf117d" + }, + "javascript__lang__security__insecure-object-assign.yaml": { + "source": "javascript/lang/security/insecure-object-assign.yaml", + "sha256": "bc5a5fdef1a8a4889f1d3efebdd3cb1f1e58f5261418928ae6c765eb7f1b2397" + }, + "javascript__lang__security__spawn-git-clone.yaml": { + "source": "javascript/lang/security/spawn-git-clone.yaml", + "sha256": "d87fdf812e1a61f137bde701d75415525ea66c45c593374a6f9ec2081609539f" + }, + "rust__lang__security__args-os.yml": { + "source": "rust/lang/security/args-os.yml", + "sha256": "24a9fb8d86f4a749a921f7a9b687fcdbef168d4a18e52c5471bcf5db232bfdf5" + }, + "rust__lang__security__args.yml": { + "source": "rust/lang/security/args.yml", + "sha256": "c84ef972cc47e8739ca4052d65136a44715561190a5dfcd67a0c7498c816cb6e" + }, + "rust__lang__security__current-exe.yml": { + "source": "rust/lang/security/current-exe.yml", + "sha256": "3eac3039fadf1817f0dac73df173cbe579ac8edf20312ff10db24cf8f5aaa9e0" + }, + "rust__lang__security__insecure-hashes.yml": { + "source": "rust/lang/security/insecure-hashes.yml", + "sha256": "5d77d4459a9d29e4b1b2303f2bdbc5282c7e30eda287e288428792659296dd24" + }, + "rust__lang__security__reqwest-accept-invalid.yml": { + "source": "rust/lang/security/reqwest-accept-invalid.yml", + "sha256": "dfd5bb583ee0d69342d684b9472b01dd4f39a951df645b4278b44827740a3c6a" + }, + "rust__lang__security__reqwest-set-sensitive.yml": { + "source": "rust/lang/security/reqwest-set-sensitive.yml", + "sha256": "9b967da495a349b99644b1c3b8665b52803c8837e691afc89f73a11798739bb9" + }, + "rust__lang__security__rustls-dangerous.yml": { + "source": "rust/lang/security/rustls-dangerous.yml", + "sha256": "dc3187a08d4cbf9200b043c30cd46ad5cd2ce8782d43b372773dd37c4362b8f8" + }, + "rust__lang__security__ssl-verify-none.yml": { + "source": "rust/lang/security/ssl-verify-none.yml", + "sha256": "2933371073e51986b8c6a45d1761926c3411f66ee37a2ddf36fd090f2eeb61c8" + }, + "rust__lang__security__temp-dir.yml": { + "source": "rust/lang/security/temp-dir.yml", + "sha256": "a06af8b8e02a1ff20bb62d56d80ad43e6c71390f1f589226db3d14a6731bed10" + }, + "rust__lang__security__unsafe-usage.yml": { + "source": "rust/lang/security/unsafe-usage.yml", + "sha256": "9a0841f3fcdefa8f9b904add92e011eb3709b4a9df791ec00ed138b068cee37d" + }, + "typescript__react__security__audit__react-dangerouslysetinnerhtml.yaml": { + "source": "typescript/react/security/audit/react-dangerouslysetinnerhtml.yaml", + "sha256": "794094512be7f7dcaa49a4b1edf621dbdf1f984b4f29ab09a23538c0e59c2136" + }, + "typescript__react__security__audit__react-href-var.yaml": { + "source": "typescript/react/security/audit/react-href-var.yaml", + "sha256": "aa8ade23b4a351f93be2bcd47ecc694b6b3d2a861a65fc8d345a6cb87f9253f2" + }, + "typescript__react__security__audit__react-jwt-decoded-property.yaml": { + "source": "typescript/react/security/audit/react-jwt-decoded-property.yaml", + "sha256": "5e4ca6b6fa672c29cfbf78993f8b3b5724d77fd99da251de7b108835705fec15" + }, + "typescript__react__security__audit__react-jwt-in-localstorage.yaml": { + "source": "typescript/react/security/audit/react-jwt-in-localstorage.yaml", + "sha256": "8850734261ecbb6eee29707a683acc5d177b2d785cec00ef4788eb6193b5ba05" + }, + "typescript__react__security__audit__react-unsanitized-method.yaml": { + "source": "typescript/react/security/audit/react-unsanitized-method.yaml", + "sha256": "c774bae09d1b0d8c4c12c32436f4dad6d93a590f9cfbd159bc2ab2416054d273" + }, + "typescript__react__security__audit__react-unsanitized-property.yaml": { + "source": "typescript/react/security/audit/react-unsanitized-property.yaml", + "sha256": "0dc00b10abae599731f0c4f56c9efc64cf2469dfa4cc0d562ca6a3a0581be59d" + }, + "typescript__react__security__react-insecure-request.yaml": { + "source": "typescript/react/security/react-insecure-request.yaml", + "sha256": "4869905cc60559b8ca0ed0ac62c5abe9a26b2ee0e3bbdc0d1baf47271ee70376" + }, + "typescript__react__security__react-markdown-insecure-html.yaml": { + "source": "typescript/react/security/react-markdown-insecure-html.yaml", + "sha256": "e464c0f72c8a89ae325524b738c7c2024be1258e7a060a6365b487a0aa284434" + }, + "LICENSE": { + "source": "LICENSE", + "sha256": "1a6466ae5f1c68631bbd13e3f1aa8f380d84219853c08f0456b853fccfacee1d" + } + } +} diff --git a/.github/security-rules/rust__lang__security__args-os.yml b/.github/security-rules/rust__lang__security__args-os.yml new file mode 100644 index 0000000..52f6a5b --- /dev/null +++ b/.github/security-rules/rust__lang__security__args-os.yml @@ -0,0 +1,21 @@ +rules: + - id: args-os + message: >- + args_os should not be used for security operations. From the docs: + "The first element is traditionally the path of the executable, but it + can be set to arbitrary text, and might not even exist. This means this + property should not be relied upon for security purposes." + pattern: "std::env::args_os()" + metadata: + references: + - https://doc.rust-lang.org/stable/std/env/fn.args_os.html + technology: + - rust + category: security + cwe: "CWE-807: Reliance on Untrusted Inputs in a Security Decision" + confidence: HIGH + likelihood: LOW + impact: LOW + subcategory: audit + languages: [rust] + severity: INFO diff --git a/.github/security-rules/rust__lang__security__args.yml b/.github/security-rules/rust__lang__security__args.yml new file mode 100644 index 0000000..e90ddb4 --- /dev/null +++ b/.github/security-rules/rust__lang__security__args.yml @@ -0,0 +1,21 @@ +rules: + - id: args + message: >- + args should not be used for security operations. From the docs: + "The first element is traditionally the path of the executable, but it + can be set to arbitrary text, and might not even exist. This means this + property should not be relied upon for security purposes." + pattern: "std::env::args()" + metadata: + references: + - https://doc.rust-lang.org/stable/std/env/fn.args.html + technology: + - rust + category: security + cwe: "CWE-807: Reliance on Untrusted Inputs in a Security Decision" + confidence: HIGH + likelihood: LOW + impact: LOW + subcategory: audit + languages: [rust] + severity: INFO diff --git a/.github/security-rules/rust__lang__security__current-exe.yml b/.github/security-rules/rust__lang__security__current-exe.yml new file mode 100644 index 0000000..f4690c0 --- /dev/null +++ b/.github/security-rules/rust__lang__security__current-exe.yml @@ -0,0 +1,21 @@ +rules: + - id: current-exe + message: >- + current_exe should not be used for security operations. From the docs: + "The output of this function should not be trusted for anything that + might have security implications. Basically, if users can run the + executable, they can change the output arbitrarily." + pattern: "std::env::current_exe()" + metadata: + references: + - https://doc.rust-lang.org/stable/std/env/fn.current_exe.html#security + technology: + - rust + category: security + cwe: "CWE-807: Reliance on Untrusted Inputs in a Security Decision" + confidence: HIGH + likelihood: LOW + impact: LOW + subcategory: audit + languages: [rust] + severity: INFO diff --git a/.github/security-rules/rust__lang__security__insecure-hashes.yml b/.github/security-rules/rust__lang__security__insecure-hashes.yml new file mode 100644 index 0000000..f5da8d4 --- /dev/null +++ b/.github/security-rules/rust__lang__security__insecure-hashes.yml @@ -0,0 +1,25 @@ +rules: + - id: insecure-hashes + message: Detected cryptographically insecure hashing function + pattern-either: + - pattern: "md2::Md2::new(...)" + - pattern: "md4::Md4::new(...)" + - pattern: "md5::Md5::new(...)" + - pattern: "sha1::Sha1::new(...)" + metadata: + references: + - https://github.com/RustCrypto/hashes + - https://docs.rs/md2/latest/md2/ + - https://docs.rs/md4/latest/md4/ + - https://docs.rs/md5/latest/md5/ + - https://docs.rs/sha-1/latest/sha1/ + technology: + - rust + category: security + cwe: "CWE-328: Use of Weak Hash" + confidence: HIGH + likelihood: LOW + impact: MEDIUM + subcategory: audit + languages: [rust] + severity: WARNING diff --git a/.github/security-rules/rust__lang__security__reqwest-accept-invalid.yml b/.github/security-rules/rust__lang__security__reqwest-accept-invalid.yml new file mode 100644 index 0000000..c11f815 --- /dev/null +++ b/.github/security-rules/rust__lang__security__reqwest-accept-invalid.yml @@ -0,0 +1,20 @@ +rules: + - id: reqwest-accept-invalid + message: Dangerously accepting invalid TLS information + pattern-either: + - pattern: reqwest::Client::builder(). ... .danger_accept_invalid_hostnames(true) + - pattern: reqwest::Client::builder(). ... .danger_accept_invalid_certs(true) + metadata: + references: + - https://docs.rs/reqwest/latest/reqwest/struct.ClientBuilder.html#method.danger_accept_invalid_hostnames + - https://docs.rs/reqwest/latest/reqwest/struct.ClientBuilder.html#method.danger_accept_invalid_certs + technology: + - reqwest + category: security + cwe: "CWE-295: Improper Certificate Validation" + confidence: HIGH + likelihood: LOW + impact: MEDIUM + subcategory: vuln + languages: [rust] + severity: WARNING diff --git a/.github/security-rules/rust__lang__security__reqwest-set-sensitive.yml b/.github/security-rules/rust__lang__security__reqwest-set-sensitive.yml new file mode 100644 index 0000000..13a929e --- /dev/null +++ b/.github/security-rules/rust__lang__security__reqwest-set-sensitive.yml @@ -0,0 +1,44 @@ +rules: + - id: reqwest-set-sensitive + message: Set sensitive flag on security headers with 'set_sensitive' to treat data with special care + patterns: + - pattern: | + let mut $HEADERS = header::HeaderMap::new(); + ... + let $HEADER_VALUE = <... header::HeaderValue::$FROM_FUNC(...) ...>; + ... + $HEADERS.insert($HEADER, $HEADER_VALUE); + - pattern-not: | + let mut $HEADERS = header::HeaderMap::new(); + ... + let $HEADER_VALUE = <... header::HeaderValue::$FROM_FUNC(...) ...>; + ... + $HEADER_VALUE.set_sensitive(true); + ... + $HEADERS.insert($HEADER, $HEADER_VALUE); + - metavariable-pattern: + metavariable: $FROM_FUNC + pattern-either: + - pattern: from_static + - pattern: from_str + - pattern: from_name + - pattern: from_bytes + - pattern: from_maybe_shared + - metavariable-pattern: + metavariable: $HEADER + pattern-either: + - pattern: header::AUTHORIZATION + - pattern: '"Authorization"' + metadata: + references: + - https://docs.rs/reqwest/latest/reqwest/header/struct.HeaderValue.html#method.set_sensitive + technology: + - reqwest + category: security + cwe: "CWE-921: Storage of Sensitive Data in a Mechanism without Access Control" + confidence: MEDIUM + likelihood: LOW + impact: LOW + subcategory: audit + languages: [rust] + severity: INFO diff --git a/.github/security-rules/rust__lang__security__rustls-dangerous.yml b/.github/security-rules/rust__lang__security__rustls-dangerous.yml new file mode 100644 index 0000000..4f36e82 --- /dev/null +++ b/.github/security-rules/rust__lang__security__rustls-dangerous.yml @@ -0,0 +1,24 @@ +rules: + - id: rustls-dangerous + message: Dangerous client config used, ensure SSL verification + pattern-either: + - pattern: "rustls::client::DangerousClientConfig" + - pattern: "$CLIENT.dangerous().set_certificate_verifier(...)" + - pattern: | + let $CLIENT = rustls::client::ClientConfig::dangerous(...); + ... + $CLIENT.set_certificate_verifier(...); + metadata: + references: + - https://docs.rs/rustls/latest/rustls/client/struct.DangerousClientConfig.html + - https://docs.rs/rustls/latest/rustls/client/struct.ClientConfig.html#method.dangerous + technology: + - rustls + category: security + cwe: "CWE-295: Improper Certificate Validation" + confidence: HIGH + likelihood: LOW + impact: MEDIUM + subcategory: vuln + languages: [rust] + severity: WARNING diff --git a/.github/security-rules/rust__lang__security__ssl-verify-none.yml b/.github/security-rules/rust__lang__security__ssl-verify-none.yml new file mode 100644 index 0000000..15925a2 --- /dev/null +++ b/.github/security-rules/rust__lang__security__ssl-verify-none.yml @@ -0,0 +1,17 @@ +rules: + - id: ssl-verify-none + message: SSL verification disabled, this allows for MitM attacks + pattern: "$BUILDER.set_verify(openssl::ssl::SSL_VERIFY_NONE)" + metadata: + references: + - https://docs.rs/openssl/latest/openssl/ssl/struct.SslContextBuilder.html#method.set_verify + technology: + - openssl + category: security + cwe: "CWE-295: Improper Certificate Validation" + confidence: HIGH + likelihood: LOW + impact: MEDIUM + subcategory: vuln + languages: [rust] + severity: WARNING diff --git a/.github/security-rules/rust__lang__security__temp-dir.yml b/.github/security-rules/rust__lang__security__temp-dir.yml new file mode 100644 index 0000000..6333999 --- /dev/null +++ b/.github/security-rules/rust__lang__security__temp-dir.yml @@ -0,0 +1,23 @@ +rules: + - id: temp-dir + message: >- + temp_dir should not be used for security operations. From the docs: + 'The temporary directory may be shared among users, or between processes + with different privileges; thus, the creation of any files or directories + in the temporary directory must use a secure method to create a uniquely + named file. Creating a file or directory with a fixed or predictable name + may result in “insecure temporary file” security vulnerabilities.' + pattern: "std::env::temp_dir()" + metadata: + references: + - https://doc.rust-lang.org/stable/std/env/fn.temp_dir.html + technology: + - rust + category: security + cwe: "CWE-807: Reliance on Untrusted Inputs in a Security Decision" + confidence: HIGH + likelihood: LOW + impact: LOW + subcategory: audit + languages: [rust] + severity: INFO diff --git a/.github/security-rules/rust__lang__security__unsafe-usage.yml b/.github/security-rules/rust__lang__security__unsafe-usage.yml new file mode 100644 index 0000000..99b876e --- /dev/null +++ b/.github/security-rules/rust__lang__security__unsafe-usage.yml @@ -0,0 +1,17 @@ +rules: + - id: unsafe-usage + message: Detected 'unsafe' usage, please audit for secure usage + pattern: "unsafe { ... }" + metadata: + references: + - https://doc.rust-lang.org/std/keyword.unsafe.html + technology: + - rust + category: security + cwe: "CWE-242: Use of Inherently Dangerous Function" + confidence: HIGH + likelihood: LOW + impact: LOW + subcategory: audit + languages: [rust] + severity: INFO diff --git a/.github/security-rules/typescript__react__security__audit__react-dangerouslysetinnerhtml.yaml b/.github/security-rules/typescript__react__security__audit__react-dangerouslysetinnerhtml.yaml new file mode 100644 index 0000000..06c26cc --- /dev/null +++ b/.github/security-rules/typescript__react__security__audit__react-dangerouslysetinnerhtml.yaml @@ -0,0 +1,147 @@ +rules: +- id: react-dangerouslysetinnerhtml + message: >- + Detection of dangerouslySetInnerHTML from non-constant definition. This + can inadvertently expose users to cross-site scripting (XSS) attacks if + this comes from user-provided input. If you have to use + dangerouslySetInnerHTML, consider using a sanitization library such as + DOMPurify to sanitize your HTML. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + - A05:2025 - Injection + references: + - https://react.dev/reference/react-dom/components/common#dangerously-setting-the-inner-html + category: security + confidence: MEDIUM + technology: + - react + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + languages: + - typescript + - javascript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + function ...({..., $X, ...}) { ... } + - pattern-inside: | + function ...(..., $X, ...) { ... } + - focus-metavariable: $X + # Added to remove value.map which causes a fair amount of false positives + - pattern-not-inside: | + $F. ... .$SANITIZEUNC(...) + pattern-sinks: + - patterns: + - focus-metavariable: $X + - pattern-either: + - pattern: | + {...,dangerouslySetInnerHTML: {__html: $X},...} + - pattern: | + <$Y ... dangerouslySetInnerHTML={{__html: $X}} /> + - pattern-not: | + <$Y ... dangerouslySetInnerHTML={{__html: "..."}} /> + - pattern-not: | + {...,dangerouslySetInnerHTML:{__html: "..."},...} + - metavariable-pattern: + patterns: + - pattern-not: | + {...} + metavariable: $X + - pattern-not: | + <... {__html: "..."} ...> + - pattern-not: | + <... {__html: `...`} ...> + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + import * as $S from "underscore.string" + ... + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + $S = require("underscore.string") + ... + - pattern-either: + - pattern: $S.escapeHTML(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "dompurify" + ... + - pattern-inside: | + import { ..., $S,... } from "dompurify" + ... + - pattern-inside: | + import * as $S from "dompurify" + ... + - pattern-inside: | + $S = require("dompurify") + ... + - pattern-inside: | + import $S from "isomorphic-dompurify" + ... + - pattern-inside: | + import * as $S from "isomorphic-dompurify" + ... + - pattern-inside: | + $S = require("isomorphic-dompurify") + ... + - pattern-either: + - patterns: + - pattern-inside: | + $VALUE = $S(...) + ... + - pattern: $VALUE.sanitize(...) + - patterns: + - pattern-inside: | + $VALUE = $S.sanitize + ... + - pattern: $S(...) + - pattern: $S.sanitize(...) + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'xss'; + ... + - pattern-inside: | + import * as $S from 'xss'; + ... + - pattern-inside: | + $S = require("xss") + ... + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'sanitize-html'; + ... + - pattern-inside: | + import * as $S from "sanitize-html"; + ... + - pattern-inside: | + $S = require("sanitize-html") + ... + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + $S = new Remarkable() + ... + - pattern: $S.render(...) diff --git a/.github/security-rules/typescript__react__security__audit__react-href-var.yaml b/.github/security-rules/typescript__react__security__audit__react-href-var.yaml new file mode 100644 index 0000000..eb68e56 --- /dev/null +++ b/.github/security-rules/typescript__react__security__audit__react-href-var.yaml @@ -0,0 +1,90 @@ +rules: + - id: react-href-var + message: >- + Detected a variable used in an anchor tag with the 'href' attribute. A + malicious actor may be able to input the 'javascript:' URI, which could + cause cross-site scripting (XSS). It is recommended to disallow + 'javascript:' URIs within your application. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation + ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + - A05:2025 - Injection + references: + - https://reactjs.org/blog/2019/08/08/react-v16.9.0.html#deprecating-javascript-urls + - https://pragmaticwebsecurity.com/articles/spasecurity/react-xss-part1.html + category: security + confidence: LOW + technology: + - react + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: MEDIUM + languages: + - typescript + - javascript + severity: WARNING + mode: taint + pattern-sources: + - label: TAINTED + patterns: + - pattern-either: + - pattern-inside: | + function ...({..., $X, ...}) { ... } + - pattern-inside: | + function ...(..., $X, ...) { ... } + - focus-metavariable: $X + # This rule causes too many false positives without this addition + - pattern-either: + - pattern: $X.$Y + - pattern: $X[...] + # this removes .map(...) etc which likely comes from hard coded values. + - pattern-not-inside: | + $F. ... .$SANITIZEUNC(...) + - label: CONCAT + requires: TAINTED + patterns: + - pattern-either: + - pattern: | + `...${$X}...` + - pattern: | + $SANITIZE + <... $X ...> + - pattern-not: | + `${$X}...` + - pattern-not: | + $X + ... + - focus-metavariable: $X + - label: CLEAN + by-side-effect: true + patterns: + - pattern-either: + - pattern: $A($SOURCE) + - pattern: $SANITIZE. ... .$A($SOURCE) + - pattern: $A. ... .$SANITIZE($SOURCE) + - focus-metavariable: $SOURCE + - metavariable-regex: + metavariable: $A + regex: (?i)(.*valid|.*sanitiz) + pattern-sinks: + - requires: TAINTED and not CONCAT and not CLEAN + patterns: + - focus-metavariable: $X + - pattern-either: + - pattern: | + <$EL href={$X} /> + - pattern: | + React.createElement($EL, {href: $X}) + - pattern-inside: | + $PARAMS = {href: $X}; + ... + React.createElement($EL, $PARAMS); + - metavariable-pattern: + patterns: + - pattern-not-regex: (?i)(button) + metavariable: $EL diff --git a/.github/security-rules/typescript__react__security__audit__react-jwt-decoded-property.yaml b/.github/security-rules/typescript__react__security__audit__react-jwt-decoded-property.yaml new file mode 100644 index 0000000..4b9ba27 --- /dev/null +++ b/.github/security-rules/typescript__react__security__audit__react-jwt-decoded-property.yaml @@ -0,0 +1,32 @@ +rules: +- id: react-jwt-decoded-property + message: >- + Property decoded from JWT token without verifying and cannot be trustworthy. + metadata: + cwe: + - 'CWE-922: Insecure Storage of Sensitive Information' + references: + - https://pragmaticwebsecurity.com/articles/oauthoidc/localstorage-xss.html + category: security + owasp: + - A01:2021 - Broken Access Control + - A01:2025 - Broken Access Control + technology: + - react + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - typescript + - javascript + severity: INFO + patterns: + - pattern-inside: | + import jwt_decode from "jwt-decode"; + ... + - pattern-inside: | + $DECODED = jwt_decode($TOKEN,...); + ... + - pattern: $DECODED.$PROPERTY diff --git a/.github/security-rules/typescript__react__security__audit__react-jwt-in-localstorage.yaml b/.github/security-rules/typescript__react__security__audit__react-jwt-in-localstorage.yaml new file mode 100644 index 0000000..c4b4bfe --- /dev/null +++ b/.github/security-rules/typescript__react__security__audit__react-jwt-in-localstorage.yaml @@ -0,0 +1,38 @@ +rules: +- id: react-jwt-in-localstorage + message: >- + Storing JWT tokens in localStorage known to be a bad practice, consider moving your tokens from localStorage + to a HTTP cookie. + metadata: + cwe: + - 'CWE-922: Insecure Storage of Sensitive Information' + references: + - https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies + category: security + owasp: + - A01:2021 - Broken Access Control + - A01:2025 - Broken Access Control + technology: + - react + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - typescript + - javascript + severity: INFO + patterns: + - pattern-inside: | + import jwt_decode from "jwt-decode"; + ... + - pattern-either: + - pattern: | + $DECODED = jwt_decode($TOKEN,...); + ... + localStorage.setItem($NAME, <... $TOKEN ...>); + - pattern: | + $DECODED = jwt_decode(...); + ... + localStorage.setItem($NAME, <... $DECODED ...>); diff --git a/.github/security-rules/typescript__react__security__audit__react-unsanitized-method.yaml b/.github/security-rules/typescript__react__security__audit__react-unsanitized-method.yaml new file mode 100644 index 0000000..245d72d --- /dev/null +++ b/.github/security-rules/typescript__react__security__audit__react-unsanitized-method.yaml @@ -0,0 +1,148 @@ +rules: +- id: react-unsanitized-method + message: >- + Detection of $HTML from non-constant definition. This + can inadvertently expose users to cross-site scripting (XSS) attacks if this + comes from user-provided input. If you have to use $HTML, + consider using a sanitization library such as DOMPurify to sanitize your HTML. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + - A05:2025 - Injection + references: + - https://developer.mozilla.org/en-US/docs/Web/API/Document/writeln + - https://developer.mozilla.org/en-US/docs/Web/API/Document/write + - https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML + category: security + confidence: MEDIUM + technology: + - react + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: HIGH + impact: MEDIUM + languages: + - typescript + - javascript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + function ...({..., $X, ...}) { ... } + - pattern-inside: | + function ...(..., $X, ...) { ... } + - focus-metavariable: $X + - pattern-either: + - pattern: $X.$Y + - pattern: $X[...] + pattern-sinks: + - patterns: + - pattern-either: + - pattern: | + this.window.document. ... .$HTML('...',$SINK) + - pattern: | + window.document. ... .$HTML('...',$SINK) + - pattern: | + document.$HTML($SINK) + - metavariable-regex: + metavariable: $HTML + regex: (writeln|write) + - focus-metavariable: $SINK + - patterns: + - pattern-either: + - pattern: | + $PROP. ... .$HTML('...',$SINK) + - metavariable-regex: + metavariable: $HTML + regex: (insertAdjacentHTML) + - focus-metavariable: $SINK + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + import * as $S from "underscore.string" + ... + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + $S = require("underscore.string") + ... + - pattern-either: + - pattern: $S.escapeHTML(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "dompurify" + ... + - pattern-inside: | + import { ..., $S,... } from "dompurify" + ... + - pattern-inside: | + import * as $S from "dompurify" + ... + - pattern-inside: | + $S = require("dompurify") + ... + - pattern-inside: | + import $S from "isomorphic-dompurify" + ... + - pattern-inside: | + import * as $S from "isomorphic-dompurify" + ... + - pattern-inside: | + $S = require("isomorphic-dompurify") + ... + - pattern-either: + - patterns: + - pattern-inside: | + $VALUE = $S(...) + ... + - pattern: $VALUE.sanitize(...) + - patterns: + - pattern-inside: | + $VALUE = $S.sanitize + ... + - pattern: $S(...) + - pattern: $S.sanitize(...) + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'xss'; + ... + - pattern-inside: | + import * as $S from 'xss'; + ... + - pattern-inside: | + $S = require("xss") + ... + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'sanitize-html'; + ... + - pattern-inside: | + import * as $S from "sanitize-html"; + ... + - pattern-inside: | + $S = require("sanitize-html") + ... + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + $S = new Remarkable() + ... + - pattern: $S.render(...) diff --git a/.github/security-rules/typescript__react__security__audit__react-unsanitized-property.yaml b/.github/security-rules/typescript__react__security__audit__react-unsanitized-property.yaml new file mode 100644 index 0000000..555f2d3 --- /dev/null +++ b/.github/security-rules/typescript__react__security__audit__react-unsanitized-property.yaml @@ -0,0 +1,162 @@ +rules: +- id: react-unsanitized-property + message: >- + Detection of $HTML from non-constant definition. This + can inadvertently expose users to cross-site scripting (XSS) attacks if this + comes from user-provided input. If you have to use $HTML, consider using + a sanitization library such as DOMPurify to sanitize your HTML. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + - A05:2025 - Injection + references: + - https://react.dev/reference/react-dom/components/common#dangerously-setting-the-inner-html + category: security + confidence: MEDIUM + technology: + - react + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - vuln + likelihood: MEDIUM + impact: MEDIUM + languages: + - typescript + - javascript + severity: WARNING + mode: taint + pattern-sources: + - patterns: + - pattern-either: + - pattern-inside: | + function ...({..., $X, ...}) { ... } + - pattern-inside: | + function ...(..., $X, ...) { ... } + - focus-metavariable: $X + - pattern-either: + - pattern: $X.$Y + - pattern: $X[...] + pattern-sinks: + - patterns: + - pattern-either: + - pattern-inside: | + $BODY = $REACT.useRef(...) + ... + - pattern-inside: | + $BODY = useRef(...) + ... + - pattern-inside: | + $BODY = findDOMNode(...) + ... + - pattern-inside: | + $BODY = createRef(...) + ... + - pattern-inside: | + $BODY = $REACT.findDOMNode(...) + ... + - pattern-inside: | + $BODY = $REACT.createRef(...) + ... + - pattern-either: + - pattern: | + $BODY. ... .$HTML = $SINK + - pattern: | + $BODY.$HTML = $SINK + - metavariable-regex: + metavariable: $HTML + regex: (innerHTML|outerHTML) + - focus-metavariable: $SINK + - patterns: + - pattern-either: + - pattern: ReactDOM.findDOMNode(...).$HTML = $SINK + - metavariable-regex: + metavariable: $HTML + regex: (innerHTML|outerHTML) + - focus-metavariable: $SINK + pattern-sanitizers: + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + import * as $S from "underscore.string" + ... + - pattern-inside: | + import $S from "underscore.string" + ... + - pattern-inside: | + $S = require("underscore.string") + ... + - pattern-either: + - pattern: $S.escapeHTML(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from "dompurify" + ... + - pattern-inside: | + import { ..., $S,... } from "dompurify" + ... + - pattern-inside: | + import * as $S from "dompurify" + ... + - pattern-inside: | + $S = require("dompurify") + ... + - pattern-inside: | + import $S from "isomorphic-dompurify" + ... + - pattern-inside: | + import * as $S from "isomorphic-dompurify" + ... + - pattern-inside: | + $S = require("isomorphic-dompurify") + ... + - pattern-either: + - patterns: + - pattern-inside: | + $VALUE = $S(...) + ... + - pattern: $VALUE.sanitize(...) + - patterns: + - pattern-inside: | + $VALUE = $S.sanitize + ... + - pattern: $S(...) + - pattern: $S.sanitize(...) + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'xss'; + ... + - pattern-inside: | + import * as $S from 'xss'; + ... + - pattern-inside: | + $S = require("xss") + ... + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + import $S from 'sanitize-html'; + ... + - pattern-inside: | + import * as $S from "sanitize-html"; + ... + - pattern-inside: | + $S = require("sanitize-html") + ... + - pattern: $S(...) + - patterns: + - pattern-either: + - pattern-inside: | + $S = new Remarkable() + ... + - pattern: $S.render(...) diff --git a/.github/security-rules/typescript__react__security__react-insecure-request.yaml b/.github/security-rules/typescript__react__security__react-insecure-request.yaml new file mode 100644 index 0000000..94fbe9d --- /dev/null +++ b/.github/security-rules/typescript__react__security__react-insecure-request.yaml @@ -0,0 +1,62 @@ +rules: +- id: react-insecure-request + message: >- + Unencrypted request over HTTP detected. + metadata: + vulnerability: Insecure Transport + owasp: + - A03:2017 - Sensitive Data Exposure + - A02:2021 - Cryptographic Failures + - A04:2025 - Cryptographic Failures + cwe: + - 'CWE-319: Cleartext Transmission of Sensitive Information' + references: + - https://www.npmjs.com/package/axios + category: security + technology: + - react + subcategory: + - vuln + likelihood: LOW + impact: MEDIUM + confidence: MEDIUM + languages: + - typescript + - javascript + severity: ERROR + patterns: + - pattern-either: + - patterns: + - pattern-either: + - pattern-inside: | + import $AXIOS from 'axios'; + ... + $AXIOS.$METHOD(...) + - pattern-inside: | + $AXIOS = require('axios'); + ... + $AXIOS.$METHOD(...) + - pattern: $AXIOS.$VERB("$URL",...) + - metavariable-regex: + metavariable: $VERB + regex: ^(get|post|delete|head|patch|put|options) + - patterns: + - pattern-either: + - pattern-inside: | + import $AXIOS from 'axios'; + ... + $AXIOS(...) + - pattern-inside: | + $AXIOS = require('axios'); + ... + $AXIOS(...) + - pattern-either: + - pattern: '$AXIOS({url: "$URL"}, ...)' + - pattern: | + $OPTS = {url: "$URL"} + ... + $AXIOS($OPTS, ...) + - pattern: fetch("$URL", ...) + - metavariable-regex: + metavariable: $URL + regex: ^([Hh][Tt][Tt][Pp]:\/\/(?!localhost).*) diff --git a/.github/security-rules/typescript__react__security__react-markdown-insecure-html.yaml b/.github/security-rules/typescript__react__security__react-markdown-insecure-html.yaml new file mode 100644 index 0000000..df5cb6f --- /dev/null +++ b/.github/security-rules/typescript__react__security__react-markdown-insecure-html.yaml @@ -0,0 +1,51 @@ +rules: +- id: react-markdown-insecure-html + message: >- + Overwriting `transformLinkUri` or `transformImageUri` to something insecure, or turning `allowDangerousHtml` + on, or turning `escapeHtml` off, will open the code up to XSS vectors. + metadata: + cwe: + - "CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')" + owasp: + - A07:2017 - Cross-Site Scripting (XSS) + - A03:2021 - Injection + - A05:2025 - Injection + references: + - https://www.npmjs.com/package/react-markdown#security + category: security + technology: + - react + cwe2022-top25: true + cwe2021-top25: true + subcategory: + - audit + likelihood: LOW + impact: LOW + confidence: LOW + languages: + - typescript + - javascript + severity: WARNING + patterns: + - pattern-either: + - pattern-inside: | + $X = require('react-markdown/with-html'); + ... + - pattern-inside: | + $X = require('react-markdown'); + ... + - pattern-inside: | + import 'react-markdown/with-html'; + ... + - pattern-inside: | + import 'react-markdown'; + ... + - pattern-either: + - pattern: | + <$EL allowDangerousHtml /> + - pattern: | + <$EL escapeHtml={false} /> + - pattern: | + <$EL transformLinkUri=... /> + - pattern: | + <$EL transformImageUri=... /> diff --git a/.github/semgrep-project.yml b/.github/semgrep-project.yml new file mode 100644 index 0000000..5795c9b --- /dev/null +++ b/.github/semgrep-project.yml @@ -0,0 +1,14 @@ +rules: + - id: mierkhat-sql-request-injection + languages: [typescript, javascript] + message: Request data must be passed as bound PostgreSQL values, never as SQL text. + severity: ERROR + mode: taint + pattern-sources: + - pattern: $REQ.body + - pattern: $REQ.params + - pattern: $REQ.query + pattern-sinks: + - patterns: + - pattern: $DB.query($SQL, ...) + - focus-metavariable: $SQL diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 12971e4..eb17c0a 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -5,6 +5,8 @@ on: pull_request: branches: [main] workflow_dispatch: + schedule: + - cron: "17 4 * * 1" permissions: contents: read concurrency: @@ -16,21 +18,33 @@ defaults: jobs: security: runs-on: ubuntu-24.04 - timeout-minutes: 10 + timeout-minutes: 20 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false fetch-depth: 0 - run: ./scripts/ci-security.sh + - name: Install hash-locked security analyzer + run: | + python3 -m venv /tmp/mierkhat-security + /tmp/mierkhat-security/bin/pip install --require-hashes -r .github/security-requirements.txt + - run: /tmp/mierkhat-security/bin/python scripts/check-workflows.py + - run: /tmp/mierkhat-security/bin/python -m unittest discover -s scripts -p "test_security.py" + - name: Block security findings in application source + run: /tmp/mierkhat-security/bin/python scripts/scan-security.py compatibility: runs-on: ubuntu-24.04 - timeout-minutes: 5 + timeout-minutes: 20 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - run: python3 scripts/check-compatibility.py + - run: rustup toolchain install 1.93.0 --profile minimal + - name: Install pinned RustSec auditor + run: cargo +1.93.0 install cargo-audit --version 0.22.2 --locked + - run: python3 scripts/audit-rust.py application: runs-on: ubuntu-24.04 timeout-minutes: 40 @@ -51,6 +65,7 @@ jobs: - run: ./scripts/build-guard.sh - run: cargo +1.93.0 test --workspace --locked - run: cargo +1.93.0 fmt --all --check + - run: cargo +1.93.0 clippy --workspace --all-targets --locked -- -D warnings - run: python3 scripts/verify-artifacts.py - run: git diff --exit-code -- evidence/upstream-build.json - name: Package verified contract artifacts diff --git a/.semgrepignore b/.semgrepignore new file mode 100644 index 0000000..78b9256 --- /dev/null +++ b/.semgrepignore @@ -0,0 +1,13 @@ +node_modules/ +.tooling/ +dist/ +target/ +upstream/ +artifacts/ +evidence/ +fixtures/ +tests/ +test/ +**/*.test.ts +sdk/src/generated/ +.github/security-rules/ diff --git a/docs/CI_SECURITY.md b/docs/CI_SECURITY.md new file mode 100644 index 0000000..b9a34f4 --- /dev/null +++ b/docs/CI_SECURITY.md @@ -0,0 +1,17 @@ +# PR validation and security maintenance + +Every PR to main must pass the aggregate `CI` check, comprising mandatory application, compatibility and security jobs. Main protection additionally requires a current approving code-owner review and resolved conversations. Administrators are included. Workflow, source, dependency, test and security-policy changes require owner review; a PR author cannot supply their own required approval. + +Validation has read-only contents permissions, credential-free checkout, no deployment environment or secret references, and immutable Action commits. The parsed workflow policy and its mutation tests reject privileged triggers, token escalation, secret access (including bracket syntax), conditional validation, mutable Actions and suppressed failures. The aggregate check fails if any validation job fails or is skipped. + +The security job scans Git history with redacted Gitleaks, runs Actionlint, and installs Semgrep 1.183.0 plus PyYAML from a transitive hash-locked requirements file. Forty local rules (39 official Semgrep rules plus the project request-to-SQL taint rule) run with findings and parse errors blocking CI. Vendored upstream rules are bound to their recorded commit and checked SHA-256 inventory. Regression fixtures prove the real analyzer rejects SQL injection and eval. To update tooling, edit `.github/security-requirements.in`, generate hashes with `uv pip compile --generate-hashes --python-version 3.12`, and review the resulting lock. Updates to upstream rules require refreshed provenance and review. + +SAST covers shipped source: application/API, SDK, React embed/copy modules, and guard/migration Rust sources as applicable. Test fixtures, diagnostic/asset-generation scripts, generated SDK ABI files, build outputs and vendored upstream artifacts are excluded from application SAST. Scripts remain covered by owner review, secret scanning and the appropriate existing type/workflow checks. Semgrep cannot parse the SDK's type-namespace barrel syntax: `scripts/scan-security.py` first proves that the excluded `sdk/src/index.ts`, when present, contains only local re-exports. Any executable addition or external export fails closed. No SDK runtime source or archive is rewritten for this workaround. + +A weekly Monday audit reruns the complete workflow on main. Deployment runs only after CI on trusted main push/manual dispatch, with the protected production environment. Scheduled and PR runs cannot deploy. Frozen dependency installs, full JS dependency audits at high severity (including development/build dependencies), and npm/Cargo and security-tooling pip Dependabot updates keep the build supply chain under review. A passing pipeline is evidence from these checks; financial/authentication changes still need qualified human security review and existing release acceptance. + +## Rust advisories and real-WASM invariants + +Pinned cargo-audit 0.22.2 audits the complete lockfile. `.github/rustsec-native-host.json` temporarily excepts only RUSTSEC-2026-0387 / crypto-bigint 0.5.5, used by the Soroban 29.0.1 native test host through elliptic-curve / k256 / p256. The patched major cannot be substituted compatibly into the pinned SDK. Every run proves neither crypto-bigint nor soroban-env-host appears in either deployed contract's normal wasm32v1-none dependency graph. Fixtures use mocked authorization and public verification inputs, with no production secret scalar operations. The exception expires on 2027-01-01 and fails closed: any other advisory/version, guest-graph exposure, expiry or removal of the original finding requires resolution/review. No unrestricted cargo-audit ignore option is used. RustSec's unmaintained paste 1.0.15 notice remains visible as upstream maintenance debt; unsoundness warnings fail. + +Clippy runs on every workspace target with warnings denied. Narrow allowances preserve the existing event ABI and imported upstream ABI argument counts. Deployed guard and migration WASM hashes remain verified. Nineteen compiled-WASM tests include a deterministic 18-case share/route sweep across rounding boundaries that measures real output, rejects minimum output + 1 with a full ledger rollback, rejects neighboring-share authority, accepts the exact bound, reconciles balances and rejects replay without ledger changes. Existing migration remainder/refund and destination rollback tests remain mandatory. diff --git a/evidence/host-fixture.json b/evidence/host-fixture.json index 1cbae35..a564316 100644 --- a/evidence/host-fixture.json +++ b/evidence/host-fixture.json @@ -1,7 +1,7 @@ { "kind": "strict owner mock host fixture, not a signed ledger transaction", - "profile_xdr_hex": "0000001100000001000000090000000f0000000661737365747300000000001000000001000000020000001100000001000000020000000f0000000561737365740000000000001200000001692c360a04a982db02db346a106cbf008ad9e058c384bdaaf77bc0c48799b3a40000000f00000004706169720000001000000001000000010000001100000001000000020000000f0000000761646472657373000000001200000001981a6ce176706d05ae858b8d9c794e0cf4a715deb4500b2f2c6a11d101dbf33c0000000f000000097761736d5f686173680000000000000d00000020aae8760f5eebdfefa66914cf98e4cf945f9bac4aa8e5613d4e9e2d423a438d8a0000001100000001000000020000000f00000005617373657400000000000012000000018011bbf4cdf04e5bc6ac886935b99aa4b2c0cabde133f9d7fb3e656799f0a8960000000f00000004706169720000001000000001000000010000001100000001000000020000000f00000007616464726573730000000012000000019c74720908493975fe2f34cdd72cfb471e08942783d73f239fcb73d5094caa240000000f000000097761736d5f686173680000000000000d00000020aae8760f5eebdfefa66914cf98e4cf945f9bac4aa8e5613d4e9e2d423a438d8a0000000f00000007666163746f7279000000001100000001000000020000000f0000000761646472657373000000001200000001facd71593a1ade7b222082db614868109345dcb4f2d3504893f28c533905872f0000000f000000097761736d5f686173680000000000000d0000002093ff0f4a634feceae6fb21b587b9508b58cbce8100da2eed0f53601ecf0533a60000000f0000000b6d61785f6c6564676572730000000003000000400000000f0000000b6d61785f7365636f6e64730000000005000000000000012c0000000f0000000a6e6574776f726b5f696400000000000d0000002000000000000000000000000000000000000000000000000000000000000000000000000f00000006726f7574657200000000001100000001000000020000000f0000000761646472657373000000001200000001eea84deb18cbc8858910a66aeaf0e70624bb1fbe72a790692aa1320a53c1c2e40000000f000000097761736d5f686173680000000000000d00000020394539a70060065116930cdbb5d301f299621025985ba9693c7e58142e6425390000000f00000006736368656d61000000000003000000010000000f0000000a736574746c656d656e7400000000001200000001d63a954726751a876d37290072af1ee723d7d761eec3bf4191849d2116acdc730000000f000000057661756c740000000000001100000001000000020000000f0000000761646472657373000000001200000001bd892df8929d9c9612c3b74b63d537725506f87546b03be2acb5e864052c7c0b0000000f000000097761736d5f686173680000000000000d00000020e2786bd6693a117ec0d9c4acfab940d74a99687ea26e5273342adbd802a68dd9", - "intent_xdr_hex": "00000011000000010000000d0000000f0000000567756172640000000000001200000001c2d19c159e597830b2d18295722149411a1710c8ad9cdb015a4d7cac3d54c8d70000000f00000009696e74656e745f69640000000000000d0000002007070707070707070707070707070707070707070707070707070707070707070000000f0000000b6d696e5f72656365697665000000000a000000000000000000000000000000010000000f000000086d696e5f737761700000001000000001000000020000000a000000000000000000000000000000010000000a000000000000000000000000000000010000000f0000000c6d696e5f77697468647261770000001000000001000000020000000a000000000000000000000000000000010000000a000000000000000000000000000000010000000f0000000a6e6574776f726b5f696400000000000d0000002000000000000000000000000000000000000000000000000000000000000000000000000f000000056f776e6572000000000000120000000100000000000000000000000000000000000000000000000000000000000000020000000f0000000c70726f66696c655f686173680000000d00000020685da37bd958dad174d23e37b6d74549043df3f0cbc5735106a936eec86c7bb20000000f00000009726563697069656e74000000000000120000000100000000000000000000000000000000000000000000000000000000000000020000000f00000006736368656d61000000000003000000010000000f0000000673686172657300000000000a0000000000000000000000003b9aca000000000f0000001376616c69645f6265666f72655f6c656467657200000000030000007c0000000f0000001176616c69645f6265666f72655f74696d65000000000000050000000000000460", - "receipt_xdr_hex": "00000011000000010000000a0000000f0000000b696e74656e745f68617368000000000d0000002004c8d4c2d89c62afd91569f73267145fcfcde342f51593a936f5f3abba5bcf840000000f00000009696e74656e745f69640000000000000d0000002007070707070707070707070707070707070707070707070707070707070707070000000f000000066c6564676572000000000003000000640000000f000000056f776e6572000000000000120000000100000000000000000000000000000000000000000000000000000000000000020000000f0000000c70726f66696c655f686173680000000d00000020685da37bd958dad174d23e37b6d74549043df3f0cbc5735106a936eec86c7bb20000000f0000000872656365697665640000000a0000000000000000000000003b218d4e0000000f0000000c7368617265735f7370656e740000000a0000000000000000000000003b9aca000000000f0000000b737761707065645f6f7574000000001000000001000000020000000a0000000000000000000000001d90c6a70000000a0000000000000000000000001d90c6a70000000f0000000974696d657374616d700000000000000500000000000003e80000000f0000000977697468647261776e0000000000001000000001000000020000000a0000000000000000000000001dcd65000000000a0000000000000000000000001dcd6500", - "resources_debug": "InvocationResources { instructions: 20392023, mem_bytes: 6831372, disk_read_entries: 3, memory_read_entries: 30, write_entries: 17, disk_read_bytes: 276, write_bytes: 4976, contract_events_size_bytes: 5016, persistent_rent_ledger_bytes: 646963200, persistent_entry_rent_bumps: 4, temporary_rent_ledger_bytes: 454468128, temporary_entry_rent_bumps: 2 }" + "profile_xdr_hex": "0000001100000001000000090000000f0000000661737365747300000000001000000001000000020000001100000001000000020000000f0000000561737365740000000000001200000001692c360a04a982db02db346a106cbf008ad9e058c384bdaaf77bc0c48799b3a40000000f00000004706169720000001000000001000000010000001100000001000000020000000f0000000761646472657373000000001200000001981a6ce176706d05ae858b8d9c794e0cf4a715deb4500b2f2c6a11d101dbf33c0000000f000000097761736d5f686173680000000000000d000000201f7efead432ee5b900025568b4822ca6f90b950d6ff9ce0f3092d3c456c3977c0000001100000001000000020000000f00000005617373657400000000000012000000018011bbf4cdf04e5bc6ac886935b99aa4b2c0cabde133f9d7fb3e656799f0a8960000000f00000004706169720000001000000001000000010000001100000001000000020000000f00000007616464726573730000000012000000019c74720908493975fe2f34cdd72cfb471e08942783d73f239fcb73d5094caa240000000f000000097761736d5f686173680000000000000d000000201f7efead432ee5b900025568b4822ca6f90b950d6ff9ce0f3092d3c456c3977c0000000f00000007666163746f7279000000001100000001000000020000000f0000000761646472657373000000001200000001facd71593a1ade7b222082db614868109345dcb4f2d3504893f28c533905872f0000000f000000097761736d5f686173680000000000000d00000020f5d520b2ff29807db4becb7d663f7bf6a2f88b2a1173c393aff528cea57e4c740000000f0000000b6d61785f6c6564676572730000000003000000400000000f0000000b6d61785f7365636f6e64730000000005000000000000012c0000000f0000000a6e6574776f726b5f696400000000000d0000002000000000000000000000000000000000000000000000000000000000000000000000000f00000006726f7574657200000000001100000001000000020000000f0000000761646472657373000000001200000001eea84deb18cbc8858910a66aeaf0e70624bb1fbe72a790692aa1320a53c1c2e40000000f000000097761736d5f686173680000000000000d00000020394539a70060065116930cdbb5d301f299621025985ba9693c7e58142e6425390000000f00000006736368656d61000000000003000000010000000f0000000a736574746c656d656e7400000000001200000001d63a954726751a876d37290072af1ee723d7d761eec3bf4191849d2116acdc730000000f000000057661756c740000000000001100000001000000020000000f0000000761646472657373000000001200000001bd892df8929d9c9612c3b74b63d537725506f87546b03be2acb5e864052c7c0b0000000f000000097761736d5f686173680000000000000d00000020e2786bd6693a117ec0d9c4acfab940d74a99687ea26e5273342adbd802a68dd9", + "intent_xdr_hex": "00000011000000010000000d0000000f0000000567756172640000000000001200000001c2d19c159e597830b2d18295722149411a1710c8ad9cdb015a4d7cac3d54c8d70000000f00000009696e74656e745f69640000000000000d0000002007070707070707070707070707070707070707070707070707070707070707070000000f0000000b6d696e5f72656365697665000000000a000000000000000000000000000000010000000f000000086d696e5f737761700000001000000001000000020000000a000000000000000000000000000000010000000a000000000000000000000000000000010000000f0000000c6d696e5f77697468647261770000001000000001000000020000000a000000000000000000000000000000010000000a000000000000000000000000000000010000000f0000000a6e6574776f726b5f696400000000000d0000002000000000000000000000000000000000000000000000000000000000000000000000000f000000056f776e6572000000000000120000000100000000000000000000000000000000000000000000000000000000000000020000000f0000000c70726f66696c655f686173680000000d00000020ffd40374ac49f9a60b919bfee4397784e36223555ea94f54e32fd9aa815bb2d90000000f00000009726563697069656e74000000000000120000000100000000000000000000000000000000000000000000000000000000000000020000000f00000006736368656d61000000000003000000010000000f0000000673686172657300000000000a0000000000000000000000003b9aca000000000f0000001376616c69645f6265666f72655f6c656467657200000000030000007c0000000f0000001176616c69645f6265666f72655f74696d65000000000000050000000000000460", + "receipt_xdr_hex": "00000011000000010000000a0000000f0000000b696e74656e745f68617368000000000d00000020fc59a03b581b2996a54e51d9e5bbbc4e907253ca18b83970dbaab92f179f3eb20000000f00000009696e74656e745f69640000000000000d0000002007070707070707070707070707070707070707070707070707070707070707070000000f000000066c6564676572000000000003000000640000000f000000056f776e6572000000000000120000000100000000000000000000000000000000000000000000000000000000000000020000000f0000000c70726f66696c655f686173680000000d00000020ffd40374ac49f9a60b919bfee4397784e36223555ea94f54e32fd9aa815bb2d90000000f0000000872656365697665640000000a0000000000000000000000003b218d4e0000000f0000000c7368617265735f7370656e740000000a0000000000000000000000003b9aca000000000f0000000b737761707065645f6f7574000000001000000001000000020000000a0000000000000000000000001d90c6a70000000a0000000000000000000000001d90c6a70000000f0000000974696d657374616d700000000000000500000000000003e80000000f0000000977697468647261776e0000000000001000000001000000020000000a0000000000000000000000001dcd65000000000a0000000000000000000000001dcd6500", + "resources_debug": "InvocationResources { instructions: 20391111, mem_bytes: 6831372, disk_read_entries: 3, memory_read_entries: 30, write_entries: 17, disk_read_bytes: 276, write_bytes: 4976, contract_events_size_bytes: 5016, persistent_rent_ledger_bytes: 646963200, persistent_entry_rent_bumps: 4, temporary_rent_ledger_bytes: 454468128, temporary_entry_rent_bumps: 2 }" } diff --git a/fixtures/src/tests.rs b/fixtures/src/tests.rs index 3f3f54f..ea9af09 100644 --- a/fixtures/src/tests.rs +++ b/fixtures/src/tests.rs @@ -4,12 +4,15 @@ use soroban_sdk::{ token, vec, Address, BytesN, Env, IntoVal, Map, String, Vec, }; +// Upstream ABI-generated signatures cannot be shortened locally. +#[allow(clippy::too_many_arguments)] mod vault { soroban_sdk::contractimport!(file = "../artifacts/defindex_vault.wasm"); } mod factory { soroban_sdk::contractimport!(file = "../artifacts/soroswap_factory.wasm"); } +#[allow(clippy::too_many_arguments)] mod router { soroban_sdk::contractimport!(file = "../artifacts/soroswap_router.wasm"); } @@ -40,7 +43,6 @@ fn pin(env: &Env, address: &Address, wasm: &[u8]) -> CodePin { fn fixture(settlement_underlying: bool, one_asset: bool) -> Fixture { let env = Env::new_with_config(soroban_sdk::testutils::EnvTestConfig { capture_snapshot_at_drop: false, - ..Default::default() }); env.cost_estimate().budget().reset_unlimited(); env.ledger().with_mut(|l| { @@ -433,7 +435,9 @@ fn runtime_code_pin_change_rejects_before_spending() { let f = fixture(false, false); let hash = f.env.deployer().upload_contract_wasm(router::WASM); f.env.as_contract(&f.vault, || { - f.env.deployer().update_current_contract_wasm(hash) + f.env + .deployer() + .update_current_contract(soroban_sdk::ContractExecutable::Wasm(hash)) }); authorize(&f, &f.intent); let before = f.env.to_snapshot().ledger; @@ -493,42 +497,51 @@ fn exclusive_deadlines_and_expired_marker_cannot_revive_an_intent() { ); } -#[soroban_sdk::contract] -struct AuthorizationProbe; -#[soroban_sdk::contractimpl] -impl AuthorizationProbe { - pub fn run( - env: Env, - router: Address, - input: Address, - output: Address, - pair: Address, - amount: i128, - authorized_amount: i128, - authorized_token: Address, - ) { - use soroban_sdk::auth::{ContractContext, InvokerContractAuthEntry, SubContractInvocation}; - let me = env.current_contract_address(); - env.authorize_as_current_contract(vec![ - &env, - InvokerContractAuthEntry::Contract(SubContractInvocation { - context: ContractContext { - contract: authorized_token, - fn_name: soroban_sdk::symbol_short!("transfer"), - args: (me.clone(), pair, authorized_amount).into_val(&env), - }, - sub_invocations: vec![&env], - }), - ]); - mierkhat_guard::RouterClient::new(&env, &router).swap_exact_tokens_for_tokens( - &amount, - &1, - &vec![&env, input, output], - &me, - &1120, - ); +// Only this fixed upstream-authorization probe ABI exceeds Clippy argument limits. +#[allow(clippy::too_many_arguments)] +mod authorization_probe { + use soroban_sdk::{vec, Address, Env, IntoVal}; + #[soroban_sdk::contract] + pub(super) struct AuthorizationProbe; + #[soroban_sdk::contractimpl] + impl AuthorizationProbe { + pub fn run( + env: Env, + router: Address, + input: Address, + output: Address, + pair: Address, + amount: i128, + authorized_amount: i128, + authorized_token: Address, + ) { + use soroban_sdk::auth::{ + ContractContext, InvokerContractAuthEntry, SubContractInvocation, + }; + let me = env.current_contract_address(); + env.authorize_as_current_contract(vec![ + &env, + InvokerContractAuthEntry::Contract(SubContractInvocation { + context: ContractContext { + contract: authorized_token, + fn_name: soroban_sdk::symbol_short!("transfer"), + args: (me.clone(), pair, authorized_amount).into_val(&env), + }, + sub_invocations: vec![&env], + }), + ]); + mierkhat_guard::RouterClient::new(&env, &router).swap_exact_tokens_for_tokens( + &amount, + &1, + &vec![&env, input, output], + &me, + &1120, + ); + } } } +use authorization_probe::{AuthorizationProbe, AuthorizationProbeClient}; + #[test] fn nested_transfer_authorization_rejects_wrong_amount_and_token() { let f = fixture(false, false); @@ -697,7 +710,9 @@ fn router_factory_and_each_executable_pin_change_rejects_before_spending() { }; let replacement = f.env.deployer().upload_contract_wasm(vault::WASM); f.env.as_contract(&address, || { - f.env.deployer().update_current_contract_wasm(replacement) + f.env + .deployer() + .update_current_contract(soroban_sdk::ContractExecutable::Wasm(replacement)) }); } authorize(&f, &f.intent); @@ -748,3 +763,77 @@ fn corrupted_pair_asset_state_rolls_back_all_touched_state() { } mod migrations; + +/// Bounded deterministic property sweep across rounding and position sizes, +/// executed against the same real vault/router/pair/guard WASM used in CI. +#[test] +fn varied_shares_bind_authority_minimum_rollback_and_replay() { + let quantities = [1_001i128, 9_999, 10_001, 999_999, 10_000_001, 1_000_000_003]; + for (settlement, one) in [(false, false), (true, false), (false, true)] { + for shares in quantities { + let measured = fixture(settlement, one); + let mut intent = measured.intent.clone(); + intent.shares = shares; + authorize(&measured, &intent); + let receipt = GuardClient::new(&measured.env, &measured.guard).execute_exit(&intent); + assert!(receipt.received > 0, "rounding boundary {shares}"); + assert_eq!(receipt.shares_spent, shares); + + let f = fixture(settlement, one); + let mut i = f.intent.clone(); + i.shares = shares; + i.min_receive = receipt.received + 1; + authorize(&f, &i); + let before = f.env.to_snapshot().ledger; + assert_eq!( + GuardClient::new(&f.env, &f.guard).try_execute_exit(&i), + Err(Ok(soroban_sdk::Error::from_contract_error( + Error::OutcomeBelowMinimum as u32 + ))) + ); + assert_eq!(before, f.env.to_snapshot().ledger); + + // Approval for a neighboring share count must not authorize this + // transaction, even when the same owner/route/minimum are supplied. + i.min_receive = receipt.received; + let mut neighboring = i.clone(); + neighboring.shares += 1; + authorize(&f, &neighboring); + assert!(GuardClient::new(&f.env, &f.guard) + .try_execute_exit(&i) + .is_err()); + assert_eq!(before, f.env.to_snapshot().ledger); + + authorize(&f, &i); + let shares_before = token::Client::new(&f.env, &f.vault).balance(&f.owner); + let out_before = token::Client::new(&f.env, &f.settlement).balance(&f.owner); + let exact = GuardClient::new(&f.env, &f.guard).execute_exit(&i); + assert_eq!(exact.received, receipt.received); + assert_eq!( + token::Client::new(&f.env, &f.vault).balance(&f.owner), + shares_before - shares + ); + assert_eq!( + token::Client::new(&f.env, &f.settlement).balance(&f.owner), + out_before + exact.received + ); + for asset in f + .assets + .iter() + .chain(core::iter::once(f.settlement.clone())) + .chain(core::iter::once(f.vault.clone())) + { + assert_eq!(token::Client::new(&f.env, &asset).balance(&f.guard), 0); + } + let committed = f.env.to_snapshot().ledger; + authorize(&f, &i); + assert_eq!( + GuardClient::new(&f.env, &f.guard).try_execute_exit(&i), + Err(Ok(soroban_sdk::Error::from_contract_error( + Error::AlreadyExecuted as u32 + ))) + ); + assert_eq!(committed, f.env.to_snapshot().ledger); + } + } +} diff --git a/fixtures/src/tests/migrations.rs b/fixtures/src/tests/migrations.rs index 5d8bfac..8a15ef4 100644 --- a/fixtures/src/tests/migrations.rs +++ b/fixtures/src/tests/migrations.rs @@ -259,7 +259,9 @@ fn changed_destination_code_or_strategy_rejects_before_spending() { } else { let hash = f.env.deployer().upload_contract_wasm(router::WASM); f.env.as_contract(&destination, || { - f.env.deployer().update_current_contract_wasm(hash) + f.env + .deployer() + .update_current_contract(soroban_sdk::ContractExecutable::Wasm(hash)) }); } auth(&f, &guard, &draft); diff --git a/guard/src/lib.rs b/guard/src/lib.rs index 7e7614f..19cddac 100644 --- a/guard/src/lib.rs +++ b/guard/src/lib.rs @@ -416,6 +416,8 @@ impl Guard { ledger, timestamp: now, }; + // Preserve the deployed receipt event ABI; migrate only in a separately reviewed release. + #[allow(deprecated)] env.events() .publish((Symbol::new(&env, "exit_v1"),), &receipt); receipt diff --git a/migration/src/lib.rs b/migration/src/lib.rs index 5f84cf9..2a3d5b2 100644 --- a/migration/src/lib.rs +++ b/migration/src/lib.rs @@ -313,6 +313,8 @@ fn deposit_amounts( } panic_with_error!(env, Error::DepositMismatch); } +// This reviewed asset-flow helper keeps the deployed implementation and executable unchanged. +#[allow(clippy::too_many_arguments)] fn deposit_and_refund( env: &Env, m: &MigrationProfile, @@ -727,6 +729,8 @@ impl Migration { ledger, timestamp: now, }; + // Preserve the deployed receipt event ABI; migrate only in a separately reviewed release. + #[allow(deprecated)] env.events() .publish((Symbol::new(&env, "migrate_v1"),), &receipt); receipt diff --git a/scripts/audit-rust.py b/scripts/audit-rust.py new file mode 100644 index 0000000..8a7c7be --- /dev/null +++ b/scripts/audit-rust.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +"""Audit every locked Rust dependency; enforce a narrow native-host exception.""" +from datetime import date +import json +from pathlib import Path +import subprocess + + +def validate(report, policy, graphs, today=None): + today = today or date.today() + if today >= date.fromisoformat(policy['expires']): + raise SystemExit('RustSec native-host exception expired; update upstream or review policy') + expected = ('RUSTSEC-2026-0387', 'crypto-bigint', '0.5.5') + if (policy['advisory'], policy['package'], policy['version']) != expected: + raise SystemExit('Unexpected RustSec exception scope') + if len(graphs) != 2: + raise SystemExit("Both deployed contract dependency graphs are required") + for graph in graphs: + if 'crypto-bigint ' in graph or 'soroban-env-host ' in graph: + raise SystemExit('Native-only advisory dependency present in deployed WASM graph') + vulnerabilities = report['vulnerabilities']['list'] + if report['vulnerabilities']['count'] != len(vulnerabilities): + raise SystemExit('Inconsistent RustSec report') + for entry in vulnerabilities: + actual = (entry['advisory']['id'], entry['package']['name'], entry['package']['version']) + if actual != expected: + raise SystemExit(f'Unexcepted vulnerability: {actual}') + if report.get('warnings', {}).get('unsound'): + raise SystemExit('RustSec unsoundness finding requires resolution') + if not vulnerabilities: + raise SystemExit('Advisory no longer present: remove obsolete exception') + + +if __name__ == '__main__': + policy = json.loads(Path('.github/rustsec-native-host.json').read_text()) + graphs = [subprocess.check_output(['cargo', '+1.93.0', 'tree', '--locked', '-p', package, '--target', 'wasm32v1-none', '--edges', 'normal', '--prefix', 'none'], text=True) for package in ('mierkhat-guard', 'mierkhat-migration')] + process = subprocess.run(['cargo', 'audit', '--file', 'Cargo.lock', '--json'], text=True, capture_output=True) + if process.returncode not in (0, 1): + raise SystemExit(process.stderr) + report = json.loads(process.stdout) + validate(report, policy, graphs) + print(json.dumps(report, indent=2)) + print('PASS: RustSec audit; exact temporary native-host advisory absent from both deployed WASM dependency graphs') diff --git a/scripts/check-workflows.py b/scripts/check-workflows.py new file mode 100644 index 0000000..2906658 --- /dev/null +++ b/scripts/check-workflows.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +"""Reject workflow permission and event changes that expose untrusted PR code.""" +from pathlib import Path +import re +import yaml + +# BaseLoader preserves the YAML 1.1 keyword `on` as a string. +def validate(data, path="workflow"): + if not isinstance(data, dict): + raise SystemExit(f"{path}: workflow mapping required") + events = data.get("on", {}) + if not isinstance(events, dict) or set(events) - {"push", "pull_request", "workflow_dispatch", "schedule"}: + raise SystemExit(f"{path}: unexpected workflow trigger") + if data.get("permissions") != {"contents": "read"}: + raise SystemExit(f"{path}: workflow token must have read-only contents access") + if re.search(r"\bsecrets\b", yaml.dump({k: v for k, v in data.items() if k != "jobs"})): + raise SystemExit(f"{path}: workflow-level secret access forbidden") + required = {"security", "compatibility", "application"} + jobs = data.get("jobs", {}) + if not required <= set(jobs) or jobs.get("ci", {}).get("needs") != ["security", "compatibility", "application"] or jobs["ci"].get("if") != "always()": + raise SystemExit(f"{path}: all validation jobs must feed the unconditional CI gate") + for name, job in data.get("jobs", {}).items(): + if name in required and "if" in job: + raise SystemExit(f"{path}/{name}: validation cannot be conditionally skipped") + if "permissions" in job and job["permissions"] != {"contents": "read"}: + raise SystemExit(f"{path}/{name}: elevated job permissions forbidden") + if job.get("continue-on-error") not in (None, "false"): + raise SystemExit(f"{path}/{name}: failures must block CI") + if "environment" in job and name != "production": + raise SystemExit(f"{path}/{name}: validation jobs cannot enter a credential environment") + if name == "production": + expected = "github.ref == 'refs/heads/main' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')" + if job.get("if") != expected or job.get("needs") != "ci": + raise SystemExit(f"{path}: production must follow CI only on trusted main events") + for step in job.get("steps", []): + if step.get("continue-on-error") not in (None, "false"): + raise SystemExit(f"{path}/{name}: step failures must not be suppressed") + action = step.get("uses") + if action and not re.fullmatch(r"[A-Za-z0-9_./-]+@[0-9a-f]{40}", action): + raise SystemExit(f"{path}/{name}: immutable action SHA required") + if action and action.startswith("actions/checkout@") and step.get("with", {}).get("persist-credentials") != "false": + raise SystemExit(f"{path}/{name}: checkout must not retain credentials") + text = yaml.dump(job) + if name != "production" and re.search(r"\bsecrets\b", text): + raise SystemExit(f"{path}/{name}: validation must not reference deployment secrets") +if __name__ == "__main__": + paths = list(Path(".github/workflows").glob("*.y*ml")) + if not paths: + raise SystemExit("No workflows found") + for path in paths: + validate(yaml.load(path.read_text(), Loader=yaml.BaseLoader), str(path)) + print("PASS: workflow events, permissions, action pins and secret isolation") diff --git a/scripts/scan-security.py b/scripts/scan-security.py new file mode 100644 index 0000000..dbbf6de --- /dev/null +++ b/scripts/scan-security.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +"""Strict SAST of shipped source, with an enforced export-only parser workaround.""" +import hashlib +import json +from pathlib import Path +import re +import subprocess +import sys + + +def validate_barrel(text): + # Semgrep 1.183.0 cannot parse `export type * as ...`. Only pure local + # re-exports may be excluded; adding any executable statement fails closed. + export = r'export (?:type )?\*(?: as [A-Za-z_$][\w$]*)? from "\./(?:generated/)?[A-Za-z0-9_-]+\.js";' + if not text.strip() or any(not re.fullmatch(export, line.strip()) for line in text.splitlines() if line.strip()): + raise SystemExit("SDK index parser exception permits only local re-exports") + + +def verify_rules(): + base = Path(".github/security-rules") + provenance = json.loads((base / "provenance.json").read_text()) + files = provenance["files"] + actual = {p.name for p in base.iterdir() if p.name != "provenance.json"} + if actual != set(files): + raise SystemExit("Security rule inventory differs from provenance") + for name, metadata in files.items(): + if hashlib.sha256((base / name).read_bytes()).hexdigest() != metadata["sha256"]: + raise SystemExit(f"Security rule digest mismatch: {name}") + + +if __name__ == "__main__": + verify_rules() + barrel = Path("sdk/src/index.ts") + if barrel.exists(): + validate_barrel(barrel.read_text()) + sources = [str(p) for p in map(Path, ("src", "sdk/src", "api", "embed/src", "copy/src", "guard/src", "migration/src")) if p.is_dir()] + if not sources: + raise SystemExit("No application sources found") + command = [str(Path(sys.prefix) / "bin" / "semgrep"), "scan", "--config", ".github/security-rules", "--config", ".github/semgrep-project.yml", "--error", "--strict", "--metrics", "off", "--disable-version-check", *sources] + subprocess.run(command, check=True) diff --git a/scripts/test_security.py b/scripts/test_security.py new file mode 100644 index 0000000..d6be97a --- /dev/null +++ b/scripts/test_security.py @@ -0,0 +1,83 @@ +"""Regression checks for security gate rejection, not application policy mocks.""" +import copy +import importlib.util +from pathlib import Path +import unittest +import yaml + + +def module(name): + spec = importlib.util.spec_from_file_location(name, Path(__file__).with_name(name.replace("_", "-") + ".py")) + result = importlib.util.module_from_spec(spec) + spec.loader.exec_module(result) + return result + + +class WorkflowPolicy(unittest.TestCase): + def test_current_workflow_and_reject_privilege_changes(self): + checker = module("check_workflows") + data = yaml.load(Path(".github/workflows/verify.yml").read_text(), Loader=yaml.BaseLoader) + checker.validate(data) + mutations = [ + lambda d: d.update(permissions={"contents": "write"}), + lambda d: d["on"].update(pull_request_target={}), + lambda d: d["jobs"]["security"].update(permissions={"contents": "write"}), + lambda d: d["jobs"]["security"].update(env={"KEY": "${{ secrets [ 'KEY' ] }}"}), + lambda d: d.update(env={"KEY": "${{ secrets.KEY }}"}), + lambda d: d["jobs"]["application"].update(environment="production"), + lambda d: d["jobs"]["security"].update({"continue-on-error": "true"}), + lambda d: d["jobs"]["security"].update({"if": "false"}), + lambda d: d["jobs"]["security"]["steps"][0].update(uses="actions/checkout@main"), + lambda d: d["jobs"]["security"]["steps"][0]["with"].update({"persist-credentials": "true"}), + lambda d: d["jobs"]["ci"].update(needs=["application"]), + ] + if "production" in data["jobs"]: + mutations.append(lambda d: d["jobs"]["production"].update({"if": "always()"})) + for mutate in mutations: + candidate = copy.deepcopy(data) + mutate(candidate) + with self.subTest(candidate=candidate), self.assertRaises(SystemExit): + checker.validate(candidate) + + def test_sdk_barrel_rejects_executable_or_external_export(self): + checker = module("scan_security") + checker.validate_barrel('export * from "./policy.js";\nexport type * as ContractTypes from "./generated/types.js";\n') + for candidate in ['export * from "./../scripts/evil.js";', 'export const x = eval(input);', 'export * from "https://evil.test/x.js";', 'export * from "./ok.js";\nfetch(url);']: + with self.assertRaises(SystemExit): + checker.validate_barrel(candidate) + +class RustAdvisoryPolicy(unittest.TestCase): + def test_exact_native_only_scope_and_expiry(self): + import json + from datetime import date + checker = module('audit_rust') + policy = json.loads(Path('.github/rustsec-native-host.json').read_text()) + entry = {'advisory': {'id': policy['advisory']}, 'package': {'name': policy['package'], 'version': policy['version']}} + report = {'vulnerabilities': {'list': [entry], 'count': 1}} + checker.validate(report, policy, ['soroban-env-guest v29.0.1'] * 2, date(2026, 11, 3)) + for field, value in [('id', 'RUSTSEC-9999-0001'), ('version', '0.5.6'), ('name', 'other')]: + candidate = copy.deepcopy(report) + section = 'advisory' if field == 'id' else 'package' + candidate['vulnerabilities']['list'][0][section][field] = value + with self.assertRaises(SystemExit): + checker.validate(candidate, policy, ['', ''], date(2026, 11, 3)) + with self.assertRaises(SystemExit): + checker.validate(report, policy, ['', 'crypto-bigint v0.5.5'], date(2026, 11, 3)) + with self.assertRaises(SystemExit): + checker.validate(report, policy, ['', ''], date(2027, 1, 1)) + + +class ScannerRejection(unittest.TestCase): + def test_real_analyzer_blocks_sql_and_eval(self): + import json + import subprocess + import sys + import tempfile + with tempfile.TemporaryDirectory(prefix="mierkhat-security-") as directory: + target = Path(directory) / "injection.ts" + target.write_text('function handler(req, db) { db.query(req.body.sql); eval(req.query.code); }') + result = subprocess.run([str(Path(sys.prefix) / "bin" / "semgrep"), "scan", "--config", ".github/security-rules", "--config", ".github/semgrep-project.yml", "--error", "--strict", "--metrics", "off", "--disable-version-check", "--no-git-ignore", "--json", str(target)], text=True, capture_output=True) + self.assertEqual(result.returncode, 1, result.stderr) + findings = json.loads(result.stdout)["results"] + self.assertTrue(any("mierkhat-sql-request-injection" in f["check_id"] for f in findings)) + self.assertTrue(any("eval" in f["check_id"] for f in findings))