diff --git a/.github/workflows/actions.lock b/.github/workflows/actions.lock index f366860e..e1cf8331 100644 --- a/.github/workflows/actions.lock +++ b/.github/workflows/actions.lock @@ -42,10 +42,12 @@ workflows: '.github/workflows/escript-soundness.yml': [] '.github/workflows/estate-rescan.yml': - 'actions/cache@v6.1.0' - '.github/workflows/governance.yml': [] + '.github/workflows/governance.yml': + - 'hyperpolymath/standards@333b06a01db1874ffedb2de1bfabb195640927c7' '.github/workflows/hypatia-remediation-sweep.yml': - 'actions/upload-artifact@v7.0.2' - '.github/workflows/hypatia-scan.yml': [] + '.github/workflows/hypatia-scan.yml': + - 'hyperpolymath/standards@333b06a01db1874ffedb2de1bfabb195640927c7' '.github/workflows/inbox-steward-intake.yml': - 'actions/checkout@v7.0.1' '.github/workflows/label-triage.yml': [] @@ -57,7 +59,8 @@ workflows: - 'actions/checkout@v7.0.1' - 'actions/upload-artifact@v7.0.2' - 'erlef/setup-beam@v1.24.1' - '.github/workflows/mirror.yml': [] + '.github/workflows/mirror.yml': + - 'hyperpolymath/standards@333b06a01db1874ffedb2de1bfabb195640927c7' '.github/workflows/pages.yml': - 'actions/checkout@v7.0.1' - 'actions/deploy-pages@v5.0.1' @@ -91,8 +94,10 @@ workflows: - 'actions/checkout@v7.0.1' - 'dtolnay/rust-toolchain@v1' - 'swatinem/rust-cache@v2.9.2' - '.github/workflows/scorecard.yml': [] - '.github/workflows/secret-scanner.yml': [] + '.github/workflows/scorecard.yml': + - 'hyperpolymath/standards@333b06a01db1874ffedb2de1bfabb195640927c7' + '.github/workflows/secret-scanner.yml': + - 'hyperpolymath/standards@333b06a01db1874ffedb2de1bfabb195640927c7' '.github/workflows/security-policy.yml': - 'actions/cache@v6.1.0' - 'actions/checkout@v7.0.1' @@ -140,6 +145,11 @@ dependencies: commit: 'sha1-27d5ce7f107fe9357f9df03efb73ab90386fccae' owner_id: 44036562 repo_id: 215566462 + 'actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9': + ref: 'v6.1.0' + commit: 'sha1-55cc8345863c7cc4c66a329aec7e433d2d1c52a9' + owner_id: 44036562 + repo_id: 215566462 'actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb': ref: 'v5.0.1' commit: 'sha1-9255dc7a253b0ccc959486e2bca901246202afeb' @@ -150,6 +160,11 @@ dependencies: commit: 'sha1-55cc8345863c7cc4c66a329aec7e433d2d1c52a9' owner_id: 44036562 repo_id: 215566462 + 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1': + ref: 'v7.0.1' + commit: 'sha1-3d3c42e5aac5ba805825da76410c181273ba90b1' + owner_id: 44036562 + repo_id: 197814629 'actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8': ref: 'v6.0.1' commit: 'sha1-8e8c483db84b4bee98b60c0593521ed34d9990e8' @@ -190,6 +205,11 @@ dependencies: commit: 'sha1-bbbca2ddaa5d8feaa63e36b76fdaad77386f024f' owner_id: 44036562 repo_id: 192625955 + 'actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9': + ref: 'v7.0.2' + commit: 'sha1-cf430e030ddbb5b0abf93d22962f4752f3646cd9' + owner_id: 44036562 + repo_id: 192625955 'actions/upload-artifact@v7.0.2': ref: 'v7.0.2' commit: 'sha1-cf430e030ddbb5b0abf93d22962f4752f3646cd9' @@ -218,6 +238,11 @@ dependencies: uses: - 'actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae' - 'aquasecurity/setup-trivy@3fb12ec12f41e471780db15c232d5dd185dcb514' + 'denoland/setup-deno@22d081ff2d3a40755e97629de92e3bcbfa7cf2ed': + ref: 'v2.0.5' + commit: 'sha1-22d081ff2d3a40755e97629de92e3bcbfa7cf2ed' + owner_id: 42048915 + repo_id: 356423100 'dependabot/fetch-metadata@v3.1.0': ref: 'v3.1.0' commit: 'sha1-25dd0e34f4fe68f24cc83900b1fe3fe149efef98' @@ -248,21 +273,41 @@ dependencies: commit: 'sha1-99012661954931238ded8c8b007157a8430204e1' owner_id: 5429470 repo_id: 288487894 + 'dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8': + ref: 'v1' + commit: 'sha1-683b588c487a69d01f6c6ddf40f036ff682cc2c8' + owner_id: 1940490 + repo_id: 260749683 'dtolnay/rust-toolchain@v1': ref: 'v1' commit: 'sha1-02cb101ec7c40f2c49e1d9714d64511d8e1b74de' owner_id: 1940490 repo_id: 260749683 + 'editorconfig-checker/action-editorconfig-checker@51f63319f592f97930c73d9c46184d20bd206393': + ref: 'v3.0.0' + commit: 'sha1-51f63319f592f97930c73d9c46184d20bd206393' + owner_id: 26415196 + repo_id: 297874902 'editorconfig-checker/action-editorconfig-checker@v3.0.0': ref: 'v3.0.0' commit: 'sha1-51f63319f592f97930c73d9c46184d20bd206393' owner_id: 26415196 repo_id: 297874902 + 'erlef/setup-beam@54075bcc5e249e4758d363f27d099f55d843f124': + ref: 'v1.24.1' + commit: 'sha1-54075bcc5e249e4758d363f27d099f55d843f124' + owner_id: 47606891 + repo_id: 331103973 'erlef/setup-beam@v1.24.1': ref: 'v1.24.1' commit: 'sha1-54075bcc5e249e4758d363f27d099f55d843f124' owner_id: 47606891 repo_id: 331103973 + 'github/codeql-action@b96794f015dfd88f77b49b1c93e0fa7110f94c63': + ref: 'v4.38.0' + commit: 'sha1-b96794f015dfd88f77b49b1c93e0fa7110f94c63' + owner_id: 9919 + repo_id: 259445878 'github/codeql-action@v4.38.2': ref: 'v4.38.2' commit: 'sha1-2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2' @@ -308,6 +353,33 @@ dependencies: commit: 'sha1-c1c9fa07992a02c1fd3d67a0dc1b08cccb852aef' owner_id: 6759885 repo_id: 1352485172 + 'hyperpolymath/standards@333b06a01db1874ffedb2de1bfabb195640927c7': + ref: '333b06a01db1874ffedb2de1bfabb195640927c7' + commit: 'sha1-333b06a01db1874ffedb2de1bfabb195640927c7' + owner_id: 6759885 + repo_id: 1116521501 + uses: + - 'actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9' + - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' + - 'actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9' + - 'denoland/setup-deno@22d081ff2d3a40755e97629de92e3bcbfa7cf2ed' + - 'dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8' + - 'editorconfig-checker/action-editorconfig-checker@51f63319f592f97930c73d9c46184d20bd206393' + - 'erlef/setup-beam@54075bcc5e249e4758d363f27d099f55d843f124' + - 'github/codeql-action@b96794f015dfd88f77b49b1c93e0fa7110f94c63' + - 'ossf/scorecard-action@fa7117db83c52d787ae5a89f350999701505d78e' + - 'oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6' + - 'webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555' + 'ossf/scorecard-action@fa7117db83c52d787ae5a89f350999701505d78e': + ref: 'v2.5.0' + commit: 'sha1-fa7117db83c52d787ae5a89f350999701505d78e' + owner_id: 67707773 + repo_id: 421101922 + 'oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6': + ref: 'v2.2.0' + commit: 'sha1-0c5077e51419868618aeaa5fe8019c62421857d6' + owner_id: 108928776 + repo_id: 512644635 'ruby/setup-ruby@v1.329.0': ref: 'v1.329.0' commit: 'sha1-651ff0d62c5c79bed6d53ec518387aae20e72c1a' @@ -333,3 +405,8 @@ dependencies: commit: 'sha1-e76dff8a7e57d6df0c60ad8cbf5d5cba505a8fc9' owner_id: 79229934 repo_id: 77726177 + 'webfactory/ssh-agent@e83874834305fe9a4a2997156cb26c5de65a8555': + ref: 'v0.10.0' + commit: 'sha1-e83874834305fe9a4a2997156cb26c5de65a8555' + owner_id: 135788 + repo_id: 208510314 diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml index 0bf27a56..b587d669 100644 --- a/.github/workflows/governance.yml +++ b/.github/workflows/governance.yml @@ -16,7 +16,7 @@ permissions: jobs: governance: - uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@da2c748aad55c1a1dcba00b60fe4a35017bc6540 + uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@333b06a01db1874ffedb2de1bfabb195640927c7 permissions: actions: read contents: read diff --git a/.github/workflows/hypatia-scan.yml b/.github/workflows/hypatia-scan.yml index 61c81175..c640d0f7 100644 --- a/.github/workflows/hypatia-scan.yml +++ b/.github/workflows/hypatia-scan.yml @@ -21,5 +21,6 @@ permissions: jobs: hypatia: - uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@da2c748aad55c1a1dcba00b60fe4a35017bc6540 - secrets: inherit + uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@333b06a01db1874ffedb2de1bfabb195640927c7 + secrets: + HYPATIA_SCAN_PAT: ${{ secrets.HYPATIA_SCAN_PAT }} diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index 0bd744f2..e4baabce 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -41,8 +41,15 @@ permissions: jobs: mirror: - uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@2479cf769ed5f0481ccf64860a2ab954514c2b59 - secrets: inherit + uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@333b06a01db1874ffedb2de1bfabb195640927c7 + secrets: + GITLAB_SSH_KEY: ${{ secrets.GITLAB_SSH_KEY }} + BITBUCKET_SSH_KEY: ${{ secrets.BITBUCKET_SSH_KEY }} + CODEBERG_SSH_KEY: ${{ secrets.CODEBERG_SSH_KEY }} + SOURCEHUT_SSH_KEY: ${{ secrets.SOURCEHUT_SSH_KEY }} + DISROOT_SSH_KEY: ${{ secrets.DISROOT_SSH_KEY }} + GITEA_SSH_KEY: ${{ secrets.GITEA_SSH_KEY }} + RADICLE_KEY: ${{ secrets.RADICLE_KEY }} permissions: actions: read contents: read diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 79a29fee..ed5b71a9 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -16,10 +16,9 @@ permissions: jobs: scorecard: - uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@da2c748aad55c1a1dcba00b60fe4a35017bc6540 + uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@333b06a01db1874ffedb2de1bfabb195640927c7 permissions: actions: read contents: read security-events: write id-token: write - secrets: inherit diff --git a/.github/workflows/secret-scanner.yml b/.github/workflows/secret-scanner.yml index 0dbf55c7..328f70b0 100644 --- a/.github/workflows/secret-scanner.yml +++ b/.github/workflows/secret-scanner.yml @@ -22,5 +22,4 @@ jobs: contents: read pull-requests: write actions: read - uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@571cc734cd69fb846032ec77a662aa8ee4fc32cd - secrets: inherit + uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@333b06a01db1874ffedb2de1bfabb195640927c7 diff --git a/.gitleaksignore b/.gitleaksignore new file mode 100644 index 00000000..46f630f4 --- /dev/null +++ b/.gitleaksignore @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: MPL-2.0 +# Historical false positives, scoped to these exact commit/path/rule/line findings. +# Prometheus recording-rule identifier for API latency, not a credential. +269dac03d57835a1dfe3fb336095ffac61567ccf:deploy/terraform/modules/monitoring/main.tf:generic-api-key:421 +# Kubernetes template values all decode to the literal CHANGE_ME_IN_PRODUCTION. +0d310faa0d74da36faa8f5cfb5b6786ebe912c1b:deploy/k8s/secrets.yaml:generic-api-key:38 +0d310faa0d74da36faa8f5cfb5b6786ebe912c1b:deploy/k8s/secrets.yaml:generic-api-key:40 +0d310faa0d74da36faa8f5cfb5b6786ebe912c1b:deploy/k8s/secrets.yaml:generic-api-key:44 +0d310faa0d74da36faa8f5cfb5b6786ebe912c1b:deploy/k8s/secrets.yaml:generic-api-key:50 diff --git a/Cargo.lock b/Cargo.lock index 9d44e46d..6b7e3904 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,7 +71,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -82,7 +82,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -484,9 +484,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chacha20" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" dependencies = [ "cfg-if", "cpufeatures 0.3.0", @@ -625,7 +625,7 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -642,15 +642,6 @@ dependencies = [ "tokio-util", ] -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "config" version = "0.15.25" @@ -824,9 +815,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d" dependencies = [ "crossbeam-utils", ] @@ -1029,7 +1020,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -1147,7 +1138,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -1162,11 +1153,10 @@ dependencies = [ [[package]] name = "event-listener" -version = "5.4.1" +version = "5.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" dependencies = [ - "concurrent-queue", "parking", "pin-project-lite", ] @@ -1445,9 +1435,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.15" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" +checksum = "7d29020232d6aa3fb1daca64c1127cf662cf97f254ae16c18c05b8ab635fc118" dependencies = [ "atomic-waker", "bytes", @@ -2356,7 +2346,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -2861,9 +2851,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.16" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" +checksum = "0e750cca55fe4f0439a15d0bb529da9651e79993e8e72c61a899a36d462befbe" dependencies = [ "aws-lc-rs", "bytes", @@ -3208,14 +3198,14 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] name = "rustls" -version = "0.23.45" +version = "0.23.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" +checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" dependencies = [ "aws-lc-rs", "once_cell", @@ -3266,7 +3256,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -3612,7 +3602,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -3763,7 +3753,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -3773,7 +3763,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ "rustix", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -4550,7 +4540,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] diff --git a/deny.toml b/deny.toml new file mode 100644 index 00000000..b4d277b7 --- /dev/null +++ b/deny.toml @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: MPL-2.0 +# Keep this checked in: the CI fallback uses a retired cargo-deny schema. + +[advisories] +db-path = "~/.cargo/advisory-db" +db-urls = ["https://github.com/rustsec/advisory-db"] +# Current cargo-deny always rejects vulnerabilities. Reject unmaintained direct +# dependencies; cargo-audit also reports maintenance warnings for transitives. +unmaintained = "workspace" +yanked = "warn" + +[licenses] +allow = [ + "MIT", + "Apache-2.0", + "Apache-2.0 WITH LLVM-exception", + "BSD-2-Clause", + "BSD-3-Clause", + "ISC", + "Zlib", + "CC0-1.0", + "MPL-2.0", + "Unicode-DFS-2016", + "Unicode-3.0", +] +exceptions = [ + # Mozilla CA data uses the permissive Community Data License Agreement. + { crate = "webpki-roots", allow = ["CDLA-Permissive-2.0"] }, + { crate = "webpki-root-certs", allow = ["CDLA-Permissive-2.0"] }, + # Redis's xxHash implementation uses the permissive Boost license. + { crate = "xxhash-rust", allow = ["BSL-1.0"] }, +] + +[bans] +multiple-versions = "warn" +wildcards = "warn" +highlight = "all" + +[sources] +unknown-registry = "deny" +unknown-git = "warn" +allow-registry = ["https://github.com/rust-lang/crates.io-index"] diff --git a/hypatia-cli-bash.sh b/hypatia-cli-bash.sh index 3bcf1cfc..66e5c0bb 100755 --- a/hypatia-cli-bash.sh +++ b/hypatia-cli-bash.sh @@ -331,7 +331,7 @@ scan_code_patterns() { # the banned-language filter above). run_pattern "$dir" "*.{js,jsx,mjs,res}" '\beval\s*\(' \ "critical" "code_injection" "eval_usage" "CWE-95" \ - "Replace eval() with JSON.parse, switch, or safe alternatives" + "Replace eval() with JSON.parse, switch, or safe alternatives" # hypatia:ignore eval_in_shell -- JavaScript diagnostic text, not shell execution. # Dynamic Function() constructor run_pattern "$dir" "*.{js,jsx,mjs,res}" '\bFunction\s*\(' \ diff --git a/integration/fixtures/mock-responses/bitbucket-repo.json b/integration/fixtures/mock-responses/bitbucket-repo.json index 628c0b6a..06fcee5e 100644 --- a/integration/fixtures/mock-responses/bitbucket-repo.json +++ b/integration/fixtures/mock-responses/bitbucket-repo.json @@ -1,6 +1,6 @@ { "type": "repository", - "uuid": "{12345678-1234-1234-1234-123456789abc}", + "uuid": "{12345678-1234-8234-8234-123456789abc}", "full_name": "hyperpolymath/test-repo", "name": "test-repo", "slug": "test-repo", @@ -15,13 +15,13 @@ "has_wiki": false, "owner": { "type": "user", - "uuid": "{87654321-4321-4321-4321-cba987654321}", + "uuid": "{87654321-4321-8321-8321-cba987654321}", "username": "hyperpolymath", "display_name": "hyperpolymath", - "account_id": "123456:abcdef12-3456-7890-abcd-ef1234567890", + "account_id": "123456:abcdef12-3456-8890-abcd-ef1234567890", "links": { "self": { - "href": "https://api.bitbucket.org/2.0/users/%7B87654321-4321-4321-4321-cba987654321%7D" + "href": "https://api.bitbucket.org/2.0/users/%7B87654321-4321-8321-8321-cba987654321%7D" }, "html": { "href": "https://bitbucket.org/hyperpolymath/" @@ -33,7 +33,7 @@ }, "workspace": { "type": "workspace", - "uuid": "{87654321-4321-4321-4321-cba987654321}", + "uuid": "{87654321-4321-8321-8321-cba987654321}", "name": "hyperpolymath", "slug": "hyperpolymath", "links": { @@ -51,7 +51,7 @@ "project": { "type": "project", "key": "TEST", - "uuid": "{11111111-1111-1111-1111-111111111111}", + "uuid": "{11111111-1111-8111-8111-111111111111}", "name": "Test Project", "links": { "self": { diff --git a/lib/rules/actions_lock.ex b/lib/rules/actions_lock.ex index fce24544..2d6987fe 100644 --- a/lib/rules/actions_lock.ex +++ b/lib/rules/actions_lock.ex @@ -3,7 +3,7 @@ defmodule Hypatia.Rules.ActionsLock do @moduledoc """ - Strict local validation for machine-generated `gh actions-lock` v0.0.2 files. + Strict local validation for machine-generated `gh actions-lock` v0.0.2/v0.0.3 files. This module validates lockfile *shape and association*. It does not replace `gh actions-lock --verify`, which remains authoritative for resolving refs @@ -13,11 +13,11 @@ defmodule Hypatia.Rules.ActionsLock do The parser is deliberately line-oriented. `actions.lock` is generated by a single tool with a versioned stable format, and Hypatia must not add a general - YAML dependency merely to consume that format. Unknown or malformed v0.0.2 + YAML dependency merely to consume that format. Unknown or malformed lockfile lines fail closed rather than being guessed at. """ - @supported_version "v0.0.2" + @supported_versions ["v0.0.2", "v0.0.3"] @action_ref ~r/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.\/-]+@[^\s':]+$/ @dependency_key ~r/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+@[^\s':]+$/ @sha_ref ~r/^[0-9A-Fa-f]{40}$/ @@ -38,7 +38,7 @@ defmodule Hypatia.Rules.ActionsLock do } @doc """ - Parse and validate a complete v0.0.2 lockfile. + Parse and validate a complete v0.0.2 or v0.0.3 lockfile. Returns `{:error, reason}` for missing, unsupported, malformed, incomplete, duplicate, or contradictory input. One bad dependency invalidates the whole @@ -136,17 +136,17 @@ defmodule Hypatia.Rules.ActionsLock do cond do match = Regex.run(~r/^version: '([^']+)'$/, line) -> case match do - [_, @supported_version] when is_nil(state.version) -> - {:ok, %{state | version: @supported_version}} + [_, version] when version in @supported_versions and is_nil(state.version) -> + {:ok, %{state | version: version}} - [_, @supported_version] -> + [_, version] when version in @supported_versions -> line_error(line_number, :duplicate_version) [_, version] -> line_error(line_number, {:unsupported_version, version}) end - line == "workflows:" and state.version == @supported_version -> + line == "workflows:" and state.version in @supported_versions -> {:ok, %{state | section: :workflows}} true -> diff --git a/scripts/hypatia-sitrep.sh b/scripts/hypatia-sitrep.sh index 14648063..5772e56c 100755 --- a/scripts/hypatia-sitrep.sh +++ b/scripts/hypatia-sitrep.sh @@ -135,11 +135,9 @@ echo "$ALL_OUTPUT" | sed -n '/SECTION:GATE/,/SECTION:END/p' | grep -E "^\s+(Appr # --- 6. Top findings by frequency --- header "TOP PATTERNS (by repo count)" if [[ -f "$MANIFEST" ]]; then - jq -r '.pattern_id' "$MANIFEST" 2>/dev/null | sort | uniq -c | sort -rn | head -10 > /tmp/hypatia-top-patterns.txt || true while read -r count pid; do printf " %4d repos %s\n" "$count" "$pid" - done < /tmp/hypatia-top-patterns.txt - rm -f /tmp/hypatia-top-patterns.txt + done < <(jq -r '.pattern_id' "$MANIFEST" 2>/dev/null | sort | uniq -c | sort -rn | head -10 || true) else log " No dispatch manifest found" fi diff --git a/scripts/ramdisk-orchestrator.sh b/scripts/ramdisk-orchestrator.sh index bbf2e06f..7bc07f91 100755 --- a/scripts/ramdisk-orchestrator.sh +++ b/scripts/ramdisk-orchestrator.sh @@ -19,7 +19,7 @@ # --push Push committed fixes to remotes # --dry-run Show what would be done without doing it # --keep Do not unmount RAM disk on completion -# --mount PATH Custom mount point (default: /tmp/hypatia-workspace) +# --mount PATH Custom mount point (default: per-user hypatia/workspace) # --max-repos N Limit number of repos to process # --fallback-disk Fall back to Eclipse drive if RAM is insufficient # --quiet Suppress non-essential output @@ -43,7 +43,8 @@ FARM_DIR="${FARM_DIR:-${HYPATIA_DIR}/../.git-private-farm}" ECLIPSE_REPOS="${HYPATIA_REPOS_DIR:-$(dirname "$HYPATIA_DIR")}" # Defaults -MOUNT_POINT="/tmp/hypatia-workspace" +WORKSPACE_BASE="${XDG_RUNTIME_DIR:-${XDG_STATE_HOME:-$HOME/.local/state}}/hypatia" +MOUNT_POINT="${WORKSPACE_BASE}/workspace" RAMDISK_SIZE="2G" ORG="hyperpolymath" SEVERITY="high" @@ -176,7 +177,7 @@ mount_workspace() { if ! sudo -n true 2>/dev/null; then log_warn "No passwordless sudo — falling back to disk workspace" USE_TMPFS=false - MOUNT_POINT="/tmp/hypatia-workspace-$$" + MOUNT_POINT="${WORKSPACE_BASE}/workspace-$$" fi fi diff --git a/test/rules/actions_lock_test.exs b/test/rules/actions_lock_test.exs index e7e9c9eb..2c80e74c 100644 --- a/test/rules/actions_lock_test.exs +++ b/test/rules/actions_lock_test.exs @@ -281,6 +281,21 @@ defmodule Hypatia.Rules.ActionsLockTest do assert map_size(parsed.dependencies) > 0 end + test "v0.0.3 retains workflow association and fails closed on malformed dependencies" do + content = String.replace(@valid_lock, "v0.0.2", "v0.0.3") + + assert {:ok, parsed} = ActionsLock.parse(content) + assert parsed.version == "v0.0.3" + assert ActionsLock.pinned?(parsed, "ci.yml", "actions/checkout@v7.0.1") + refute ActionsLock.pinned?(parsed, "other.yml", "actions/checkout@v7.0.1") + + malformed = String.replace(content, ~r/sha1-[0-9a-f]{40}/, "sha1-short") + assert {:error, {:line, _, :malformed_dependency_commit}} = ActionsLock.parse(malformed) + + duplicate = String.replace(content, "workflows:", "version: 'v0.0.3'\nworkflows:") + assert {:error, {:line, _, :duplicate_version}} = ActionsLock.parse(duplicate) + end + test "legacy Rules workflow scanner delegates to path-aware lock semantics" do assert Rules.scan_workflow(@workflow, filename: "ci.yml", actions_lock: @valid_lock) == [] diff --git a/tests/e2e.sh b/tests/e2e.sh index 37b1352c..f904e715 100644 --- a/tests/e2e.sh +++ b/tests/e2e.sh @@ -164,7 +164,7 @@ if $HAS_ELIXIR; then if [ "${_n_fail}" -gt 0 ]; then # Everything from the first failure block onward, capped so a # pathological run cannot flood the CI log. - sed -n '/^[[:space:]]*1) test /,$p' "$_mix_log" | head -500 + sed -n '/^[[:space:]]*1) test /,$p' "$_mix_log" | sed -n '1,500p' else echo "(no ExUnit failure block found — the run did not reach the tests)" tail -120 "$_mix_log"