diff --git a/.github/chainguard/regen-answers.sts.yaml b/.github/chainguard/regen-answers.sts.yaml deleted file mode 100644 index b022681..0000000 --- a/.github/chainguard/regen-answers.sts.yaml +++ /dev/null @@ -1,9 +0,0 @@ -issuer: https://token.actions.githubusercontent.com -subject: repo:chainguard-dev/vulnerability-scanner-support:ref:refs/heads/main -claim_pattern: - job_workflow_ref: chainguard-dev/vulnerability-scanner-support/.github/workflows/regen-answers.yaml@refs/heads/main - -permissions: - contents: write - pull_requests: write - workflows: write diff --git a/.github/workflows/build-scanner-audit.yaml b/.github/workflows/build-scanner-audit.yaml deleted file mode 100644 index 1151baa..0000000 --- a/.github/workflows/build-scanner-audit.yaml +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2025 Chainguard, Inc. -# SPDX-License-Identifier: Apache-2.0 - -name: build-scanner-audit - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -permissions: {} - -jobs: - build: - name: build - runs-on: ubuntu-latest - - permissions: - contents: read - - steps: - - uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 - with: - egress-policy: audit - - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 - with: - go-version-file: './scanner-audit/go.mod' - check-latest: true - - - name: build - run: | - set -x - cd scanner-audit/ - go build -o scanner-audit . - ./scanner-audit --help diff --git a/README.md b/README.md index 7655089..ad3e085 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,3 @@ Chainguard Libraries provides secure, curated versions of open source libraries If you're unfamiliar with Chainguard Libraries, start with [Libraries Foundational Concepts](./libraries/foundational_concepts.md) to understand what Libraries are and how CVE remediation works. Next, to learn how to integrate Chainguard's VEX feed in your vulnerability scanner, look at [Libraries Scanning Implementation](./libraries/scanning_implementation.md). - -### Scanner Audit Tool - -The `scanner-audit` tool is a Go-based CLI utility that allows organizations responsible for specific scanner implementations to validate their scanner against Chainguard's provided test cases. This tool helps ensure your scanner correctly identifies vulnerabilities in Chainguard Images and packages according to the official support criteria, producing a detailed HTML report with test results. - -For detailed usage instructions and implementation details, please see the [ `scanner-audit/`](./scanner-audit/README.md) directory. diff --git a/data/answers-chainguard.json b/data/answers-chainguard.json deleted file mode 100644 index 98f3bed..0000000 --- a/data/answers-chainguard.json +++ /dev/null @@ -1,1736 +0,0 @@ -{ - "testCases": [ - { - "testCaseName": "false-positive-language-package-vulnerabilities", - "vulnerabilities": [], - "optionalVulnerabilities": [ - [ - "CVE-2024-12798" - ], - [ - "CVE-2024-12801" - ], - [ - "CVE-2024-23454" - ], - [ - "CVE-2024-25638" - ], - [ - "CVE-2024-31141" - ], - [ - "CVE-2024-36114" - ], - [ - "CVE-2024-36124" - ], - [ - "CVE-2024-38808" - ], - [ - "CVE-2024-38809" - ], - [ - "CVE-2024-38820" - ], - [ - "CVE-2024-38821" - ], - [ - "CVE-2024-38829" - ], - [ - "CVE-2024-47554" - ], - [ - "CVE-2024-47561" - ], - [ - "CVE-2024-52046" - ], - [ - "CVE-2024-57699" - ], - [ - "CVE-2024-58103" - ], - [ - "CVE-2024-6763" - ], - [ - "CVE-2024-7254" - ], - [ - "CVE-2024-8184" - ], - [ - "CVE-2025-11226" - ], - [ - "CVE-2025-14763" - ], - [ - "CVE-2025-22227" - ], - [ - "CVE-2025-22233" - ], - [ - "CVE-2025-24970" - ], - [ - "CVE-2025-27817" - ], - [ - "CVE-2025-41234" - ], - [ - "CVE-2025-41248" - ], - [ - "CVE-2025-41249" - ], - [ - "CVE-2025-48734" - ], - [ - "CVE-2025-48924" - ], - [ - "CVE-2025-5115" - ], - [ - "CVE-2025-53864" - ], - [ - "CVE-2025-55163" - ], - [ - "CVE-2025-58056" - ], - [ - "CVE-2025-58057" - ], - [ - "CVE-2025-67735" - ], - [ - "CVE-2025-7962" - ], - [ - "CVE-2026-0636" - ], - [ - "CVE-2026-1225" - ], - [ - "CVE-2026-22732" - ], - [ - "CVE-2026-22746" - ], - [ - "CVE-2026-22747" - ], - [ - "CVE-2026-22748" - ], - [ - "CVE-2026-22751" - ], - [ - "CVE-2026-22753" - ], - [ - "CVE-2026-22754" - ], - [ - "CVE-2026-2332" - ], - [ - "CVE-2026-24281" - ], - [ - "CVE-2026-24308" - ], - [ - "CVE-2026-29062" - ], - [ - "CVE-2026-33557" - ], - [ - "CVE-2026-3505" - ], - [ - "CVE-2026-35554" - ], - [ - "CVE-2026-41409" - ], - [ - "CVE-2026-41417" - ], - [ - "CVE-2026-42578" - ], - [ - "CVE-2026-42579" - ], - [ - "CVE-2026-42580" - ], - [ - "CVE-2026-42581" - ], - [ - "CVE-2026-42583" - ], - [ - "CVE-2026-42584" - ], - [ - "CVE-2026-42585" - ], - [ - "CVE-2026-42587" - ], - [ - "CVE-2026-42778" - ], - [ - "CVE-2026-42779" - ], - [ - "CVE-2026-5588" - ], - [ - "CVE-2026-5598" - ], - [ - "GHSA-25qh-j22f-pwp8" - ], - [ - "GHSA-288c-cq4h-88gq" - ], - [ - "GHSA-28jg-cgg7-j4wc" - ], - [ - "GHSA-2c59-37c4-qrx5" - ], - [ - "GHSA-2hmj-97jw-28jh" - ], - [ - "GHSA-2jrg-rf5x-568g" - ], - [ - "GHSA-2m67-wjpj-xhg9" - ], - [ - "GHSA-2rmj-mq67-h97g" - ], - [ - "GHSA-2x2g-32r7-p4x8" - ], - [ - "GHSA-355h-qmc2-wpwf" - ], - [ - "GHSA-35gq-cvrm-xf94" - ], - [ - "GHSA-3677-xxcr-wjqv" - ], - [ - "GHSA-38f8-5428-x5cv" - ], - [ - "GHSA-3j6g-hxx5-3q26" - ], - [ - "GHSA-3p8m-j85q-pgmj" - ], - [ - "GHSA-3x8x-79m2-3w2w" - ], - [ - "GHSA-4265-ccf5-phj5" - ], - [ - "GHSA-45q3-82m4-75jr" - ], - [ - "GHSA-4cx2-fc23-5wg6" - ], - [ - "GHSA-4g8c-wm8x-jfhw" - ], - [ - "GHSA-4g9r-vxhx-9pgx" - ], - [ - "GHSA-4gc7-5j7h-4qph" - ], - [ - "GHSA-4h8f-2wvx-gg5w" - ], - [ - "GHSA-4q2v-9p7v-3v22" - ], - [ - "GHSA-4vrc-j85c-598c" - ], - [ - "GHSA-4wp7-92pw-q264" - ], - [ - "GHSA-4wrg-8wpc-h923" - ], - [ - "GHSA-53wx-pr6q-m3j5" - ], - [ - "GHSA-5476-xc4j-rqcv" - ], - [ - "GHSA-5568-6qcg-g7fx" - ], - [ - "GHSA-57j2-w4cx-62h2" - ], - [ - "GHSA-57rv-r2g8-2cj3" - ], - [ - "GHSA-5jpm-x58v-624v" - ], - [ - "GHSA-5mg8-w23w-74h3" - ], - [ - "GHSA-5qcv-4rpc-jp93" - ], - [ - "GHSA-67mf-3cr5-8w23" - ], - [ - "GHSA-6mjq-h674-j845" - ], - [ - "GHSA-6qvw-249j-h44c" - ], - [ - "GHSA-6r3c-xf4w-jxjm" - ], - [ - "GHSA-6v53-7c9g-w56r" - ], - [ - "GHSA-6v67-2wr5-gvf4" - ], - [ - "GHSA-72hv-8253-57qq" - ], - [ - "GHSA-72qj-48g4-5xgx" - ], - [ - "GHSA-735f-pc8j-v9w8" - ], - [ - "GHSA-76h9-2vwh-w278" - ], - [ - "GHSA-78wr-2p64-hpwj" - ], - [ - "GHSA-7g45-4rm6-3mm3" - ], - [ - "GHSA-7mqj-xgf8-p59v" - ], - [ - "GHSA-7xrh-hqfc-g7qr" - ], - [ - "GHSA-8297-v2rf-2p32" - ], - [ - "GHSA-84h7-rjj3-6jx4" - ], - [ - "GHSA-8v5q-rhf3-jphm" - ], - [ - "GHSA-8wh2-6qhj-h7j9" - ], - [ - "GHSA-8xfc-gm6g-vgpv" - ], - [ - "GHSA-9342-92gg-6v29" - ], - [ - "GHSA-973x-65j7-xcf4" - ], - [ - "GHSA-995c-6rp3-4m4x" - ], - [ - "GHSA-9cmq-m9j5-mvww" - ], - [ - "GHSA-9w38-p64v-xpmv" - ], - [ - "GHSA-c3fc-8qff-9hwx" - ], - [ - "GHSA-c4q5-6c82-3qpw" - ], - [ - "GHSA-c5w7-m8wf-xc77" - ], - [ - "GHSA-cfxw-4h78-h7fw" - ], - [ - "GHSA-cj8j-37rh-8475" - ], - [ - "GHSA-cm33-6792-r9fm" - ], - [ - "GHSA-cmp6-m4wj-q63q" - ], - [ - "GHSA-crhr-qqj8-rpxc" - ], - [ - "GHSA-cvc6-q2cp-2xhw" - ], - [ - "GHSA-f2wh-grmh-r6jm" - ], - [ - "GHSA-f58c-gq56-vjjf" - ], - [ - "GHSA-f5fw-25gw-5m92" - ], - [ - "GHSA-f6hv-jmp6-3vwv" - ], - [ - "GHSA-fghv-69vj-qj49" - ], - [ - "GHSA-fx2c-96vj-985v" - ], - [ - "GHSA-g8m5-722r-8whq" - ], - [ - "GHSA-g93m-8x6h-g5gv" - ], - [ - "GHSA-gmg8-593g-7mv3" - ], - [ - "GHSA-gvpg-vgmx-xg6w" - ], - [ - "GHSA-h2h4-5m64-m273" - ], - [ - "GHSA-h46c-h94j-95f3" - ], - [ - "GHSA-h4h5-3hr4-j3g2" - ], - [ - "GHSA-hh82-3pmq-7frp" - ], - [ - "GHSA-hr8g-6v94-x4m9" - ], - [ - "GHSA-j288-q9x7-2f5v" - ], - [ - "GHSA-jfg9-48mv-9qgx" - ], - [ - "GHSA-jjjh-jjxp-wpff" - ], - [ - "GHSA-jmp9-x22r-554x" - ], - [ - "GHSA-jq43-27x9-3v86" - ], - [ - "GHSA-m2cm-222f-qw44" - ], - [ - "GHSA-m4cv-j2px-7723" - ], - [ - "GHSA-m5vv-6r4h-3vj9" - ], - [ - "GHSA-mf92-479x-3373" - ], - [ - "GHSA-mg83-c7gq-rv5c" - ], - [ - "GHSA-mj4r-2hfc-f8p6" - ], - [ - "GHSA-mm8h-8587-p46h" - ], - [ - "GHSA-mmxm-8w33-wc4h" - ], - [ - "GHSA-mpj7-7mg7-x95j" - ], - [ - "GHSA-mqvr-2rp8-j7h4" - ], - [ - "GHSA-mvr2-9pj6-7w5j" - ], - [ - "GHSA-p53j-g8pw-4w5f" - ], - [ - "GHSA-p93r-85wp-75v3" - ], - [ - "GHSA-pq2g-wx69-c263" - ], - [ - "GHSA-pr98-23f8-jwxv" - ], - [ - "GHSA-prj3-ccx8-p6x4" - ], - [ - "GHSA-pwf9-q62p-v7wc" - ], - [ - "GHSA-pwqr-wmgm-9rr8" - ], - [ - "GHSA-q3v6-hm2v-pw99" - ], - [ - "GHSA-q4rv-gq96-w7c5" - ], - [ - "GHSA-qh8g-58pp-2wxh" - ], - [ - "GHSA-qqpg-mvqg-649v" - ], - [ - "GHSA-r7pg-v2c8-mfg3" - ], - [ - "GHSA-rgrr-p7gp-5xj7" - ], - [ - "GHSA-rgv9-q543-rqg4" - ], - [ - "GHSA-v3vc-6qcv-4vrx" - ], - [ - "GHSA-v435-xc8x-wvr9" - ], - [ - "GHSA-v4p2-2w39-mhrj" - ], - [ - "GHSA-v8h7-rr48-vmmv" - ], - [ - "GHSA-vf5j-865m-mq7c" - ], - [ - "GHSA-vgq5-3255-v292" - ], - [ - "GHSA-vqf4-7m7x-wgfc" - ], - [ - "GHSA-vx9q-rhv9-3jvg" - ], - [ - "GHSA-vxf7-qj7q-83fh" - ], - [ - "GHSA-w9fj-cfpg-grvv" - ], - [ - "GHSA-wf66-mphr-4c4r" - ], - [ - "GHSA-wf8f-6423-gfxg" - ], - [ - "GHSA-wg6q-6289-32hp" - ], - [ - "GHSA-whxr-3p84-rf3c" - ], - [ - "GHSA-wjpw-4j6x-6rwh" - ], - [ - "GHSA-wjxj-5m7g-mg7q" - ], - [ - "GHSA-wrvw-hg22-4m67" - ], - [ - "GHSA-wxr5-93ph-8wr9" - ], - [ - "GHSA-x2wq-9x2f-fhj7" - ], - [ - "GHSA-x44p-gvrj-pj2r" - ], - [ - "GHSA-xjp4-hw94-mvp5" - ], - [ - "GHSA-xpw8-rcwv-8f8p" - ], - [ - "GHSA-xwmg-2g98-w7v9" - ], - [ - "GHSA-xxqh-mfjm-7mv9" - ] - ] - }, - { - "testCaseName": "false-positives-from-lock-files", - "vulnerabilities": [], - "optionalVulnerabilities": [ - [ - "CVE-2023-45803" - ], - [ - "CVE-2024-34155" - ], - [ - "CVE-2024-34156" - ], - [ - "CVE-2024-34158" - ], - [ - "CVE-2024-35195" - ], - [ - "CVE-2024-3651" - ], - [ - "CVE-2024-37891" - ], - [ - "CVE-2024-39689" - ], - [ - "CVE-2024-41110" - ], - [ - "CVE-2024-45336" - ], - [ - "CVE-2024-45337" - ], - [ - "CVE-2024-45338" - ], - [ - "CVE-2024-45341" - ], - [ - "CVE-2024-47081" - ], - [ - "CVE-2024-51744" - ], - [ - "CVE-2024-6345" - ], - [ - "CVE-2025-15558" - ], - [ - "CVE-2025-22868" - ], - [ - "CVE-2025-22869" - ], - [ - "CVE-2025-22870" - ], - [ - "CVE-2025-30204" - ], - [ - "CVE-2025-47907" - ], - [ - "CVE-2025-47910" - ], - [ - "CVE-2025-47914" - ], - [ - "CVE-2025-54410" - ], - [ - "CVE-2025-58181" - ], - [ - "CVE-2025-61727" - ], - [ - "CVE-2025-61729" - ], - [ - "CVE-2026-0994" - ], - [ - "CVE-2026-1703" - ], - [ - "CVE-2026-21441" - ], - [ - "CVE-2026-23490" - ], - [ - "CVE-2026-23949" - ], - [ - "CVE-2026-24049" - ], - [ - "CVE-2026-25645" - ], - [ - "CVE-2026-27140" - ], - [ - "CVE-2026-3219" - ], - [ - "CVE-2026-32280" - ], - [ - "CVE-2026-32281" - ], - [ - "CVE-2026-32289" - ], - [ - "CVE-2026-33186" - ], - [ - "CVE-2026-33811" - ], - [ - "CVE-2026-39817" - ], - [ - "CVE-2026-39819" - ], - [ - "CVE-2026-39823" - ], - [ - "CVE-2026-39826" - ], - [ - "CVE-2026-39836" - ], - [ - "CVE-2026-42501" - ], - [ - "CVE-2026-6357" - ], - [ - "GHSA-2283-wf8c-rw8r" - ], - [ - "GHSA-248v-346w-9cwc" - ], - [ - "GHSA-29wx-vh33-7x7r" - ], - [ - "GHSA-34jh-p97f-mpxf" - ], - [ - "GHSA-38jv-5279-wg99" - ], - [ - "GHSA-3f6r-qh9c-x6mm" - ], - [ - "GHSA-3v2c-x6q9-f697" - ], - [ - "GHSA-497x-jcxf-m478" - ], - [ - "GHSA-4vq8-7jfc-9cvp" - ], - [ - "GHSA-4xh5-x5gv-qwph" - ], - [ - "GHSA-58pv-8j8x-9vj2" - ], - [ - "GHSA-58qw-9mgm-455v" - ], - [ - "GHSA-5m4p-2gjx-p2g8" - ], - [ - "GHSA-5mh9-3jwc-rp59" - ], - [ - "GHSA-5w89-2c2x-6x66" - ], - [ - "GHSA-63vm-454h-vhhq" - ], - [ - "GHSA-6v2p-p543-phr9" - ], - [ - "GHSA-6vgw-5pg2-w6jp" - ], - [ - "GHSA-7c64-f9jr-v9h2" - ], - [ - "GHSA-7gcm-g887-7qv7" - ], - [ - "GHSA-7mr4-xjxg-34g6" - ], - [ - "GHSA-7wrw-r4p8-38rx" - ], - [ - "GHSA-8g2r-hhvj-mv99" - ], - [ - "GHSA-8pjc-487g-w6p2" - ], - [ - "GHSA-8qvm-5x2c-j2w7" - ], - [ - "GHSA-8rrh-rw8j-w5fx" - ], - [ - "GHSA-8xfx-rj4p-23jm" - ], - [ - "GHSA-9hjg-9r4m-mvj7" - ], - [ - "GHSA-9wx4-h78v-vm56" - ], - [ - "GHSA-crqm-pwhx-j97f" - ], - [ - "GHSA-cx63-2mw6-8hw5" - ], - [ - "GHSA-f6x5-jh6r-wrfv" - ], - [ - "GHSA-g4mx-q9vg-27p4" - ], - [ - "GHSA-gc5v-m9x4-r6x2" - ], - [ - "GHSA-gjvh-7jh8-7xhm" - ], - [ - "GHSA-hcg3-q754-cr77" - ], - [ - "GHSA-j5pm-7495-qmr3" - ], - [ - "GHSA-j5w8-q4qc-rx2x" - ], - [ - "GHSA-j7vj-rw65-4v26" - ], - [ - "GHSA-jjg7-2v4v-x38h" - ], - [ - "GHSA-jp4c-xjxw-mgf9" - ], - [ - "GHSA-m4pr-4j3g-9v7v" - ], - [ - "GHSA-mh63-6h87-95cp" - ], - [ - "GHSA-p436-gjf2-799p" - ], - [ - "GHSA-p77j-4mvh-x3m3" - ], - [ - "GHSA-q339-8rmv-2mhv" - ], - [ - "GHSA-qc64-m6c2-v4x7" - ], - [ - "GHSA-qf3q-3h68-mmh2" - ], - [ - "GHSA-qxp5-gwg8-xv66" - ], - [ - "GHSA-v23v-6jw2-98fq" - ], - [ - "GHSA-v778-237x-gjrc" - ], - [ - "GHSA-w32m-9786-jp63" - ] - ] - }, - { - "testCaseName": "fixed-language-package-vulnerabilities", - "vulnerabilities": [ - [ - "GHSA-pxq6-2prw-chj9" - ], - [ - "GHSA-x744-4wpc-v9h2" - ] - ] - }, - { - "testCaseName": "fixed-vulnerabilities", - "vulnerabilities": [ - [ - "CVE-2024-58251", - "GHSA-rrv5-483w-xmr9" - ], - [ - "CVE-2025-46394", - "GHSA-wp4q-9jq4-gv74" - ] - ] - }, - { - "testCaseName": "no-software", - "vulnerabilities": [] - }, - { - "testCaseName": "subpackage-fixed-vulnerabilities", - "vulnerabilities": [] - }, - { - "testCaseName": "subpackage-unfixed-vulnerabilities", - "vulnerabilities": [ - [ - "CVE-2022-4203" - ], - [ - "CVE-2022-4304" - ], - [ - "CVE-2022-4450" - ], - [ - "CVE-2023-0215" - ], - [ - "CVE-2023-0216" - ], - [ - "CVE-2023-0217" - ], - [ - "CVE-2023-0286" - ], - [ - "CVE-2023-0401" - ], - [ - "CVE-2023-0464" - ], - [ - "CVE-2023-0465" - ], - [ - "CVE-2023-1255" - ], - [ - "CVE-2023-2650" - ], - [ - "CVE-2023-2975" - ], - [ - "CVE-2023-3446" - ], - [ - "CVE-2023-3817" - ], - [ - "CVE-2023-5363" - ], - [ - "CVE-2023-5678" - ], - [ - "CVE-2023-6237" - ], - [ - "CVE-2024-0727" - ], - [ - "CVE-2024-12797" - ], - [ - "CVE-2024-13176" - ], - [ - "CVE-2024-2511" - ], - [ - "CVE-2024-4603" - ], - [ - "CVE-2024-4741" - ], - [ - "CVE-2024-5535" - ], - [ - "CVE-2024-6119" - ], - [ - "CVE-2024-9143" - ], - [ - "CVE-2025-11187" - ], - [ - "CVE-2025-15467" - ], - [ - "CVE-2025-15468" - ], - [ - "CVE-2025-15469" - ], - [ - "CVE-2025-4575" - ], - [ - "CVE-2025-66199" - ], - [ - "CVE-2025-68160" - ], - [ - "CVE-2025-69418" - ], - [ - "CVE-2025-69419" - ], - [ - "CVE-2025-69420" - ], - [ - "CVE-2025-69421" - ], - [ - "CVE-2025-9230" - ], - [ - "CVE-2025-9231" - ], - [ - "CVE-2025-9232" - ], - [ - "CVE-2026-22795" - ], - [ - "CVE-2026-22796" - ], - [ - "CVE-2026-2673" - ], - [ - "CVE-2026-28387" - ], - [ - "CVE-2026-28388" - ], - [ - "CVE-2026-28389" - ], - [ - "CVE-2026-28390" - ], - [ - "CVE-2026-31789" - ], - [ - "CVE-2026-31790" - ], - [ - "GHSA-299c-jvhc-gxj8" - ], - [ - "GHSA-29xx-hcv2-c4cp" - ], - [ - "GHSA-2cj7-mg3x-9mhq" - ], - [ - "GHSA-3p3x-vg38-6g9q" - ], - [ - "GHSA-3vqq-45qg-2xf6" - ], - [ - "GHSA-4fc7-mvrr-wv2c" - ], - [ - "GHSA-4wp2-xw7p-2gfx" - ], - [ - "GHSA-5888-36j9-c92p" - ], - [ - "GHSA-76r2-c3cg-f5r9" - ], - [ - "GHSA-77f3-6546-6rj7" - ], - [ - "GHSA-78qr-24v5-7q73" - ], - [ - "GHSA-79v4-65xg-pq4g" - ], - [ - "GHSA-7m4m-pwhv-49c5" - ], - [ - "GHSA-85xr-ghj6-6m46" - ], - [ - "GHSA-9mrx-mqmg-gwj9" - ], - [ - "GHSA-9v9h-cgj8-h64p" - ], - [ - "GHSA-c945-cqj5-wfv6" - ], - [ - "GHSA-g78j-46j5-97cr" - ], - [ - "GHSA-gqxg-9vfr-p9cg" - ], - [ - "GHSA-hpc7-gcqm-58fv" - ], - [ - "GHSA-hpqg-7fjp-436p" - ], - [ - "GHSA-hvc4-mjv4-5mw6" - ], - [ - "GHSA-p52g-cm5j-mjv4" - ], - [ - "GHSA-q764-r57m-9wp9" - ], - [ - "GHSA-r7jw-wp68-3xch" - ], - [ - "GHSA-r9fv-h47r-823f" - ], - [ - "GHSA-r9hf-rxjm-gv2f" - ], - [ - "GHSA-rhx3-fg8p-f9m4" - ], - [ - "GHSA-v2vr-926q-29fr" - ], - [ - "GHSA-v5w6-wcm8-jm4q" - ], - [ - "GHSA-v8qh-5c5w-48pp" - ], - [ - "GHSA-vrh7-x64v-7vxq" - ], - [ - "GHSA-vxrh-cpg7-8vjr" - ], - [ - "GHSA-w2w6-xp88-5cvw" - ], - [ - "GHSA-w42r-ph9f-9x66" - ], - [ - "GHSA-w67w-mw4j-8qrv" - ], - [ - "GHSA-w9rv-xc8m-cmqp" - ], - [ - "GHSA-wj64-gh9j-xm82" - ], - [ - "GHSA-wvhq-3h88-rf6g" - ], - [ - "GHSA-x4qr-2fvf-3mr5" - ], - [ - "GHSA-x77r-97gw-wh89" - ], - [ - "GHSA-xw78-pcr6-wrg8" - ] - ] - }, - { - "testCaseName": "unfixed-vulnerabilities", - "vulnerabilities": [ - [ - "CVE-2023-25139" - ], - [ - "CVE-2023-4527" - ], - [ - "CVE-2023-4911" - ], - [ - "CVE-2023-5156" - ], - [ - "CVE-2023-6246" - ], - [ - "CVE-2023-6779" - ], - [ - "CVE-2023-6780" - ], - [ - "CVE-2024-2961" - ], - [ - "CVE-2024-33599" - ], - [ - "CVE-2024-33600" - ], - [ - "CVE-2024-33601" - ], - [ - "CVE-2024-33602" - ], - [ - "CVE-2025-0395" - ], - [ - "CVE-2025-15281" - ], - [ - "CVE-2025-4802" - ], - [ - "CVE-2025-8058" - ], - [ - "CVE-2026-0861" - ], - [ - "CVE-2026-0915" - ], - [ - "CVE-2026-3904" - ], - [ - "CVE-2026-4046" - ], - [ - "CVE-2026-4437" - ], - [ - "CVE-2026-4438" - ], - [ - "CVE-2026-5450" - ], - [ - "CVE-2026-5928" - ], - [ - "GHSA-22q4-f5r6-3xqw" - ], - [ - "GHSA-2g67-jw5m-244m" - ], - [ - "GHSA-4xpw-6594-8f5m" - ], - [ - "GHSA-5pf6-63v3-88hw" - ], - [ - "GHSA-829p-mc9m-7xhr" - ], - [ - "GHSA-8xjp-c72j-67q8" - ], - [ - "GHSA-935r-rfch-9mr7" - ], - [ - "GHSA-9gvm-vcgf-x5xw" - ], - [ - "GHSA-f4cf-2w52-c853" - ], - [ - "GHSA-f4pv-q5f7-2h55" - ], - [ - "GHSA-g7c4-wv7q-gcc6" - ], - [ - "GHSA-hmf7-f8gf-8f4p" - ], - [ - "GHSA-jjr8-97p7-vmmg" - ], - [ - "GHSA-jv3g-6pg3-v9j8" - ], - [ - "GHSA-m5wq-r4r4-4qrh" - ], - [ - "GHSA-m77w-6vjw-wh2f" - ], - [ - "GHSA-m7p3-g2hx-xfc3" - ], - [ - "GHSA-p5vr-h433-qhqr" - ], - [ - "GHSA-p6rw-gvvh-q8v4" - ], - [ - "GHSA-qg56-4cfq-w9w3" - ], - [ - "GHSA-v898-xg3c-w4rj" - ], - [ - "GHSA-xp56-6525-9chf" - ] - ] - }, - { - "testCaseName": "unfixed-vulnerabilities-chainguard-layered", - "vulnerabilities": [ - [ - "CVE-2024-45336" - ], - [ - "CVE-2024-45341" - ], - [ - "CVE-2025-22868" - ], - [ - "CVE-2025-22871" - ], - [ - "CVE-2025-22872" - ], - [ - "CVE-2025-22873" - ], - [ - "CVE-2025-22874" - ], - [ - "CVE-2025-4673" - ], - [ - "CVE-2025-4674" - ], - [ - "CVE-2025-47906" - ], - [ - "CVE-2025-47907" - ], - [ - "CVE-2025-47912" - ], - [ - "CVE-2025-58183" - ], - [ - "CVE-2025-58185" - ], - [ - "CVE-2025-58186" - ], - [ - "CVE-2025-58187" - ], - [ - "CVE-2025-58188" - ], - [ - "CVE-2025-58189" - ], - [ - "CVE-2025-61723" - ], - [ - "CVE-2025-61724" - ], - [ - "CVE-2025-61725" - ], - [ - "CVE-2025-61726" - ], - [ - "CVE-2025-61727" - ], - [ - "CVE-2025-61728" - ], - [ - "CVE-2025-61729" - ], - [ - "CVE-2025-61730" - ], - [ - "CVE-2025-61731" - ], - [ - "CVE-2025-61732" - ], - [ - "CVE-2025-68121" - ], - [ - "CVE-2026-25679" - ], - [ - "CVE-2026-27139" - ], - [ - "CVE-2026-27140" - ], - [ - "CVE-2026-27142" - ], - [ - "CVE-2026-27143" - ], - [ - "CVE-2026-27144" - ], - [ - "CVE-2026-32280" - ], - [ - "CVE-2026-32281" - ], - [ - "CVE-2026-32282" - ], - [ - "CVE-2026-32283" - ], - [ - "CVE-2026-32288" - ], - [ - "CVE-2026-32289" - ], - [ - "CVE-2026-33811" - ], - [ - "CVE-2026-33814" - ], - [ - "CVE-2026-39817" - ], - [ - "CVE-2026-39819" - ], - [ - "CVE-2026-39820" - ], - [ - "CVE-2026-39823" - ], - [ - "CVE-2026-39825" - ], - [ - "CVE-2026-39826" - ], - [ - "CVE-2026-39836" - ], - [ - "CVE-2026-42499" - ], - [ - "CVE-2026-42501" - ], - [ - "GHSA-3f6r-qh9c-x6mm" - ], - [ - "GHSA-4x4m-3c2p-qppc" - ], - [ - "GHSA-62jj-gr2r-5c34" - ], - [ - "GHSA-6f52-wpx2-hvf2" - ], - [ - "GHSA-6v2p-p543-phr9" - ], - [ - "GHSA-7wrw-r4p8-38rx" - ], - [ - "GHSA-9h8m-3fm2-qjrq" - ], - [ - "GHSA-cgrx-mc8f-2prm" - ], - [ - "GHSA-g9pc-8g42-g6vq" - ], - [ - "GHSA-hfvc-g4fc-pqhx" - ], - [ - "GHSA-hj2p-8wj8-pfq4" - ], - [ - "GHSA-p77j-4mvh-x3m3" - ], - [ - "GHSA-r6j8-c6r2-37rr" - ], - [ - "GHSA-vvgc-356p-c3xw" - ] - ] - }, - { - "testCaseName": "unfixed-vulnerabilities-layered", - "vulnerabilities": [ - [ - "CVE-2023-25139" - ], - [ - "CVE-2023-4527" - ], - [ - "CVE-2023-4911" - ], - [ - "CVE-2023-5156" - ], - [ - "CVE-2023-6246" - ], - [ - "CVE-2023-6779" - ], - [ - "CVE-2023-6780" - ], - [ - "CVE-2024-2961" - ], - [ - "CVE-2024-33599" - ], - [ - "CVE-2024-33600" - ], - [ - "CVE-2024-33601" - ], - [ - "CVE-2024-33602" - ], - [ - "CVE-2025-0395" - ], - [ - "CVE-2025-15281" - ], - [ - "CVE-2025-4802" - ], - [ - "CVE-2025-8058" - ], - [ - "CVE-2026-0861" - ], - [ - "CVE-2026-0915" - ], - [ - "CVE-2026-3904" - ], - [ - "CVE-2026-4046" - ], - [ - "CVE-2026-4437" - ], - [ - "CVE-2026-4438" - ], - [ - "CVE-2026-5450" - ], - [ - "CVE-2026-5928" - ], - [ - "GHSA-22q4-f5r6-3xqw" - ], - [ - "GHSA-2g67-jw5m-244m" - ], - [ - "GHSA-4xpw-6594-8f5m" - ], - [ - "GHSA-5pf6-63v3-88hw" - ], - [ - "GHSA-829p-mc9m-7xhr" - ], - [ - "GHSA-8xjp-c72j-67q8" - ], - [ - "GHSA-935r-rfch-9mr7" - ], - [ - "GHSA-9gvm-vcgf-x5xw" - ], - [ - "GHSA-f4cf-2w52-c853" - ], - [ - "GHSA-f4pv-q5f7-2h55" - ], - [ - "GHSA-g7c4-wv7q-gcc6" - ], - [ - "GHSA-hmf7-f8gf-8f4p" - ], - [ - "GHSA-jjr8-97p7-vmmg" - ], - [ - "GHSA-jv3g-6pg3-v9j8" - ], - [ - "GHSA-m5wq-r4r4-4qrh" - ], - [ - "GHSA-m77w-6vjw-wh2f" - ], - [ - "GHSA-m7p3-g2hx-xfc3" - ], - [ - "GHSA-p5vr-h433-qhqr" - ], - [ - "GHSA-p6rw-gvvh-q8v4" - ], - [ - "GHSA-qg56-4cfq-w9w3" - ], - [ - "GHSA-v898-xg3c-w4rj" - ], - [ - "GHSA-xp56-6525-9chf" - ] - ] - } - ] -} diff --git a/data/answers.json b/data/answers.json deleted file mode 100644 index 98f3bed..0000000 --- a/data/answers.json +++ /dev/null @@ -1,1736 +0,0 @@ -{ - "testCases": [ - { - "testCaseName": "false-positive-language-package-vulnerabilities", - "vulnerabilities": [], - "optionalVulnerabilities": [ - [ - "CVE-2024-12798" - ], - [ - "CVE-2024-12801" - ], - [ - "CVE-2024-23454" - ], - [ - "CVE-2024-25638" - ], - [ - "CVE-2024-31141" - ], - [ - "CVE-2024-36114" - ], - [ - "CVE-2024-36124" - ], - [ - "CVE-2024-38808" - ], - [ - "CVE-2024-38809" - ], - [ - "CVE-2024-38820" - ], - [ - "CVE-2024-38821" - ], - [ - "CVE-2024-38829" - ], - [ - "CVE-2024-47554" - ], - [ - "CVE-2024-47561" - ], - [ - "CVE-2024-52046" - ], - [ - "CVE-2024-57699" - ], - [ - "CVE-2024-58103" - ], - [ - "CVE-2024-6763" - ], - [ - "CVE-2024-7254" - ], - [ - "CVE-2024-8184" - ], - [ - "CVE-2025-11226" - ], - [ - "CVE-2025-14763" - ], - [ - "CVE-2025-22227" - ], - [ - "CVE-2025-22233" - ], - [ - "CVE-2025-24970" - ], - [ - "CVE-2025-27817" - ], - [ - "CVE-2025-41234" - ], - [ - "CVE-2025-41248" - ], - [ - "CVE-2025-41249" - ], - [ - "CVE-2025-48734" - ], - [ - "CVE-2025-48924" - ], - [ - "CVE-2025-5115" - ], - [ - "CVE-2025-53864" - ], - [ - "CVE-2025-55163" - ], - [ - "CVE-2025-58056" - ], - [ - "CVE-2025-58057" - ], - [ - "CVE-2025-67735" - ], - [ - "CVE-2025-7962" - ], - [ - "CVE-2026-0636" - ], - [ - "CVE-2026-1225" - ], - [ - "CVE-2026-22732" - ], - [ - "CVE-2026-22746" - ], - [ - "CVE-2026-22747" - ], - [ - "CVE-2026-22748" - ], - [ - "CVE-2026-22751" - ], - [ - "CVE-2026-22753" - ], - [ - "CVE-2026-22754" - ], - [ - "CVE-2026-2332" - ], - [ - "CVE-2026-24281" - ], - [ - "CVE-2026-24308" - ], - [ - "CVE-2026-29062" - ], - [ - "CVE-2026-33557" - ], - [ - "CVE-2026-3505" - ], - [ - "CVE-2026-35554" - ], - [ - "CVE-2026-41409" - ], - [ - "CVE-2026-41417" - ], - [ - "CVE-2026-42578" - ], - [ - "CVE-2026-42579" - ], - [ - "CVE-2026-42580" - ], - [ - "CVE-2026-42581" - ], - [ - "CVE-2026-42583" - ], - [ - "CVE-2026-42584" - ], - [ - "CVE-2026-42585" - ], - [ - "CVE-2026-42587" - ], - [ - "CVE-2026-42778" - ], - [ - "CVE-2026-42779" - ], - [ - "CVE-2026-5588" - ], - [ - "CVE-2026-5598" - ], - [ - "GHSA-25qh-j22f-pwp8" - ], - [ - "GHSA-288c-cq4h-88gq" - ], - [ - "GHSA-28jg-cgg7-j4wc" - ], - [ - "GHSA-2c59-37c4-qrx5" - ], - [ - "GHSA-2hmj-97jw-28jh" - ], - [ - "GHSA-2jrg-rf5x-568g" - ], - [ - "GHSA-2m67-wjpj-xhg9" - ], - [ - "GHSA-2rmj-mq67-h97g" - ], - [ - "GHSA-2x2g-32r7-p4x8" - ], - [ - "GHSA-355h-qmc2-wpwf" - ], - [ - "GHSA-35gq-cvrm-xf94" - ], - [ - "GHSA-3677-xxcr-wjqv" - ], - [ - "GHSA-38f8-5428-x5cv" - ], - [ - "GHSA-3j6g-hxx5-3q26" - ], - [ - "GHSA-3p8m-j85q-pgmj" - ], - [ - "GHSA-3x8x-79m2-3w2w" - ], - [ - "GHSA-4265-ccf5-phj5" - ], - [ - "GHSA-45q3-82m4-75jr" - ], - [ - "GHSA-4cx2-fc23-5wg6" - ], - [ - "GHSA-4g8c-wm8x-jfhw" - ], - [ - "GHSA-4g9r-vxhx-9pgx" - ], - [ - "GHSA-4gc7-5j7h-4qph" - ], - [ - "GHSA-4h8f-2wvx-gg5w" - ], - [ - "GHSA-4q2v-9p7v-3v22" - ], - [ - "GHSA-4vrc-j85c-598c" - ], - [ - "GHSA-4wp7-92pw-q264" - ], - [ - "GHSA-4wrg-8wpc-h923" - ], - [ - "GHSA-53wx-pr6q-m3j5" - ], - [ - "GHSA-5476-xc4j-rqcv" - ], - [ - "GHSA-5568-6qcg-g7fx" - ], - [ - "GHSA-57j2-w4cx-62h2" - ], - [ - "GHSA-57rv-r2g8-2cj3" - ], - [ - "GHSA-5jpm-x58v-624v" - ], - [ - "GHSA-5mg8-w23w-74h3" - ], - [ - "GHSA-5qcv-4rpc-jp93" - ], - [ - "GHSA-67mf-3cr5-8w23" - ], - [ - "GHSA-6mjq-h674-j845" - ], - [ - "GHSA-6qvw-249j-h44c" - ], - [ - "GHSA-6r3c-xf4w-jxjm" - ], - [ - "GHSA-6v53-7c9g-w56r" - ], - [ - "GHSA-6v67-2wr5-gvf4" - ], - [ - "GHSA-72hv-8253-57qq" - ], - [ - "GHSA-72qj-48g4-5xgx" - ], - [ - "GHSA-735f-pc8j-v9w8" - ], - [ - "GHSA-76h9-2vwh-w278" - ], - [ - "GHSA-78wr-2p64-hpwj" - ], - [ - "GHSA-7g45-4rm6-3mm3" - ], - [ - "GHSA-7mqj-xgf8-p59v" - ], - [ - "GHSA-7xrh-hqfc-g7qr" - ], - [ - "GHSA-8297-v2rf-2p32" - ], - [ - "GHSA-84h7-rjj3-6jx4" - ], - [ - "GHSA-8v5q-rhf3-jphm" - ], - [ - "GHSA-8wh2-6qhj-h7j9" - ], - [ - "GHSA-8xfc-gm6g-vgpv" - ], - [ - "GHSA-9342-92gg-6v29" - ], - [ - "GHSA-973x-65j7-xcf4" - ], - [ - "GHSA-995c-6rp3-4m4x" - ], - [ - "GHSA-9cmq-m9j5-mvww" - ], - [ - "GHSA-9w38-p64v-xpmv" - ], - [ - "GHSA-c3fc-8qff-9hwx" - ], - [ - "GHSA-c4q5-6c82-3qpw" - ], - [ - "GHSA-c5w7-m8wf-xc77" - ], - [ - "GHSA-cfxw-4h78-h7fw" - ], - [ - "GHSA-cj8j-37rh-8475" - ], - [ - "GHSA-cm33-6792-r9fm" - ], - [ - "GHSA-cmp6-m4wj-q63q" - ], - [ - "GHSA-crhr-qqj8-rpxc" - ], - [ - "GHSA-cvc6-q2cp-2xhw" - ], - [ - "GHSA-f2wh-grmh-r6jm" - ], - [ - "GHSA-f58c-gq56-vjjf" - ], - [ - "GHSA-f5fw-25gw-5m92" - ], - [ - "GHSA-f6hv-jmp6-3vwv" - ], - [ - "GHSA-fghv-69vj-qj49" - ], - [ - "GHSA-fx2c-96vj-985v" - ], - [ - "GHSA-g8m5-722r-8whq" - ], - [ - "GHSA-g93m-8x6h-g5gv" - ], - [ - "GHSA-gmg8-593g-7mv3" - ], - [ - "GHSA-gvpg-vgmx-xg6w" - ], - [ - "GHSA-h2h4-5m64-m273" - ], - [ - "GHSA-h46c-h94j-95f3" - ], - [ - "GHSA-h4h5-3hr4-j3g2" - ], - [ - "GHSA-hh82-3pmq-7frp" - ], - [ - "GHSA-hr8g-6v94-x4m9" - ], - [ - "GHSA-j288-q9x7-2f5v" - ], - [ - "GHSA-jfg9-48mv-9qgx" - ], - [ - "GHSA-jjjh-jjxp-wpff" - ], - [ - "GHSA-jmp9-x22r-554x" - ], - [ - "GHSA-jq43-27x9-3v86" - ], - [ - "GHSA-m2cm-222f-qw44" - ], - [ - "GHSA-m4cv-j2px-7723" - ], - [ - "GHSA-m5vv-6r4h-3vj9" - ], - [ - "GHSA-mf92-479x-3373" - ], - [ - "GHSA-mg83-c7gq-rv5c" - ], - [ - "GHSA-mj4r-2hfc-f8p6" - ], - [ - "GHSA-mm8h-8587-p46h" - ], - [ - "GHSA-mmxm-8w33-wc4h" - ], - [ - "GHSA-mpj7-7mg7-x95j" - ], - [ - "GHSA-mqvr-2rp8-j7h4" - ], - [ - "GHSA-mvr2-9pj6-7w5j" - ], - [ - "GHSA-p53j-g8pw-4w5f" - ], - [ - "GHSA-p93r-85wp-75v3" - ], - [ - "GHSA-pq2g-wx69-c263" - ], - [ - "GHSA-pr98-23f8-jwxv" - ], - [ - "GHSA-prj3-ccx8-p6x4" - ], - [ - "GHSA-pwf9-q62p-v7wc" - ], - [ - "GHSA-pwqr-wmgm-9rr8" - ], - [ - "GHSA-q3v6-hm2v-pw99" - ], - [ - "GHSA-q4rv-gq96-w7c5" - ], - [ - "GHSA-qh8g-58pp-2wxh" - ], - [ - "GHSA-qqpg-mvqg-649v" - ], - [ - "GHSA-r7pg-v2c8-mfg3" - ], - [ - "GHSA-rgrr-p7gp-5xj7" - ], - [ - "GHSA-rgv9-q543-rqg4" - ], - [ - "GHSA-v3vc-6qcv-4vrx" - ], - [ - "GHSA-v435-xc8x-wvr9" - ], - [ - "GHSA-v4p2-2w39-mhrj" - ], - [ - "GHSA-v8h7-rr48-vmmv" - ], - [ - "GHSA-vf5j-865m-mq7c" - ], - [ - "GHSA-vgq5-3255-v292" - ], - [ - "GHSA-vqf4-7m7x-wgfc" - ], - [ - "GHSA-vx9q-rhv9-3jvg" - ], - [ - "GHSA-vxf7-qj7q-83fh" - ], - [ - "GHSA-w9fj-cfpg-grvv" - ], - [ - "GHSA-wf66-mphr-4c4r" - ], - [ - "GHSA-wf8f-6423-gfxg" - ], - [ - "GHSA-wg6q-6289-32hp" - ], - [ - "GHSA-whxr-3p84-rf3c" - ], - [ - "GHSA-wjpw-4j6x-6rwh" - ], - [ - "GHSA-wjxj-5m7g-mg7q" - ], - [ - "GHSA-wrvw-hg22-4m67" - ], - [ - "GHSA-wxr5-93ph-8wr9" - ], - [ - "GHSA-x2wq-9x2f-fhj7" - ], - [ - "GHSA-x44p-gvrj-pj2r" - ], - [ - "GHSA-xjp4-hw94-mvp5" - ], - [ - "GHSA-xpw8-rcwv-8f8p" - ], - [ - "GHSA-xwmg-2g98-w7v9" - ], - [ - "GHSA-xxqh-mfjm-7mv9" - ] - ] - }, - { - "testCaseName": "false-positives-from-lock-files", - "vulnerabilities": [], - "optionalVulnerabilities": [ - [ - "CVE-2023-45803" - ], - [ - "CVE-2024-34155" - ], - [ - "CVE-2024-34156" - ], - [ - "CVE-2024-34158" - ], - [ - "CVE-2024-35195" - ], - [ - "CVE-2024-3651" - ], - [ - "CVE-2024-37891" - ], - [ - "CVE-2024-39689" - ], - [ - "CVE-2024-41110" - ], - [ - "CVE-2024-45336" - ], - [ - "CVE-2024-45337" - ], - [ - "CVE-2024-45338" - ], - [ - "CVE-2024-45341" - ], - [ - "CVE-2024-47081" - ], - [ - "CVE-2024-51744" - ], - [ - "CVE-2024-6345" - ], - [ - "CVE-2025-15558" - ], - [ - "CVE-2025-22868" - ], - [ - "CVE-2025-22869" - ], - [ - "CVE-2025-22870" - ], - [ - "CVE-2025-30204" - ], - [ - "CVE-2025-47907" - ], - [ - "CVE-2025-47910" - ], - [ - "CVE-2025-47914" - ], - [ - "CVE-2025-54410" - ], - [ - "CVE-2025-58181" - ], - [ - "CVE-2025-61727" - ], - [ - "CVE-2025-61729" - ], - [ - "CVE-2026-0994" - ], - [ - "CVE-2026-1703" - ], - [ - "CVE-2026-21441" - ], - [ - "CVE-2026-23490" - ], - [ - "CVE-2026-23949" - ], - [ - "CVE-2026-24049" - ], - [ - "CVE-2026-25645" - ], - [ - "CVE-2026-27140" - ], - [ - "CVE-2026-3219" - ], - [ - "CVE-2026-32280" - ], - [ - "CVE-2026-32281" - ], - [ - "CVE-2026-32289" - ], - [ - "CVE-2026-33186" - ], - [ - "CVE-2026-33811" - ], - [ - "CVE-2026-39817" - ], - [ - "CVE-2026-39819" - ], - [ - "CVE-2026-39823" - ], - [ - "CVE-2026-39826" - ], - [ - "CVE-2026-39836" - ], - [ - "CVE-2026-42501" - ], - [ - "CVE-2026-6357" - ], - [ - "GHSA-2283-wf8c-rw8r" - ], - [ - "GHSA-248v-346w-9cwc" - ], - [ - "GHSA-29wx-vh33-7x7r" - ], - [ - "GHSA-34jh-p97f-mpxf" - ], - [ - "GHSA-38jv-5279-wg99" - ], - [ - "GHSA-3f6r-qh9c-x6mm" - ], - [ - "GHSA-3v2c-x6q9-f697" - ], - [ - "GHSA-497x-jcxf-m478" - ], - [ - "GHSA-4vq8-7jfc-9cvp" - ], - [ - "GHSA-4xh5-x5gv-qwph" - ], - [ - "GHSA-58pv-8j8x-9vj2" - ], - [ - "GHSA-58qw-9mgm-455v" - ], - [ - "GHSA-5m4p-2gjx-p2g8" - ], - [ - "GHSA-5mh9-3jwc-rp59" - ], - [ - "GHSA-5w89-2c2x-6x66" - ], - [ - "GHSA-63vm-454h-vhhq" - ], - [ - "GHSA-6v2p-p543-phr9" - ], - [ - "GHSA-6vgw-5pg2-w6jp" - ], - [ - "GHSA-7c64-f9jr-v9h2" - ], - [ - "GHSA-7gcm-g887-7qv7" - ], - [ - "GHSA-7mr4-xjxg-34g6" - ], - [ - "GHSA-7wrw-r4p8-38rx" - ], - [ - "GHSA-8g2r-hhvj-mv99" - ], - [ - "GHSA-8pjc-487g-w6p2" - ], - [ - "GHSA-8qvm-5x2c-j2w7" - ], - [ - "GHSA-8rrh-rw8j-w5fx" - ], - [ - "GHSA-8xfx-rj4p-23jm" - ], - [ - "GHSA-9hjg-9r4m-mvj7" - ], - [ - "GHSA-9wx4-h78v-vm56" - ], - [ - "GHSA-crqm-pwhx-j97f" - ], - [ - "GHSA-cx63-2mw6-8hw5" - ], - [ - "GHSA-f6x5-jh6r-wrfv" - ], - [ - "GHSA-g4mx-q9vg-27p4" - ], - [ - "GHSA-gc5v-m9x4-r6x2" - ], - [ - "GHSA-gjvh-7jh8-7xhm" - ], - [ - "GHSA-hcg3-q754-cr77" - ], - [ - "GHSA-j5pm-7495-qmr3" - ], - [ - "GHSA-j5w8-q4qc-rx2x" - ], - [ - "GHSA-j7vj-rw65-4v26" - ], - [ - "GHSA-jjg7-2v4v-x38h" - ], - [ - "GHSA-jp4c-xjxw-mgf9" - ], - [ - "GHSA-m4pr-4j3g-9v7v" - ], - [ - "GHSA-mh63-6h87-95cp" - ], - [ - "GHSA-p436-gjf2-799p" - ], - [ - "GHSA-p77j-4mvh-x3m3" - ], - [ - "GHSA-q339-8rmv-2mhv" - ], - [ - "GHSA-qc64-m6c2-v4x7" - ], - [ - "GHSA-qf3q-3h68-mmh2" - ], - [ - "GHSA-qxp5-gwg8-xv66" - ], - [ - "GHSA-v23v-6jw2-98fq" - ], - [ - "GHSA-v778-237x-gjrc" - ], - [ - "GHSA-w32m-9786-jp63" - ] - ] - }, - { - "testCaseName": "fixed-language-package-vulnerabilities", - "vulnerabilities": [ - [ - "GHSA-pxq6-2prw-chj9" - ], - [ - "GHSA-x744-4wpc-v9h2" - ] - ] - }, - { - "testCaseName": "fixed-vulnerabilities", - "vulnerabilities": [ - [ - "CVE-2024-58251", - "GHSA-rrv5-483w-xmr9" - ], - [ - "CVE-2025-46394", - "GHSA-wp4q-9jq4-gv74" - ] - ] - }, - { - "testCaseName": "no-software", - "vulnerabilities": [] - }, - { - "testCaseName": "subpackage-fixed-vulnerabilities", - "vulnerabilities": [] - }, - { - "testCaseName": "subpackage-unfixed-vulnerabilities", - "vulnerabilities": [ - [ - "CVE-2022-4203" - ], - [ - "CVE-2022-4304" - ], - [ - "CVE-2022-4450" - ], - [ - "CVE-2023-0215" - ], - [ - "CVE-2023-0216" - ], - [ - "CVE-2023-0217" - ], - [ - "CVE-2023-0286" - ], - [ - "CVE-2023-0401" - ], - [ - "CVE-2023-0464" - ], - [ - "CVE-2023-0465" - ], - [ - "CVE-2023-1255" - ], - [ - "CVE-2023-2650" - ], - [ - "CVE-2023-2975" - ], - [ - "CVE-2023-3446" - ], - [ - "CVE-2023-3817" - ], - [ - "CVE-2023-5363" - ], - [ - "CVE-2023-5678" - ], - [ - "CVE-2023-6237" - ], - [ - "CVE-2024-0727" - ], - [ - "CVE-2024-12797" - ], - [ - "CVE-2024-13176" - ], - [ - "CVE-2024-2511" - ], - [ - "CVE-2024-4603" - ], - [ - "CVE-2024-4741" - ], - [ - "CVE-2024-5535" - ], - [ - "CVE-2024-6119" - ], - [ - "CVE-2024-9143" - ], - [ - "CVE-2025-11187" - ], - [ - "CVE-2025-15467" - ], - [ - "CVE-2025-15468" - ], - [ - "CVE-2025-15469" - ], - [ - "CVE-2025-4575" - ], - [ - "CVE-2025-66199" - ], - [ - "CVE-2025-68160" - ], - [ - "CVE-2025-69418" - ], - [ - "CVE-2025-69419" - ], - [ - "CVE-2025-69420" - ], - [ - "CVE-2025-69421" - ], - [ - "CVE-2025-9230" - ], - [ - "CVE-2025-9231" - ], - [ - "CVE-2025-9232" - ], - [ - "CVE-2026-22795" - ], - [ - "CVE-2026-22796" - ], - [ - "CVE-2026-2673" - ], - [ - "CVE-2026-28387" - ], - [ - "CVE-2026-28388" - ], - [ - "CVE-2026-28389" - ], - [ - "CVE-2026-28390" - ], - [ - "CVE-2026-31789" - ], - [ - "CVE-2026-31790" - ], - [ - "GHSA-299c-jvhc-gxj8" - ], - [ - "GHSA-29xx-hcv2-c4cp" - ], - [ - "GHSA-2cj7-mg3x-9mhq" - ], - [ - "GHSA-3p3x-vg38-6g9q" - ], - [ - "GHSA-3vqq-45qg-2xf6" - ], - [ - "GHSA-4fc7-mvrr-wv2c" - ], - [ - "GHSA-4wp2-xw7p-2gfx" - ], - [ - "GHSA-5888-36j9-c92p" - ], - [ - "GHSA-76r2-c3cg-f5r9" - ], - [ - "GHSA-77f3-6546-6rj7" - ], - [ - "GHSA-78qr-24v5-7q73" - ], - [ - "GHSA-79v4-65xg-pq4g" - ], - [ - "GHSA-7m4m-pwhv-49c5" - ], - [ - "GHSA-85xr-ghj6-6m46" - ], - [ - "GHSA-9mrx-mqmg-gwj9" - ], - [ - "GHSA-9v9h-cgj8-h64p" - ], - [ - "GHSA-c945-cqj5-wfv6" - ], - [ - "GHSA-g78j-46j5-97cr" - ], - [ - "GHSA-gqxg-9vfr-p9cg" - ], - [ - "GHSA-hpc7-gcqm-58fv" - ], - [ - "GHSA-hpqg-7fjp-436p" - ], - [ - "GHSA-hvc4-mjv4-5mw6" - ], - [ - "GHSA-p52g-cm5j-mjv4" - ], - [ - "GHSA-q764-r57m-9wp9" - ], - [ - "GHSA-r7jw-wp68-3xch" - ], - [ - "GHSA-r9fv-h47r-823f" - ], - [ - "GHSA-r9hf-rxjm-gv2f" - ], - [ - "GHSA-rhx3-fg8p-f9m4" - ], - [ - "GHSA-v2vr-926q-29fr" - ], - [ - "GHSA-v5w6-wcm8-jm4q" - ], - [ - "GHSA-v8qh-5c5w-48pp" - ], - [ - "GHSA-vrh7-x64v-7vxq" - ], - [ - "GHSA-vxrh-cpg7-8vjr" - ], - [ - "GHSA-w2w6-xp88-5cvw" - ], - [ - "GHSA-w42r-ph9f-9x66" - ], - [ - "GHSA-w67w-mw4j-8qrv" - ], - [ - "GHSA-w9rv-xc8m-cmqp" - ], - [ - "GHSA-wj64-gh9j-xm82" - ], - [ - "GHSA-wvhq-3h88-rf6g" - ], - [ - "GHSA-x4qr-2fvf-3mr5" - ], - [ - "GHSA-x77r-97gw-wh89" - ], - [ - "GHSA-xw78-pcr6-wrg8" - ] - ] - }, - { - "testCaseName": "unfixed-vulnerabilities", - "vulnerabilities": [ - [ - "CVE-2023-25139" - ], - [ - "CVE-2023-4527" - ], - [ - "CVE-2023-4911" - ], - [ - "CVE-2023-5156" - ], - [ - "CVE-2023-6246" - ], - [ - "CVE-2023-6779" - ], - [ - "CVE-2023-6780" - ], - [ - "CVE-2024-2961" - ], - [ - "CVE-2024-33599" - ], - [ - "CVE-2024-33600" - ], - [ - "CVE-2024-33601" - ], - [ - "CVE-2024-33602" - ], - [ - "CVE-2025-0395" - ], - [ - "CVE-2025-15281" - ], - [ - "CVE-2025-4802" - ], - [ - "CVE-2025-8058" - ], - [ - "CVE-2026-0861" - ], - [ - "CVE-2026-0915" - ], - [ - "CVE-2026-3904" - ], - [ - "CVE-2026-4046" - ], - [ - "CVE-2026-4437" - ], - [ - "CVE-2026-4438" - ], - [ - "CVE-2026-5450" - ], - [ - "CVE-2026-5928" - ], - [ - "GHSA-22q4-f5r6-3xqw" - ], - [ - "GHSA-2g67-jw5m-244m" - ], - [ - "GHSA-4xpw-6594-8f5m" - ], - [ - "GHSA-5pf6-63v3-88hw" - ], - [ - "GHSA-829p-mc9m-7xhr" - ], - [ - "GHSA-8xjp-c72j-67q8" - ], - [ - "GHSA-935r-rfch-9mr7" - ], - [ - "GHSA-9gvm-vcgf-x5xw" - ], - [ - "GHSA-f4cf-2w52-c853" - ], - [ - "GHSA-f4pv-q5f7-2h55" - ], - [ - "GHSA-g7c4-wv7q-gcc6" - ], - [ - "GHSA-hmf7-f8gf-8f4p" - ], - [ - "GHSA-jjr8-97p7-vmmg" - ], - [ - "GHSA-jv3g-6pg3-v9j8" - ], - [ - "GHSA-m5wq-r4r4-4qrh" - ], - [ - "GHSA-m77w-6vjw-wh2f" - ], - [ - "GHSA-m7p3-g2hx-xfc3" - ], - [ - "GHSA-p5vr-h433-qhqr" - ], - [ - "GHSA-p6rw-gvvh-q8v4" - ], - [ - "GHSA-qg56-4cfq-w9w3" - ], - [ - "GHSA-v898-xg3c-w4rj" - ], - [ - "GHSA-xp56-6525-9chf" - ] - ] - }, - { - "testCaseName": "unfixed-vulnerabilities-chainguard-layered", - "vulnerabilities": [ - [ - "CVE-2024-45336" - ], - [ - "CVE-2024-45341" - ], - [ - "CVE-2025-22868" - ], - [ - "CVE-2025-22871" - ], - [ - "CVE-2025-22872" - ], - [ - "CVE-2025-22873" - ], - [ - "CVE-2025-22874" - ], - [ - "CVE-2025-4673" - ], - [ - "CVE-2025-4674" - ], - [ - "CVE-2025-47906" - ], - [ - "CVE-2025-47907" - ], - [ - "CVE-2025-47912" - ], - [ - "CVE-2025-58183" - ], - [ - "CVE-2025-58185" - ], - [ - "CVE-2025-58186" - ], - [ - "CVE-2025-58187" - ], - [ - "CVE-2025-58188" - ], - [ - "CVE-2025-58189" - ], - [ - "CVE-2025-61723" - ], - [ - "CVE-2025-61724" - ], - [ - "CVE-2025-61725" - ], - [ - "CVE-2025-61726" - ], - [ - "CVE-2025-61727" - ], - [ - "CVE-2025-61728" - ], - [ - "CVE-2025-61729" - ], - [ - "CVE-2025-61730" - ], - [ - "CVE-2025-61731" - ], - [ - "CVE-2025-61732" - ], - [ - "CVE-2025-68121" - ], - [ - "CVE-2026-25679" - ], - [ - "CVE-2026-27139" - ], - [ - "CVE-2026-27140" - ], - [ - "CVE-2026-27142" - ], - [ - "CVE-2026-27143" - ], - [ - "CVE-2026-27144" - ], - [ - "CVE-2026-32280" - ], - [ - "CVE-2026-32281" - ], - [ - "CVE-2026-32282" - ], - [ - "CVE-2026-32283" - ], - [ - "CVE-2026-32288" - ], - [ - "CVE-2026-32289" - ], - [ - "CVE-2026-33811" - ], - [ - "CVE-2026-33814" - ], - [ - "CVE-2026-39817" - ], - [ - "CVE-2026-39819" - ], - [ - "CVE-2026-39820" - ], - [ - "CVE-2026-39823" - ], - [ - "CVE-2026-39825" - ], - [ - "CVE-2026-39826" - ], - [ - "CVE-2026-39836" - ], - [ - "CVE-2026-42499" - ], - [ - "CVE-2026-42501" - ], - [ - "GHSA-3f6r-qh9c-x6mm" - ], - [ - "GHSA-4x4m-3c2p-qppc" - ], - [ - "GHSA-62jj-gr2r-5c34" - ], - [ - "GHSA-6f52-wpx2-hvf2" - ], - [ - "GHSA-6v2p-p543-phr9" - ], - [ - "GHSA-7wrw-r4p8-38rx" - ], - [ - "GHSA-9h8m-3fm2-qjrq" - ], - [ - "GHSA-cgrx-mc8f-2prm" - ], - [ - "GHSA-g9pc-8g42-g6vq" - ], - [ - "GHSA-hfvc-g4fc-pqhx" - ], - [ - "GHSA-hj2p-8wj8-pfq4" - ], - [ - "GHSA-p77j-4mvh-x3m3" - ], - [ - "GHSA-r6j8-c6r2-37rr" - ], - [ - "GHSA-vvgc-356p-c3xw" - ] - ] - }, - { - "testCaseName": "unfixed-vulnerabilities-layered", - "vulnerabilities": [ - [ - "CVE-2023-25139" - ], - [ - "CVE-2023-4527" - ], - [ - "CVE-2023-4911" - ], - [ - "CVE-2023-5156" - ], - [ - "CVE-2023-6246" - ], - [ - "CVE-2023-6779" - ], - [ - "CVE-2023-6780" - ], - [ - "CVE-2024-2961" - ], - [ - "CVE-2024-33599" - ], - [ - "CVE-2024-33600" - ], - [ - "CVE-2024-33601" - ], - [ - "CVE-2024-33602" - ], - [ - "CVE-2025-0395" - ], - [ - "CVE-2025-15281" - ], - [ - "CVE-2025-4802" - ], - [ - "CVE-2025-8058" - ], - [ - "CVE-2026-0861" - ], - [ - "CVE-2026-0915" - ], - [ - "CVE-2026-3904" - ], - [ - "CVE-2026-4046" - ], - [ - "CVE-2026-4437" - ], - [ - "CVE-2026-4438" - ], - [ - "CVE-2026-5450" - ], - [ - "CVE-2026-5928" - ], - [ - "GHSA-22q4-f5r6-3xqw" - ], - [ - "GHSA-2g67-jw5m-244m" - ], - [ - "GHSA-4xpw-6594-8f5m" - ], - [ - "GHSA-5pf6-63v3-88hw" - ], - [ - "GHSA-829p-mc9m-7xhr" - ], - [ - "GHSA-8xjp-c72j-67q8" - ], - [ - "GHSA-935r-rfch-9mr7" - ], - [ - "GHSA-9gvm-vcgf-x5xw" - ], - [ - "GHSA-f4cf-2w52-c853" - ], - [ - "GHSA-f4pv-q5f7-2h55" - ], - [ - "GHSA-g7c4-wv7q-gcc6" - ], - [ - "GHSA-hmf7-f8gf-8f4p" - ], - [ - "GHSA-jjr8-97p7-vmmg" - ], - [ - "GHSA-jv3g-6pg3-v9j8" - ], - [ - "GHSA-m5wq-r4r4-4qrh" - ], - [ - "GHSA-m77w-6vjw-wh2f" - ], - [ - "GHSA-m7p3-g2hx-xfc3" - ], - [ - "GHSA-p5vr-h433-qhqr" - ], - [ - "GHSA-p6rw-gvvh-q8v4" - ], - [ - "GHSA-qg56-4cfq-w9w3" - ], - [ - "GHSA-v898-xg3c-w4rj" - ], - [ - "GHSA-xp56-6525-9chf" - ] - ] - } - ] -} diff --git a/hack/regen-answers-chainguard.sh b/hack/regen-answers-chainguard.sh deleted file mode 100755 index 3fe0c8e..0000000 --- a/hack/regen-answers-chainguard.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash -set -eux -o pipefail - -# Enter this dir -cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/" - -# Run regen-answers.sh with alternate env to -# use the Chainguard versions of test images (vs. Wolfi) -export TAG_SUFFIX="-chainguard" -export ANSWERS_FILE_PATH="data/answers-chainguard.json" -./regen-answers.sh diff --git a/hack/regen-answers.sh b/hack/regen-answers.sh deleted file mode 100755 index a88b15e..0000000 --- a/hack/regen-answers.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash -set -eux -o pipefail - -# Enter repo root -cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/../" - -ANSWERS_FILE_PATH="${ANSWERS_FILE_PATH:-"data/answers.json"}" -TEST_IMAGE="${TEST_IMAGE:-"ghcr.io/chainguard-images/scanner-test"}" -TAG_SUFFIX="${TAG_SUFFIX:-"-wolfi"}" - -# Without this wolfictl with get us rate limited -if [[ "${GITHUB_TOKEN:-}" == "" ]]; then - echo "Must set GITHUB_TOKEN or else you gon get rate limited. Exiting." - exit 1 -fi - -RESULTS_DIR="$(mktemp -d)" - -# Avoid any auth issues accessing images (assume they are public) -export DOCKER_CONFIG="$RESULTS_DIR/docker-unauthed" -mkdir "$DOCKER_CONFIG" - -for testcase in $(jq -r .testCases[].testCaseName $ANSWERS_FILE_PATH | sort -u); do - for id in $(grype -q "${TEST_IMAGE}:${testcase}${TAG_SUFFIX}" -o json | jq -r .matches[].vulnerability.id | sort -u); do - # Note: the wolfictl output should be machine readable, we need this perl/col command to get rid of links in the output - idalias="$(set +o pipefail; wolfictl adv alias find $id | grep ' - ' | awk '{print $2}' | perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)//g' | col -b | xargs)" - if [[ "$idalias" != "" ]]; then - if [[ $idalias > $id ]]; then - echo "[\"$id\", \"$idalias\"]" | tee -a $RESULTS_DIR/$testcase.out - else - echo "[\"$idalias\", \"$id\"]" | tee -a $RESULTS_DIR/$testcase.out - fi - else - echo "[\"$id\"]" | tee -a $RESULTS_DIR/$testcase.out - fi - done - if [[ -f $RESULTS_DIR/$testcase.out ]]; then - sort -u $RESULTS_DIR/$testcase.out > $RESULTS_DIR/$testcase.out.tmp - mv $RESULTS_DIR/$testcase.out.tmp $RESULTS_DIR/$testcase.out - - # If optionalVulnerabilities is being used, then append there, - # otherwise append to vulnerabilities - if [[ "$(jq -Mcr ".testCases[] | select(.testCaseName == \"$testcase\") | .optionalVulnerabilities" data/answers.json)" != "null" ]]; then - jq ".testCases[] |= if (.testCaseName == \"$testcase\") then (.optionalVulnerabilities = [$(cat $RESULTS_DIR/$testcase.out | tr '\n' ',' | sed 's/.$//' | sed 's/ //g')]) else . end" data/answers.json > "${ANSWERS_FILE_PATH}.tmp" - else - jq ".testCases[] |= if (.testCaseName == \"$testcase\") then (.vulnerabilities = [$(cat $RESULTS_DIR/$testcase.out | tr '\n' ',' | sed 's/.$//' | sed 's/ //g')]) else . end" data/answers.json > "${ANSWERS_FILE_PATH}.tmp" - fi - - mv "${ANSWERS_FILE_PATH}.tmp" $ANSWERS_FILE_PATH - fi -done diff --git a/hack/sort-answers.sh b/hack/sort-answers.sh deleted file mode 100755 index 7ccdab9..0000000 --- a/hack/sort-answers.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash -set -eux -o pipefail - -# Enter repo root -cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/../" - -ANSWERS_FILE_PATH="${ANSWERS_FILE_PATH:-"data/answers.json"}" - -for testcase in $(jq -r .testCases[].testCaseName $ANSWERS_FILE_PATH | sort -u); do - # If optionalVulnerabilities is being used, then append there, - # otherwise append to vulnerabilities - if [[ "$(jq -Mcr ".testCases[] | select(.testCaseName == \"$testcase\") | .optionalVulnerabilities" data/answers.json)" != "null" ]]; then - jq ".testCases[] |= if (.testCaseName == \"$testcase\") then (.optionalVulnerabilities = $(jq -Mc ".testCases[] | select(.testCaseName == \"$testcase\").optionalVulnerabilities | sort" $ANSWERS_FILE_PATH)) else . end" data/answers.json > "${ANSWERS_FILE_PATH}.tmp" - else - jq ".testCases[] |= if (.testCaseName == \"$testcase\") then (.vulnerabilities = $(jq -Mc ".testCases[] | select(.testCaseName == \"$testcase\").vulnerabilities | sort" $ANSWERS_FILE_PATH)) else . end" data/answers.json > "${ANSWERS_FILE_PATH}.tmp" - fi - mv "${ANSWERS_FILE_PATH}.tmp" $ANSWERS_FILE_PATH -done diff --git a/scanner-audit/.gitignore b/scanner-audit/.gitignore deleted file mode 100644 index 0521319..0000000 --- a/scanner-audit/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -report.html -scanner-audit -*.json -*.txt -*.html -env/private-* \ No newline at end of file diff --git a/scanner-audit/README.md b/scanner-audit/README.md deleted file mode 100644 index 71580e4..0000000 --- a/scanner-audit/README.md +++ /dev/null @@ -1,163 +0,0 @@ -# scanner-audit - -Validates vulnerability scanners against Chainguard's official test cases for Chainguard Images. - -See the [main repository README](../README.md) for official docs. - -Screenshot of HTML report produced by `scanner-audit`: -![scanner-audit screenshot](./scanner-audit-screenshot.png) - -## How to Run - -Basic usage: -```bash -go run . --env -``` - -Example: -```bash -go run . --env trivy -``` - -Filter by distro or test case: -```bash -go run . --env grype -d chainguard -go run . --env grype -t fixed-vulnerabilities -go run . --env grype -d chainguard -t fixed-vulnerabilities # Can combine filters -``` - -The audit generates `report.html` by default. Use `-o` to specify a different output path. - -**Requirements:** -- Docker must be running -- Scanner-specific environment variables must be set (if required) - -## HTML Report - -The report includes: -- **Summary**: Overall pass/fail status with test counts -- **Scanner Info**: Environment name, wrapper image, and configuration details -- **Test Results**: Expandable sections for each distro showing: - - Individual test case results - - False positives/negatives - - Expected vs actual CVEs - - Scanner output logs - -Click on distro headers or test cases to expand details. - -## Audit Envs - -Each scanner environment requires two files in the `env/` directory: - -1. **`-audit-env.yaml`**: Melange configuration that defines the package -2. **`-wrapper.sh`**: Shell script that runs the scanner and outputs CVE IDs - -Example structure: -``` -env/ -├── grype-audit-env.yaml -├── grype-wrapper.sh -├── trivy-audit-env.yaml -└── trivy-wrapper.sh -``` - -The tool uses Melange and Apko to build a Docker image containing your scanner, then runs it against test images. - -### Adding a New Scanner - -1. Create `env/-audit-env.yaml` with your scanner's package definition -2. Create `env/-wrapper.sh` that: - - Accepts an image URL as the first argument - - Runs the scanner against that image - - Outputs CVE IDs to stdout (one per line) - - Sends other output to stderr - -### Cloud-Based Scanners and Environment Variables - -Required environment variables are automatically detected from your audit-env.yaml file. In the `environment.environment` section of your melange YAML, list any environment variables that need to be set: - -```yaml -environment: - environment: - API_TOKEN: placeholder - API_SECRET: placeholder - ENDPOINT_URL: placeholder -``` - -When running scanner-audit: -1. These variables are automatically detected from the YAML -2. The tool validates that each variable is set in your environment -3. Variables cannot be empty or set to "placeholder" -4. All required variables are automatically passed to your wrapper script - -Example: -```bash -# Set required environment variables -export API_TOKEN="your-token" -export API_SECRET="your-secret" - -# Run the audit -go run . --env cloud-scanner -``` - -#### Special Environment Variable: REQUIRES_DOCKER - -The `REQUIRES_DOCKER` environment variable is a special case. When this variable is defined in your audit-env.yaml file (with any value), scanner-audit will automatically mount the Docker socket into the container: - -```yaml -environment: - environment: - REQUIRES_DOCKER: "true" # Any value will trigger Docker socket mounting - # ... other variables ... -``` - -This enables scanners that need to interact with Docker (e.g., to pull images or inspect containers) to function properly. The Docker socket will be mounted as `/var/run/docker.sock:/var/run/docker.sock`. - -**Note:** Unlike other environment variables, `REQUIRES_DOCKER`: -- Is not validated for empty or placeholder values -- Is not passed to the container as an environment variable -- Only serves to trigger the Docker socket mount - -### Custom Scanner Installation - -You can use Melange pipelines in your audit-env.yaml to install custom tools: - -```yaml -package: - name: custom-scanner-audit-env - version: 1.0.0 - -environment: - contents: - packages: - - busybox - - ca-certificates-bundle - - curl - -pipeline: - - uses: fetch - with: - uri: https://github.com/your-org/scanner/releases/download/v1.0.0/scanner-linux-amd64.tar.gz - expected-sha256: abc123... - - uses: strip-prefix - with: - prefix: scanner-v1.0.0/ - - runs: | - mkdir -p ${{targets.destdir}}/usr/local/bin - mv scanner ${{targets.destdir}}/usr/local/bin/ - chmod +x ${{targets.destdir}}/usr/local/bin/scanner -``` - -## CLI Flags - -| Flag | Short | Description | -|------|-------|-------------| -| `--env` | | Scanner environment name (required) | -| `--distro` | `-d` | Filter to specific distro | -| `--test-case` | `-t` | Filter to specific test case | -| `--output` | `-o` | Output path for HTML report (default: report.html) | -| `--force-build` | | Rebuild wrapper image even if it exists | -| `--no-remove` | | Keep container after tests complete | -| `--no-cache` | | Disable XDG cache directory mounting | -| `--answers-chainguard` | | Custom answers file for Chainguard (path or URL) | -| `--answers-wolfi` | | Custom answers file (path or URL) | diff --git a/scanner-audit/env/grype-audit-env.yaml b/scanner-audit/env/grype-audit-env.yaml deleted file mode 100644 index 8efd972..0000000 --- a/scanner-audit/env/grype-audit-env.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2025 Chainguard, Inc. -# SPDX-License-Identifier: Apache-2.0 - -# grype-audit-env.yaml -# -# A melange-compatible config file for a virtual APK package -# (in the style of ones found in github.com/wolfi-dev/os) -# which provides the environment needed to run grype-wrapper.sh -# -# This is installed in into a test image (with busybox, bash, and jq) -# and is used as a sandbox to run scanner-audit against grype - -package: - name: grype-audit-env - version: 0.0.1 # Note: version unused, latest version of grype from wolfi is installed - epoch: 0 - dependencies: - runtime: - - grype diff --git a/scanner-audit/env/grype-wrapper.sh b/scanner-audit/env/grype-wrapper.sh deleted file mode 100755 index 0c3576d..0000000 --- a/scanner-audit/env/grype-wrapper.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2025 Chainguard, Inc. -# SPDX-License-Identifier: Apache-2.0 - -# grype-wrapper.sh -# -# A script which takes a remote container image as a first argument, -# scans it using grype, and normalizes the output (Vulnerability ID per line) -# for the purposes of compatibility with scanner-audit - -set -e - -function grype_wrapper { - # Make sure image name passed as first arg - local REF="$1" - [[ "$REF" != "" ]] || (echo "Must supply image ref as first arg. Exiting." && exit 1) - - # Run grype and normalize output (Vuln ID per line) - grype "registry:$REF" -vv --output json | \ - jq -r '.matches[].vulnerability.id' | \ - sort -u -} - -grype_wrapper $1 diff --git a/scanner-audit/env/trivy-audit-env.yaml b/scanner-audit/env/trivy-audit-env.yaml deleted file mode 100644 index c0da6bb..0000000 --- a/scanner-audit/env/trivy-audit-env.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2025 Chainguard, Inc. -# SPDX-License-Identifier: Apache-2.0 - -# trivy-audit-env.yaml -# -# A melange-compatible config file for a virtual APK package -# (in the style of ones found in github.com/wolfi-dev/os) -# which provides the environment needed to run trivy-wrapper.sh -# -# This is installed in into a test image (with busybox, bash, and jq) -# and is used as a sandbox to run scanner-audit against trivy - -package: - name: trivy-audit-env - version: 0.0.1 # Note: version unused, latest version of trivy from wolfi is installed - epoch: 0 - dependencies: - runtime: - - trivy diff --git a/scanner-audit/env/trivy-wrapper.sh b/scanner-audit/env/trivy-wrapper.sh deleted file mode 100755 index 31141a0..0000000 --- a/scanner-audit/env/trivy-wrapper.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2025 Chainguard, Inc. -# SPDX-License-Identifier: Apache-2.0 - -# trivy-wrapper.sh -# -# A script which takes a remote container image as a first argument, -# scans it using trivy, and normalizes the output (Vulnerability ID per line) -# for the purposes of compatibility with scanner-audit - -set -e - -function trivy_wrapper { - # Make sure image name passed as first arg - local REF="$1" - [[ "$REF" != "" ]] || (echo "Must supply image ref as first arg. Exiting." && exit 1) - - # Run trivy and normalize output (Vuln ID per line) - trivy image --format json --image-src remote "$1" | \ - jq -r '.Results[].Vulnerabilities[].VulnerabilityID' | \ - sort -u -} - -trivy_wrapper $1 diff --git a/scanner-audit/go.mod b/scanner-audit/go.mod deleted file mode 100644 index 508b97f..0000000 --- a/scanner-audit/go.mod +++ /dev/null @@ -1,160 +0,0 @@ -module github.com/chainguard-dev/vulnerability-scanner-support/scanner-audit - -go 1.25.7 - -require ( - chainguard.dev/apko v1.2.7 - chainguard.dev/melange v0.50.2 - github.com/adrg/xdg v0.5.3 - github.com/docker/docker v28.5.2+incompatible - github.com/google/go-containerregistry v0.21.5 - github.com/spf13/cobra v1.10.2 - gopkg.in/yaml.v3 v3.0.1 -) - -require ( - chainguard.dev/go-grpc-kit v0.17.16 // indirect - chainguard.dev/sdk v0.1.52 // indirect - cloud.google.com/go/auth v0.20.0 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect - cloud.google.com/go/compute/metadata v0.9.0 // indirect - dario.cat/mergo v1.0.2 // indirect - filippo.io/edwards25519 v1.2.0 // indirect - github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/chainguard-dev/clog v1.8.0 // indirect - github.com/chainguard-dev/go-pkgconfig v0.0.0-20240404163941-6351b37b2a10 // indirect - github.com/chainguard-dev/yam v0.2.55 // indirect - github.com/charmbracelet/colorprofile v0.3.2 // indirect - github.com/charmbracelet/lipgloss v1.1.0 // indirect - github.com/charmbracelet/log v1.0.0 // indirect - github.com/charmbracelet/x/ansi v0.10.1 // indirect - github.com/charmbracelet/x/cellbuf v0.0.13 // indirect - github.com/charmbracelet/x/term v0.2.1 // indirect - github.com/clipperhouse/uax29/v2 v2.6.0 // indirect - github.com/cloudflare/circl v1.6.3 // indirect - github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect - github.com/containerd/errdefs v1.0.0 // indirect - github.com/containerd/errdefs/pkg v0.3.0 // indirect - github.com/containerd/stargz-snapshotter/estargz v0.18.2 // indirect - github.com/cyphar/filepath-securejoin v0.6.1 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/distribution/reference v0.6.0 // indirect - github.com/docker/cli v29.4.0+incompatible // indirect - github.com/docker/docker-credential-helpers v0.9.4 // indirect - github.com/docker/go-connections v0.6.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/dprotaso/go-yit v0.0.0-20250513224043-18a80f8f6df4 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/github/go-spdx/v2 v2.5.0 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.9.0 // indirect - github.com/go-git/go-git/v5 v5.19.1 // indirect - github.com/go-jose/go-jose/v3 v3.0.5 // indirect - github.com/go-logfmt/logfmt v0.6.1 // indirect - github.com/go-logr/logr v1.4.3 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/google/go-cmp v0.7.0 // indirect - github.com/google/go-licenses/v2 v2.0.1 // indirect - github.com/google/licenseclassifier/v2 v2.0.0 // indirect - github.com/google/s2a-go v0.1.9 // indirect - github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect - github.com/googleapis/gax-go/v2 v2.21.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-retryablehttp v0.7.8 // indirect - github.com/ijt/goparsify v0.0.0-20221203142333-3a5276334b8d // indirect - github.com/in-toto/attestation v1.2.0 // indirect - github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/joho/godotenv v1.5.1 // indirect - github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/kelseyhightower/envconfig v1.4.0 // indirect - github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/compress v1.18.5 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/klauspost/pgzip v1.2.6 // indirect - github.com/lucasb-eyer/go-colorful v1.2.0 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.19 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/moby/api v1.54.1 // indirect - github.com/moby/moby/client v0.4.0 // indirect - github.com/moby/sys/sequential v0.6.0 // indirect - github.com/moby/term v0.5.2 // indirect - github.com/muesli/termenv v0.16.0 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.1 // indirect - github.com/package-url/packageurl-go v0.1.5 // indirect - github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0 // indirect - github.com/pierrec/lz4/v4 v4.1.22 // indirect - github.com/pjbgf/sha1cd v0.6.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.23.2 // indirect - github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.67.5 // indirect - github.com/prometheus/procfs v0.20.1 // indirect - github.com/psanford/memfs v0.0.0-20241019191636-4ef911798f9b // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/sirupsen/logrus v1.9.4 // indirect - github.com/skeema/knownhosts v1.3.1 // indirect - github.com/spdx/tools-golang v0.5.7 // indirect - github.com/spf13/afero v1.14.0 // indirect - github.com/spf13/pflag v1.0.10 // indirect - github.com/u-root/u-root v0.16.0 // indirect - github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect - github.com/ulikunitz/xz v0.5.15 // indirect - github.com/vbatts/tar-split v0.12.2 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - github.com/yookoala/realpath v1.0.0 // indirect - github.com/zealic/xignore v0.3.3 // indirect - go.lsp.dev/uri v0.3.0 // indirect - go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 // indirect - go.opentelemetry.io/otel v1.43.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 // indirect - go.opentelemetry.io/otel/metric v1.43.0 // indirect - go.opentelemetry.io/otel/sdk v1.43.0 // indirect - go.opentelemetry.io/otel/trace v1.43.0 // indirect - go.step.sm/crypto v0.77.2 // indirect - go.yaml.in/yaml/v2 v2.4.4 // indirect - golang.org/x/crypto v0.50.0 // indirect - golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect - golang.org/x/mod v0.35.0 // indirect - golang.org/x/net v0.53.0 // indirect - golang.org/x/oauth2 v0.36.0 // indirect - golang.org/x/sync v0.20.0 // indirect - golang.org/x/sys v0.43.0 // indirect - golang.org/x/term v0.42.0 // indirect - golang.org/x/text v0.36.0 // indirect - golang.org/x/time v0.15.0 // indirect - golang.org/x/tools v0.44.0 // indirect - google.golang.org/api v0.276.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect - google.golang.org/grpc v1.80.0 // indirect - google.golang.org/protobuf v1.36.11 // indirect - gopkg.in/ini.v1 v1.67.1 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect - k8s.io/apimachinery v0.35.4 // indirect - k8s.io/klog/v2 v2.130.1 // indirect - mvdan.cc/sh/v3 v3.13.1 // indirect - sigs.k8s.io/release-utils v0.12.4 // indirect -) diff --git a/scanner-audit/go.sum b/scanner-audit/go.sum deleted file mode 100644 index e25c622..0000000 --- a/scanner-audit/go.sum +++ /dev/null @@ -1,534 +0,0 @@ -chainguard.dev/apko v1.2.7 h1:Wlw6HJjbNnYy29dcTPz5lGdWpRhpEuwYtQapAPaAFWo= -chainguard.dev/apko v1.2.7/go.mod h1:JzjuFno6z5Up2BctVE/sZevJoGjBAu3OtuYwwJd6f58= -chainguard.dev/go-grpc-kit v0.17.16 h1:Y9RKwZCnrYR3S0K8BiazyOoBrZF+Q7bJWDacfKXz2zg= -chainguard.dev/go-grpc-kit v0.17.16/go.mod h1:0vrfIBJguXNa+EKOUEhx1Fj2aBp8o6A8gAHoidiF8ps= -chainguard.dev/melange v0.50.2 h1:l/0rrYSsaYhmQKH1XM+H5UWoeTJHH+lQdXZfZYYk5Wk= -chainguard.dev/melange v0.50.2/go.mod h1:LNnQ6b5OFvHhaoIQMe03sZ1Yg0R0uXpQ4yM1ah3b+yE= -chainguard.dev/sdk v0.1.52 h1:G1wmZHU8v5E78YlCHuwQH0Hwt4NBBCvCNAFad5FUanQ= -chainguard.dev/sdk v0.1.52/go.mod h1:IZIiUyuNaxTao6mpC/BROsw/dwjl/DmCR/raIT7eK4c= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA= -cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q= -cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= -cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= -cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= -cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo= -filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc= -github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= -github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= -github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= -github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chainguard-dev/clog v1.8.0 h1:frlTMEdg3XQR+ioQ6O9i92uigY8GTUcWKpuCFkhcCHA= -github.com/chainguard-dev/clog v1.8.0/go.mod h1:5MQOZi+Iu7fV7GcJG8ag8rCB5elEOpqRMKEASgnGVdo= -github.com/chainguard-dev/go-pkgconfig v0.0.0-20240404163941-6351b37b2a10 h1:XR2vgQC024I9/boh9r1ihVv8Z14+pbvWqXeYMCnZJpc= -github.com/chainguard-dev/go-pkgconfig v0.0.0-20240404163941-6351b37b2a10/go.mod h1:1p6+MesLcjKeON5BRWa7I87mvAY0QmKjgginIM3w6BI= -github.com/chainguard-dev/yam v0.2.55 h1:Uc0yovNO9fVEFMgFGSL6UUc/v7UUpsssrZl90OeX1eE= -github.com/chainguard-dev/yam v0.2.55/go.mod h1:Sbt8pVO8DbHoVly44oF5gg03NRxl9AhEImOkqGyoQCs= -github.com/charmbracelet/colorprofile v0.3.2 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI= -github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI= -github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= -github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= -github.com/charmbracelet/log v1.0.0 h1:HVVVMmfOorfj3BA9i8X8UL69Hoz9lI0PYwXfJvOdRc4= -github.com/charmbracelet/log v1.0.0/go.mod h1:uYgY3SmLpwJWxmlrPwXvzVYujxis1vAKRV/0VQB7yWA= -github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ= -github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= -github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k= -github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= -github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= -github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/clipperhouse/uax29/v2 v2.6.0 h1:z0cDbUV+aPASdFb2/ndFnS9ts/WNXgTNNGFoKXuhpos= -github.com/clipperhouse/uax29/v2 v2.6.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= -github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= -github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ= -github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w= -github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= -github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= -github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= -github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= -github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= -github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= -github.com/containerd/stargz-snapshotter/estargz v0.18.2 h1:yXkZFYIzz3eoLwlTUZKz2iQ4MrckBxJjkmD16ynUTrw= -github.com/containerd/stargz-snapshotter/estargz v0.18.2/go.mod h1:XyVU5tcJ3PRpkA9XS2T5us6Eg35yM0214Y+wvrZTBrY= -github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= -github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= -github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= -github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= -github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v29.4.0+incompatible h1:+IjXULMetlvWJiuSI0Nbor36lcJ5BTcVpUmB21KBoVM= -github.com/docker/cli v29.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM= -github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.9.4 h1:76ItO69/AP/V4yT9V4uuuItG0B1N8hvt0T0c0NN/DzI= -github.com/docker/docker-credential-helpers v0.9.4/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c= -github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= -github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dprotaso/go-yit v0.0.0-20250513224043-18a80f8f6df4 h1:JzpdVajvTuXQXL10D0vId1ZcW9alSJ3H0CnZczzz4ec= -github.com/dprotaso/go-yit v0.0.0-20250513224043-18a80f8f6df4/go.mod h1:lHwJo6jMevQL9tNpW6vLyhkK13bYHBcoh9tUakMhbnE= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= -github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= -github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/github/go-spdx/v2 v2.5.0 h1:ULLZ0ZEBOspdLD4PAmADzLYhh9GXLFEalKx3wpp3iFY= -github.com/github/go-spdx/v2 v2.5.0/go.mod h1:Ftc45YYG1WzpzwEPKRVm9Jv8vDqOrN4gWoCkK+bHer0= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.9.0 h1:jItGXszUDRtR/AlferWPTMN4j38BQ88XnXKbilmmBPA= -github.com/go-git/go-billy/v5 v5.9.0/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.19.1 h1:nX27AnaU43/K5bKktKwgBmR9lawoYVe1Ckg0rgzzN00= -github.com/go-git/go-git/v5 v5.19.1/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ= -github.com/go-jose/go-jose/v3 v3.0.5 h1:BLLJWbC4nMZOfuPVxoZIxeYsn6Nl2r1fITaJ78UQlVQ= -github.com/go-jose/go-jose/v3 v3.0.5/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= -github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE= -github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= -github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/go-containerregistry v0.21.5 h1:KTJG9Pn/jC0VdZR6ctV3/jcN+q6/Iqlx0sTVz3ywZlM= -github.com/google/go-containerregistry v0.21.5/go.mod h1:ySvMuiWg+dOsRW0Hw8GYwfMwBlNRTmpYBFJPlkco5zU= -github.com/google/go-licenses/v2 v2.0.1 h1:ti+9bi5o7DKbeeg5eBb/uZTgsaPNoJaLCh93cRcXsW8= -github.com/google/go-licenses/v2 v2.0.1/go.mod h1:efibo0EDNGkau6AIMOViGW+rTNPudhxX9rCxtfw5zKE= -github.com/google/go-replayers/httpreplay v1.2.0 h1:VM1wEyyjaoU53BwrOnaf9VhAyQQEEioJvFYxYcLRKzk= -github.com/google/go-replayers/httpreplay v1.2.0/go.mod h1:WahEFFZZ7a1P4VM1qEeHy+tME4bwyqPcwWbNlUI1Mcg= -github.com/google/licenseclassifier/v2 v2.0.0 h1:1Y57HHILNf4m0ABuMVb6xk4vAJYEUO0gDxNpog0pyeA= -github.com/google/licenseclassifier/v2 v2.0.0/go.mod h1:cOjbdH0kyC9R22sdQbYsFkto4NGCAc+ZSwbeThazEtM= -github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= -github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= -github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= -github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8= -github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= -github.com/googleapis/gax-go/v2 v2.21.0 h1:h45NjjzEO3faG9Lg/cFrBh2PgegVVgzqKzuZl/wMbiI= -github.com/googleapis/gax-go/v2 v2.21.0/go.mod h1:But/NJU6TnZsrLai/xBAQLLz+Hc7fHZJt/hsCz3Fih4= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 h1:QGLs/O40yoNK9vmy4rhUGBVyMf1lISBGtXRpsu/Qu/o= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0/go.mod h1:hM2alZsMUni80N33RBe6J0e423LB+odMj7d3EMP9l20= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= -github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= -github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= -github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= -github.com/ijt/goparsify v0.0.0-20221203142333-3a5276334b8d h1:LFOmpWrSbtolg0YqYC9hQjj5WSLtRGb6aZ3JAugLfgg= -github.com/ijt/goparsify v0.0.0-20221203142333-3a5276334b8d/go.mod h1:112TOyA+aruNSUBlyBWlKBdLVYTdhjiO2CKD0j/URSU= -github.com/in-toto/attestation v1.2.0 h1:aPRUZ3azbqD7yEBD5fP3TD8Dszf+YHo284SOcpahjQk= -github.com/in-toto/attestation v1.2.0/go.mod h1:r79G45gOmzPismgObLSL+rZTFxUgZLOQJI6LofTZgXk= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= -github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= -github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= -github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= -github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= -github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= -github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= -github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= -github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/moby/api v1.54.1 h1:TqVzuJkOLsgLDDwNLmYqACUuTehOHRGKiPhvH8V3Nn4= -github.com/moby/moby/api v1.54.1/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= -github.com/moby/moby/client v0.4.0 h1:S+2XegzHQrrvTCvF6s5HFzcrywWQmuVnhOXe2kiWjIw= -github.com/moby/moby/client v0.4.0/go.mod h1:QWPbvWchQbxBNdaLSpoKpCdf5E+WxFAgNHogCWDoa7g= -github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= -github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs= -github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= -github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= -github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= -github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= -github.com/morikuni/aec v1.1.0 h1:vBBl0pUnvi/Je71dsRrhMBtreIqNMYErSAbEeb8jrXQ= -github.com/morikuni/aec v1.1.0/go.mod h1:xDRgiq/iw5l+zkao76YTKzKttOp2cwPEne25HDkJnBw= -github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= -github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= -github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= -github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= -github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/package-url/packageurl-go v0.1.5 h1:O4efRXja2XQ5CtiiYiCZ22k/m7i5ugLiAghgcC+eDgk= -github.com/package-url/packageurl-go v0.1.5/go.mod h1:nKAWB8E6uk1MHqiS/lQb9pYBGH2+mdJ2PJc2s50dQY0= -github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0 h1:2nosf3P75OZv2/ZO/9Px5ZgZ5gbKrzA3joN1QMfOGMQ= -github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0/go.mod h1:lAVhWwbNaveeJmxrxuSTxMgKpF6DjnuVpn6T8WiBwYQ= -github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= -github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pjbgf/sha1cd v0.6.0 h1:3WJ8Wz8gvDz29quX1OcEmkAlUg9diU4GxJHqs0/XiwU= -github.com/pjbgf/sha1cd v0.6.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= -github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= -github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= -github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= -github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= -github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= -github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= -github.com/psanford/memfs v0.0.0-20241019191636-4ef911798f9b h1:xzjEJAHum+mV5Dd5KyohRlCyP03o4yq6vNpEUtAJQzI= -github.com/psanford/memfs v0.0.0-20241019191636-4ef911798f9b/go.mod h1:tcaRap0jS3eifrEEllL6ZMd9dg8IlDpi2S1oARrQ+NI= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= -github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= -github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= -github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= -github.com/spdx/tools-golang v0.5.7 h1:+sWcKGnhwp3vLdMqPcLdA6QK679vd86cK9hQWH3AwCg= -github.com/spdx/tools-golang v0.5.7/go.mod h1:jg7w0LOpoNAw6OxKEzCoqPC2GCTj45LyTlVmXubDsYw= -github.com/spf13/afero v1.2.0/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= -github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= -github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= -github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= -github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= -github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/u-root/u-root v0.16.0 h1:wY40O83MBVks97+Is0WlFlOPSwKQMIrWP9R1IsrExg8= -github.com/u-root/u-root v0.16.0/go.mod h1:yL/XdSSW27PdGLgUh4MNRBy54mKM+TBLzpwiB4nwj90= -github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM= -github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA= -github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= -github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= -github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= -github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= -github.com/yookoala/realpath v1.0.0 h1:7OA9pj4FZd+oZDsyvXWQvjn5oBdcHRTV44PpdMSuImQ= -github.com/yookoala/realpath v1.0.0/go.mod h1:gJJMA9wuX7AcqLy1+ffPatSCySA1FQ2S8Ya9AIoYBpE= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zealic/xignore v0.3.3 h1:EpLXUgZY/JEzFkTc+Y/VYypzXtNz+MSOMVCGW5Q4CKQ= -github.com/zealic/xignore v0.3.3/go.mod h1:lhS8V7fuSOtJOKsvKI7WfsZE276/7AYEqokv3UiqEAU= -go.lsp.dev/uri v0.3.0 h1:KcZJmh6nFIBeJzTugn5JTU6OOyG0lDOo3R9KwTxTYbo= -go.lsp.dev/uri v0.3.0/go.mod h1:P5sbO1IQR+qySTWOCnhnK7phBx+W3zbLqSMDJNTw88I= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= -go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 h1:yI1/OhfEPy7J9eoa6Sj051C7n5dvpj0QX8g4sRchg04= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0/go.mod h1:NoUCKYWK+3ecatC4HjkRktREheMeEtrXoQxrqYFeHSc= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 h1:OyrsyzuttWTSur2qN/Lm0m2a8yqyIjUVBZcxFPuXq2o= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0/go.mod h1:C2NGBr+kAB4bk3xtMXfZ94gqFDtg/GkI7e9zqGh5Beg= -go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= -go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0 h1:THuZiwpQZuHPul65w4WcwEnkX2QIuMT+UFoOrygtoJw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0/go.mod h1:J2pvYM5NGHofZ2/Ru6zw/TNWnEQp5crgyDeSrYpXkAw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 h1:mS47AX77OtFfKG4vtp+84kuGSFZHTyxtXIN269vChY0= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0/go.mod h1:PJnsC41lAGncJlPUniSwM81gc80GkgWJWr3cu2nKEtU= -go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= -go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= -go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= -go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= -go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= -go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= -go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= -go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= -go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= -go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= -go.step.sm/crypto v0.77.2 h1:qFjjei+RHc5kP5R7NW9OUWT7SqWIuAOvOkXqg4fNWj8= -go.step.sm/crypto v0.77.2/go.mod h1:W0YJb9onM5l78qgkXIJ2Up6grnwW8EtpCKIza/NCg0o= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= -go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= -go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= -go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= -golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= -golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= -golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= -golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= -golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= -golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= -golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= -golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= -golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= -golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= -gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/api v0.276.0 h1:nVArUtfLEihtW+b0DdcqRGK1xoEm2+ltAihyztq7MKY= -google.golang.org/api v0.276.0/go.mod h1:Fnag/EWUPIcJXuIkP1pjoTgS5vdxlk3eeemL7Do6bvw= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 h1:XzmzkmB14QhVhgnawEVsOn6OFsnpyxNPRY9QV01dNB0= -google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:L43LFes82YgSonw6iTXTxXUX1OlULt4AQtkik4ULL/I= -google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA= -google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= -google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/ini.v1 v1.67.1 h1:tVBILHy0R6e4wkYOn3XmiITt/hEVH4TFMYvAX2Ytz6k= -gopkg.in/ini.v1 v1.67.1/go.mod h1:x/cyOwCgZqOkJoDIJ3c1KNHMo10+nLGAhh+kn3Zizss= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= -gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/apimachinery v0.35.4 h1:xtdom9RG7e+yDp71uoXoJDWEE2eOiHgeO4GdBzwWpds= -k8s.io/apimachinery v0.35.4/go.mod h1:NNi1taPOpep0jOj+oRha3mBJPqvi0hGdaV8TCqGQ+cc= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -mvdan.cc/sh/v3 v3.13.1 h1:DP3TfgZhDkT7lerUdnp6PTGKyxxzz6T+cOlY/xEvfWk= -mvdan.cc/sh/v3 v3.13.1/go.mod h1:lXJ8SexMvEVcHCoDvAGLZgFJ9Wsm2sulmoNEXGhYZD0= -pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= -pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= -sigs.k8s.io/release-utils v0.12.4 h1:kuG6WTWGCKx5uUrJwl2uFErOKOw+4Ba8WrPmOQh5J3g= -sigs.k8s.io/release-utils v0.12.4/go.mod h1:Tc3iM9DVM3W9oJu/6rEI+LnREuhy8lZ7wInQhRBtUoo= diff --git a/scanner-audit/main.go b/scanner-audit/main.go deleted file mode 100644 index 236f77b..0000000 --- a/scanner-audit/main.go +++ /dev/null @@ -1,1322 +0,0 @@ -/* -Copyright 2025 Chainguard, Inc. -SPDX-License-Identifier: Apache-2.0 -*/ - -package main - -import ( - "bufio" - "context" - "crypto/sha256" - "embed" - _ "embed" - "encoding/json" - "fmt" - "html/template" - "io" - "net/http" - "os" - "path/filepath" - "slices" - "strings" - "time" - - "chainguard.dev/apko/pkg/build" - "chainguard.dev/apko/pkg/build/oci" - "chainguard.dev/apko/pkg/build/types" - "chainguard.dev/apko/pkg/tarfs" - mbuild "chainguard.dev/melange/pkg/build" - mcli "chainguard.dev/melange/pkg/cli" - "chainguard.dev/melange/pkg/config" - "chainguard.dev/melange/pkg/container/docker" - "github.com/adrg/xdg" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/client" - "github.com/google/go-containerregistry/pkg/name" - "github.com/google/go-containerregistry/pkg/v1/daemon" - "github.com/google/go-containerregistry/pkg/v1/empty" - "github.com/spf13/cobra" - "gopkg.in/yaml.v3" -) - -type TestCase struct { - Name string - Distro string - Passed bool - Skipped bool - FalsePos []string - FalseNeg []string - StderrOutput string - DockerCmd string - ActualCVEs []string - ExpectedCVEs []string - DocLink string - ExitCode int -} - -type DistroResults struct { - Name string - TestCases []TestCase - Passed bool - Skipped bool - FailedTests int - ExecutedTests int -} - -type AuditReport struct { - Distros []DistroResults - Timestamp time.Time - OverallPassed bool - TotalTests int - ExecutedTests int - SkippedTests int - ExecutedDistros int - SkippedDistros int - ScannerInfo ScannerInfo -} - -type ScannerInfo struct { - EnvName string - AuditEnvContent string - WrapperScript string - RequiredVars []string - WrapperImage string -} - -//go:embed env/* -var envFS embed.FS - -var allDistros = []string{"chainguard", "wolfi"} - -var testCaseNames = []string{ - "false-positive-language-package-vulnerabilities", - "false-positives-from-lock-files", - "fixed-language-package-vulnerabilities", - "fixed-vulnerabilities", - "no-software", - "subpackage-fixed-vulnerabilities", - "subpackage-unfixed-vulnerabilities", - "unfixed-vulnerabilities", - "unfixed-vulnerabilities-layered", - "unfixed-vulnerabilities-chainguard-layered", -} - -// generateTestCaseImages dynamically generates the test case images map -func generateTestCaseImages() map[string]map[string]string { - images := make(map[string]map[string]string) - for _, distro := range allDistros { - images[distro] = make(map[string]string) - for _, testCase := range testCaseNames { - images[distro][testCase] = fmt.Sprintf("ghcr.io/chainguard-images/scanner-test:%s-%s", testCase, distro) - } - } - return images -} - -var testCaseImages = generateTestCaseImages() - -// generateTestCaseDocLinks dynamically generates the test case documentation links -func generateTestCaseDocLinks() map[string]string { - links := make(map[string]string) - for _, testCase := range testCaseNames { - links[testCase] = fmt.Sprintf("https://github.com/chainguard-dev/vulnerability-scanner-support/blob/main/docs/verifying_scan_results.md#%s", testCase) - } - return links -} - -var testCaseDocLinks = generateTestCaseDocLinks() - -const ( - dockerStdoutStream = 1 - dockerStderrStream = 2 - requiresDockerVar = "REQUIRES_DOCKER" -) - -func main() { - var ( - envName, filterDistro, filterTestCase, answersChainguard, answersWolfi, outputPath string - forceBuild, noRemove, noCache bool - ) - - rootCmd := &cobra.Command{ - Use: "scanner-audit", - Short: "Audit vulnerability scanners against Chainguard test cases", - Long: `Scanner Audit validates vulnerability scanner implementations against -Chainguard's official test cases for Chainguard Images and packages. - -This tool builds a Docker wrapper image using Melange and Apko (as Go libraries), -then runs your scanner script against the official test case images. -Results are compared against the expected CVE lists and a detailed -HTML report is generated. - -Requirements: -- Docker must be installed and running -- The script must output CVE IDs to stdout, one per line - -Example usage: - scanner-audit --env trivy`, - PreRunE: func(cmd *cobra.Command, args []string) error { - if envName == "" { - return fmt.Errorf("--env flag is required") - } - - // Validate distro flag - if filterDistro != "" && !slices.Contains(allDistros, filterDistro) { - return fmt.Errorf("--distro must be one of: %s, got '%s'", strings.Join(allDistros, " or "), filterDistro) - } - - // Validate test case flag - if filterTestCase != "" { - validTestCase := slices.Contains(testCaseNames, filterTestCase) - if !validTestCase { - return fmt.Errorf("--test-case must be one of: %s", strings.Join(testCaseNames, ", ")) - } - } - - // Validate env exists - auditEnvPath := fmt.Sprintf("env/%s-audit-env.yaml", envName) - wrapperPath := fmt.Sprintf("env/%s-wrapper.sh", envName) - - if _, err := envFS.ReadFile(auditEnvPath); err != nil { - return fmt.Errorf("env '%s' not found: missing %s", envName, auditEnvPath) - } - if _, err := envFS.ReadFile(wrapperPath); err != nil { - return fmt.Errorf("env '%s' not found: missing %s", envName, wrapperPath) - } - return nil - }, - Run: func(cmd *cobra.Command, args []string) { - if err := runAudit(envName, forceBuild, noRemove, noCache, filterDistro, filterTestCase, answersChainguard, answersWolfi, outputPath); err != nil { - fmt.Fprintf(os.Stderr, "Error: %v\n", err) - os.Exit(1) - } - }, - } - - rootCmd.Flags().StringVar(&envName, "env", "", "Scanner environment name (required)") - rootCmd.Flags().BoolVar(&forceBuild, "force-build", false, "Force rebuild of wrapper image even if it exists") - rootCmd.Flags().BoolVar(&noRemove, "no-remove", false, "Do not remove the container after finished running tests") - rootCmd.Flags().BoolVar(&noCache, "no-cache", false, "Do not mount the XDG cache directory to the container") - rootCmd.Flags().StringVarP(&filterDistro, "distro", "d", "", "Filter to specific distro: 'chainguard' or 'wolfi'") - rootCmd.Flags().StringVarP(&filterTestCase, "test-case", "t", "", "Filter to specific test case name") - rootCmd.Flags().StringVar(&answersChainguard, "answers-chainguard", "", "Path or URL to Chainguard answers file (default: GitHub raw URL)") - rootCmd.Flags().StringVar(&answersWolfi, "answers-wolfi", "", "Path or URL to Wolfi answers file (default: GitHub raw URL)") - rootCmd.Flags().StringVarP(&outputPath, "output", "o", "report.html", "Path to output the HTML report (default: report.html)") - - if err := rootCmd.Execute(); err != nil { - fmt.Fprintf(os.Stderr, "Error: %v\n", err) - os.Exit(1) - } -} - -func runAudit(envName string, forceBuild, noRemove, noCache bool, filterDistro, filterTestCase, answersChainguard, answersWolfi, outputPath string) error { - fmt.Println("Starting scanner audit...") - - // Read embedded files - auditEnvPath := fmt.Sprintf("env/%s-audit-env.yaml", envName) - wrapperPath := fmt.Sprintf("env/%s-wrapper.sh", envName) - - auditEnvContent, err := envFS.ReadFile(auditEnvPath) - if err != nil { - return fmt.Errorf("failed to read audit env file: %w", err) - } - - wrapperContent, err := envFS.ReadFile(wrapperPath) - if err != nil { - return fmt.Errorf("failed to read wrapper script: %w", err) - } - - // Extract required environment variables from melange YAML - requiredEnvVars, err := extractRequiredEnvVars(auditEnvContent) - if err != nil { - return fmt.Errorf("failed to extract required environment variables: %w", err) - } - - // Validate required environment variables - if err := validateEnvironmentVars(requiredEnvVars); err != nil { - return fmt.Errorf("environment validation failed: %w", err) - } - - // Create and test Docker client - ctx := context.Background() - dockerClient, err := createDockerClient(ctx) - if err != nil { - return err - } - defer dockerClient.Close() - - // Build wrapper image - wrapperImage, err := buildWrapperImage(envName, auditEnvContent, forceBuild) - if err != nil { - return fmt.Errorf("failed to build wrapper image: %w", err) - } - - // Start a single long-running container - containerID, err := startLongRunningContainer(dockerClient, wrapperImage, wrapperContent, noCache, requiredEnvVars) - if err != nil { - return fmt.Errorf("failed to start container: %w", err) - } - - // Remove the container after everything - // TODO: handle signals better - defer func() { - if noRemove { - fmt.Printf("Not removing container %s\n", containerID) - } else if removeErr := dockerClient.ContainerRemove(context.Background(), containerID, container.RemoveOptions{Force: true}); removeErr != nil { - fmt.Printf("Warning: failed to remove container %s: %v\n", containerID, removeErr) - } - }() - - // Run scans against all test cases - distroResults, err := runScans(dockerClient, containerID, requiredEnvVars, filterDistro, filterTestCase, answersChainguard, answersWolfi) - if err != nil { - return fmt.Errorf("failed to run scans: %w", err) - } - - // Generate report - type testStats struct { - totalTests int - executedTests int - skippedTests int - executedDistros int - skippedDistros int - overallPassed bool - hasNonSkippedDistros bool - } - - stats := testStats{overallPassed: true} - - for _, distro := range distroResults { - stats.totalTests += len(distro.TestCases) - - if distro.Skipped { - stats.skippedDistros++ - // All test cases in a skipped distro are considered skipped - stats.skippedTests += len(distro.TestCases) - } else { - hasExecutedTests := false - for _, testCase := range distro.TestCases { - if testCase.Skipped { - stats.skippedTests++ - } else { - stats.executedTests++ - hasExecutedTests = true - } - } - if hasExecutedTests { - stats.executedDistros++ - stats.hasNonSkippedDistros = true - } - if !distro.Passed { - stats.overallPassed = false - } - } - } - - // If no non-skipped distros were tested, consider overall as passed - if !stats.hasNonSkippedDistros { - stats.overallPassed = true - } - - scannerInfo := ScannerInfo{ - EnvName: envName, - AuditEnvContent: string(auditEnvContent), - WrapperScript: string(wrapperContent), - RequiredVars: requiredEnvVars, - WrapperImage: wrapperImage, - } - - report := AuditReport{ - Distros: distroResults, - Timestamp: time.Now(), - OverallPassed: stats.overallPassed, - TotalTests: stats.totalTests, - ExecutedTests: stats.executedTests, - SkippedTests: stats.skippedTests, - ExecutedDistros: stats.executedDistros, - SkippedDistros: stats.skippedDistros, - ScannerInfo: scannerInfo, - } - - if err := generateHTMLReport(report, outputPath); err != nil { - return fmt.Errorf("failed to generate HTML report: %w", err) - } - - fmt.Printf("Audit complete. Report generated: %s\n", outputPath) - fmt.Printf("Overall result: ") - if stats.overallPassed { - fmt.Println("PASSED") - } else { - fmt.Println("FAILED") - return fmt.Errorf("one or more test cases failed") - } - - return nil -} - -func createDockerClient(ctx context.Context) (*client.Client, error) { - dockerClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) - if err != nil { - return nil, fmt.Errorf("failed to create Docker client (ensure Docker is running): %w", err) - } - - // Test Docker connection - if _, err := dockerClient.Ping(ctx); err != nil { - dockerClient.Close() - return nil, fmt.Errorf("failed to connect to Docker daemon (ensure Docker is running): %w", err) - } - - return dockerClient, nil -} - -func extractRequiredEnvVars(auditEnvContent []byte) ([]string, error) { - var c config.Configuration - if err := yaml.Unmarshal(auditEnvContent, &c); err != nil { - return nil, fmt.Errorf("failed to parse melange YAML: %w", err) - } - - var requiredVars []string - for envVar := range c.Environment.Environment { - requiredVars = append(requiredVars, envVar) - } - - // Sort for consistent ordering - slices.Sort(requiredVars) - return requiredVars, nil -} - -func validateEnvironmentVars(requiredEnvVars []string) error { - var missing []string - var invalid []string - - for _, envVar := range requiredEnvVars { - // Skip REQUIRES_DOCKER - it's optional and not treated as a masked variable - if envVar == requiresDockerVar { - continue - } - - value := os.Getenv(envVar) - if value == "" { - missing = append(missing, envVar) - } else if value == "placeholder" { - invalid = append(invalid, envVar) - } - } - - var errors []string - if len(missing) > 0 { - errors = append(errors, fmt.Sprintf("missing required environment variables: %s", strings.Join(missing, ", "))) - } - if len(invalid) > 0 { - errors = append(errors, fmt.Sprintf("environment variables still set to 'placeholder': %s", strings.Join(invalid, ", "))) - } - - if len(errors) > 0 { - return fmt.Errorf(strings.Join(errors, "; ")) - } - return nil -} - -func buildWrapperImage(envName string, auditEnvContent []byte, forceBuild bool) (string, error) { - fmt.Printf("Building wrapper image for env '%s'...\n", envName) - - ctx := context.Background() - - // Create a unique image name based on the env name - imageName := fmt.Sprintf("scanner-audit-%s:latest", envName) - - // Check if Docker image already exists (unless forceBuild is true) - if !forceBuild { - if imageExists, err := checkDockerImageExists(imageName); err == nil && imageExists { - fmt.Printf("Using existing wrapper image: %s\n", imageName) - return imageName, nil - } - } - - // Create a temporary directory for building - tempDir, err := os.MkdirTemp("", "scanner-audit-build-*") - if err != nil { - return "", fmt.Errorf("failed to create temp directory: %w", err) - } - defer os.RemoveAll(tempDir) - - // Prepare directories - packageDir := filepath.Join(tempDir, "packages") - signingKey := filepath.Join(tempDir, "melange.rsa") - pubKey := filepath.Join(tempDir, "melange.rsa.pub") - - // Generate signing keys - fmt.Printf("Generating signing keys...\n") - if err := mcli.KeygenCmd(ctx, signingKey, 4096); err != nil { - return "", fmt.Errorf("failed to generate keypair: %w", err) - } - - // Create Docker runner for melange - runner, err := docker.NewRunner(ctx) - if err != nil { - return "", fmt.Errorf("failed to create melange runner: %w", err) - } - - // Write audit env file to temp directory - melangeFile := filepath.Join(tempDir, "audit-env.yaml") - if err := os.WriteFile(melangeFile, auditEnvContent, 0644); err != nil { - return "", fmt.Errorf("failed to write audit env file: %w", err) - } - - // Configure melange build context - arch := types.ParseArchitecture("x86_64") - bc, err := mbuild.New(ctx, []mbuild.Option{ - mbuild.WithConfig(melangeFile), - mbuild.WithArch(arch), - mbuild.WithGenerateIndex(true), - mbuild.WithSigningKey(signingKey), - mbuild.WithRunner(runner), - mbuild.WithOutDir(packageDir), - mbuild.WithSourceDir(tempDir), - mbuild.WithConfigFileRepositoryURL("https://github.com/chainguard-dev/vulnerability-scanner-support"), - mbuild.WithConfigFileRepositoryCommit("TODO"), - mbuild.WithExtraRepos([]string{"https://packages.wolfi.dev/os"}), - mbuild.WithExtraKeys([]string{"https://packages.wolfi.dev/os/wolfi-signing.rsa.pub"}), - }...) - if err != nil { - return "", fmt.Errorf("failed to create melange build context: %w", err) - } - - // Build package with melange - fmt.Printf("Building package with melange...\n") - if err := bc.BuildPackage(ctx); err != nil { - return "", fmt.Errorf("failed to build package with melange: %w", err) - } - - // Extract package name from melange file for apko - packageName := bc.Configuration.Name() - - // Configure apko image - ic := types.ImageConfiguration{ - Contents: types.ImageContents{ - Repositories: []string{packageDir, "https://packages.wolfi.dev/os"}, - Keyring: []string{pubKey, "https://packages.wolfi.dev/os/wolfi-signing.rsa.pub"}, - Packages: []string{packageName, "busybox", "bash", "jq"}, - }, - Entrypoint: types.ImageEntrypoint{ - Command: "/bin/bash", - }, - Environment: map[string]string{ - "PATH": "/usr/sbin:/sbin:/usr/bin:/bin", - }, - } - - // Build with apko - fmt.Printf("Building container image with apko...\n") - opts := []build.Option{ - build.WithArch(arch), - build.WithImageConfiguration(ic), - } - - apkoBuild, err := build.New(ctx, tarfs.New(), opts...) - if err != nil { - return "", fmt.Errorf("failed to create apko build context: %w", err) - } - - // Build the layer - _, layer, err := apkoBuild.BuildLayer(ctx) - if err != nil { - return "", fmt.Errorf("failed to build layer: %w", err) - } - - // Get build date epoch - bde, err := apkoBuild.GetBuildDateEpoch() - if err != nil { - return "", fmt.Errorf("failed to determine build date epoch: %w", err) - } - - // Build OCI image from layer - img, err := oci.BuildImageFromLayer(ctx, empty.Image, layer, ic, bde, arch) - if err != nil { - return "", fmt.Errorf("failed to build OCI image: %w", err) - } - - // Save image to local Docker daemon - fmt.Printf("Saving image to Docker daemon...\n") - tag, err := name.NewTag(imageName) - if err != nil { - return "", fmt.Errorf("failed to create image tag: %w", err) - } - - _, err = daemon.Write(tag, img, daemon.WithContext(ctx)) - if err != nil { - return "", fmt.Errorf("failed to save image to Docker daemon: %w", err) - } - - fmt.Printf("Wrapper image built successfully: %s\n", imageName) - return imageName, nil -} - -// checkDockerImageExists checks if a Docker image exists locally using Docker API -func checkDockerImageExists(imageName string) (bool, error) { - ctx := context.Background() - dockerClient, err := createDockerClient(ctx) - if err != nil { - return false, err - } - defer dockerClient.Close() - - // List images with the specified name - images, err := dockerClient.ImageList(ctx, image.ListOptions{ - All: false, - }) - if err != nil { - return false, fmt.Errorf("failed to list Docker images: %w", err) - } - - // Check if any image matches our name - for _, img := range images { - if slices.Contains(img.RepoTags, imageName) { - return true, nil - } - } - - return false, nil -} - -// getBaseCacheDir returns the base XDG cache directory for scanner-audit -func getBaseCacheDir() string { - return filepath.Join(xdg.CacheHome, "dev.chainguard.scanner-audit") -} - -// getCacheDir returns the XDG cache directory for scanner-audit cache mount -func getCacheDir() string { - return filepath.Join(getBaseCacheDir(), "cache-mount") -} - -func startLongRunningContainer(dockerClient *client.Client, wrapperImage string, wrapperContent []byte, noCache bool, requiredEnvVars []string) (string, error) { - ctx := context.Background() - - // Create container configuration - keep it alive with a sleep command - containerConfig := &container.Config{ - Image: wrapperImage, - Cmd: []string{"-c", "trap : TERM INT; sleep 9999999999d & wait"}, - AttachStdout: false, - AttachStderr: false, - } - - // Create wrapper script in base cache directory - baseCacheDir := getBaseCacheDir() - wrapperScriptsDir := filepath.Join(baseCacheDir, "wrapper-scripts") - - // Check if wrapper scripts directory exists - if _, err := os.Stat(wrapperScriptsDir); os.IsNotExist(err) { - fmt.Printf("Creating wrapper scripts directory: %s\n", wrapperScriptsDir) - if err := os.MkdirAll(wrapperScriptsDir, 0755); err != nil { - return "", fmt.Errorf("failed to create wrapper scripts directory: %w", err) - } - } - - // Calculate SHA-256 hash of the wrapper content - hash := sha256.Sum256(wrapperContent) - scriptPath := filepath.Join(wrapperScriptsDir, fmt.Sprintf("%x.sh", hash)) - - // Write wrapper script if it doesn't exist - if _, err := os.Stat(scriptPath); os.IsNotExist(err) { - fmt.Printf("Creating wrapper script file: %s\n", scriptPath) - if err := os.WriteFile(scriptPath, wrapperContent, 0755); err != nil { - return "", fmt.Errorf("failed to write wrapper script: %w", err) - } - } else { - fmt.Printf("Using existing wrapper script file: %s\n", scriptPath) - } - - // Prepare bind mounts - binds := []string{ - fmt.Sprintf("%s:/scanner-audit-wrapper", scriptPath), - } - - // Add cache mount unless --no-cache is specified - if !noCache { - cacheDir := getCacheDir() - // Check if cache directory exists - if _, err := os.Stat(cacheDir); os.IsNotExist(err) { - fmt.Printf("Creating cache mount directory: %s\n", cacheDir) - if err := os.MkdirAll(cacheDir, 0755); err != nil { - return "", fmt.Errorf("failed to create cache directory %s: %w", cacheDir, err) - } - } - binds = append(binds, fmt.Sprintf("%s:/root/.cache", cacheDir)) - fmt.Printf("Mounting cache directory: %s -> /root/.cache\n", cacheDir) - } - - // Check if REQUIRES_DOCKER is in requiredEnvVars and has a value - hasRequiresDocker := slices.Contains(requiredEnvVars, requiresDockerVar) - - // Add Docker socket mount if REQUIRES_DOCKER is set - if hasRequiresDocker { - binds = append(binds, "/var/run/docker.sock:/var/run/docker.sock") - fmt.Printf("Mounting Docker socket: /var/run/docker.sock -> /var/run/docker.sock\n") - } - - hostConfig := &container.HostConfig{ - Binds: binds, - } - - // Build docker command string for display - dockerCmd := fmt.Sprintf("docker run --rm -v :/scanner-audit-wrapper") - if !noCache { - dockerCmd += fmt.Sprintf(" -v %s:/root/.cache", getCacheDir()) - } - if hasRequiresDocker { - dockerCmd += " -v /var/run/docker.sock:/var/run/docker.sock" - } - dockerCmd += fmt.Sprintf(" %s -c 'trap : TERM INT; sleep 9999999999d & wait'", wrapperImage) - fmt.Printf("Running \"%s\"\n", dockerCmd) - - // Create the container - containerResp, err := dockerClient.ContainerCreate(ctx, containerConfig, hostConfig, nil, nil, "") - if err != nil { - return "", fmt.Errorf("failed to create container: %w", err) - } - - // Start the container - if err := dockerClient.ContainerStart(ctx, containerResp.ID, container.StartOptions{}); err != nil { - return "", fmt.Errorf("failed to start container: %w", err) - } - - fmt.Printf("Started long-running container: %s\n", containerResp.ID[:12]) - return containerResp.ID, nil -} - -func runScans(dockerClient *client.Client, containerID string, requiredEnvVars []string, filterDistro, filterTestCase, answersChainguard, answersWolfi string) ([]DistroResults, error) { - fmt.Println("Running scans against test case images...") - - var distroResults []DistroResults - - for _, distro := range allDistros { - // Check if this distro should be skipped - distroSkipped := filterDistro != "" && filterDistro != distro - - var testCases []TestCase - distroPassed := true - hasNonSkippedTests := false - - for _, testCaseName := range testCaseNames { - // Check if this test case should be skipped - testCaseSkipped := filterTestCase != "" && filterTestCase != testCaseName - - if distroSkipped || testCaseSkipped { - // Create a skipped test case - testCases = append(testCases, TestCase{ - Name: testCaseName, - Distro: distro, - Passed: false, - Skipped: true, - FalsePos: []string{}, - FalseNeg: []string{}, - StderrOutput: "Skipped due to filtering", - DockerCmd: "Skipped", - ActualCVEs: []string{}, - ExpectedCVEs: []string{}, - DocLink: testCaseDocLinks[testCaseName], - }) - continue - } - - hasNonSkippedTests = true - - testImage := testCaseImages[distro][testCaseName] - testCase, err := runSingleScan(dockerClient, containerID, testImage, testCaseName, distro, requiredEnvVars, answersChainguard, answersWolfi) - if err != nil { - return nil, fmt.Errorf("failed to run scan for %s/%s: %w", distro, testCaseName, err) - } - - testCases = append(testCases, testCase) - if !testCase.Passed { - distroPassed = false - } - } - - // If no non-skipped tests were run, consider the distro as passed - if !hasNonSkippedTests { - distroPassed = true - } - - // Calculate executed and failed test counts for this distro - executedTestsInDistro := 0 - failedTestsInDistro := 0 - for _, testCase := range testCases { - if !testCase.Skipped { - executedTestsInDistro++ - if !testCase.Passed { - failedTestsInDistro++ - } - } - } - - distroResults = append(distroResults, DistroResults{ - Name: distro, - TestCases: testCases, - Passed: distroPassed, - Skipped: distroSkipped, - FailedTests: failedTestsInDistro, - ExecutedTests: executedTestsInDistro, - }) - } - - return distroResults, nil -} - -func prepareEnvVarsAndCommand(requiredEnvVars []string, containerID, testImage string) ([]string, string) { - var envVars []string - var maskedEnvVars []string - - for _, envVar := range requiredEnvVars { - // Skip REQUIRES_DOCKER - it's not passed to the container - if envVar == requiresDockerVar { - continue - } - - value := os.Getenv(envVar) - envVars = append(envVars, fmt.Sprintf("%s=%s", envVar, value)) - maskedEnvVars = append(maskedEnvVars, fmt.Sprintf("%s=\"$%s\"", envVar, envVar)) // Show as env var reference - } - - // Build Docker command string for display (with env var references) - var dockerCmdParts []string - dockerCmdParts = append(dockerCmdParts, "docker exec") - for _, maskedEnv := range maskedEnvVars { - dockerCmdParts = append(dockerCmdParts, "-e", maskedEnv) - } - dockerCmdParts = append(dockerCmdParts, containerID[:12], "bash", "-e", fmt.Sprintf("/scanner-audit-wrapper %s", testImage)) - - return envVars, strings.Join(dockerCmdParts, " ") -} - -func runSingleScan(dockerClient *client.Client, containerID, testImage, testCaseName, distro string, requiredEnvVars []string, answersChainguard, answersWolfi string) (TestCase, error) { - fmt.Printf("Scanning %s (%s)...\n", testCaseName, distro) - - ctx := context.Background() - - // Prepare environment variables for the exec - envVars, dockerCmd := prepareEnvVarsAndCommand(requiredEnvVars, containerID, testImage) - fmt.Printf("Running %q\n", dockerCmd) - - // Create exec configuration - execConfig := container.ExecOptions{ - Cmd: []string{"bash", "-e", "/scanner-audit-wrapper", testImage}, - Env: envVars, - AttachStdout: true, - AttachStderr: true, - } - - // Create the exec - execResp, err := dockerClient.ContainerExecCreate(ctx, containerID, execConfig) - if err != nil { - return TestCase{}, fmt.Errorf("failed to create exec: %w", err) - } - - // Attach to exec to capture stdout and stderr - attachResp, err := dockerClient.ContainerExecAttach(ctx, execResp.ID, container.ExecAttachOptions{ - Detach: false, - }) - if err != nil { - return TestCase{}, fmt.Errorf("failed to attach to exec: %w", err) - } - defer attachResp.Close() - - // Start the exec - if err := dockerClient.ContainerExecStart(ctx, execResp.ID, container.ExecStartOptions{}); err != nil { - return TestCase{}, fmt.Errorf("failed to start exec: %w", err) - } - - // Capture stdout and stderr separately - stdoutChan := make(chan []string) - stderrChan := make(chan []string) - errorChan := make(chan error, 2) - - go func() { - stdout, stderr, err := separateDockerStreams(attachResp.Reader) - if err != nil { - errorChan <- err - return - } - stdoutChan <- stdout - stderrChan <- stderr - }() - - // Wait for the exec to finish - var exitCode int - for { - inspect, err := dockerClient.ContainerExecInspect(ctx, execResp.ID) - if err != nil { - return TestCase{}, fmt.Errorf("failed to inspect exec: %w", err) - } - if !inspect.Running { - exitCode = inspect.ExitCode - break - } - // Small delay to avoid busy waiting - time.Sleep(100 * time.Millisecond) - } - - // Get the captured outputs - var stdoutLines, stderrLines []string - select { - case stdoutLines = <-stdoutChan: - case err := <-errorChan: - return TestCase{}, fmt.Errorf("failed to capture container output: %w", err) - } - - select { - case stderrLines = <-stderrChan: - case err := <-errorChan: - return TestCase{}, fmt.Errorf("failed to capture container output: %w", err) - } - - // Parse CVEs from stdout (each line should be a CVE ID) - actualCVEs := parseCVEsFromOutput(stdoutLines) - - // Load expected results - expectedCVEs, optionalCVEs, err := loadExpectedCVEs(testCaseName, distro, answersChainguard, answersWolfi) - if err != nil { - return TestCase{}, fmt.Errorf("failed to load expected CVEs: %w", err) - } - - // Compare results - falsePos, falseNeg := compareCVEs(expectedCVEs, optionalCVEs, actualCVEs) - passed := len(falsePos) == 0 && len(falseNeg) == 0 && exitCode == 0 - - // Join stderr output for display - stderrOutput := strings.Join(stderrLines, "\n") - - return TestCase{ - Name: testCaseName, - Distro: distro, - Passed: passed, - FalsePos: falsePos, - FalseNeg: falseNeg, - StderrOutput: stderrOutput, - DockerCmd: dockerCmd, - ActualCVEs: actualCVEs, - ExpectedCVEs: expectedCVEs, - DocLink: testCaseDocLinks[testCaseName], - ExitCode: exitCode, - }, nil -} - -// fetchAnswers retrieves answers from a URL or file path -func fetchAnswers(source string) (io.ReadCloser, error) { - if source == "" { - return nil, fmt.Errorf("source cannot be empty") - } - - // Check if source is a URL - if strings.HasPrefix(source, "http://") || strings.HasPrefix(source, "https://") { - resp, err := http.Get(source) - if err != nil { - return nil, fmt.Errorf("failed to fetch from URL %s: %w", source, err) - } - if resp.StatusCode != http.StatusOK { - resp.Body.Close() - return nil, fmt.Errorf("failed to fetch from URL %s: HTTP %d", source, resp.StatusCode) - } - return resp.Body, nil - } - - // Treat as file path - file, err := os.Open(source) - if err != nil { - return nil, fmt.Errorf("failed to open file %s: %w", source, err) - } - return file, nil -} - -func loadExpectedCVEs(testCaseName, distro, answersChainguard, answersWolfi string) ([]string, []string, error) { - // Determine the source for answers - var source string - if distro == "chainguard" { - if answersChainguard != "" { - source = answersChainguard - } else { - source = "https://raw.githubusercontent.com/chainguard-dev/vulnerability-scanner-support/refs/heads/main/data/answers-chainguard.json" - } - } else { - if answersWolfi != "" { - source = answersWolfi - } else { - source = "https://raw.githubusercontent.com/chainguard-dev/vulnerability-scanner-support/refs/heads/main/data/answers.json" - } - } - - reader, err := fetchAnswers(source) - if err != nil { - return nil, nil, fmt.Errorf("failed to fetch answers for %s: %w", distro, err) - } - defer reader.Close() - - // Define struct to match the JSON structure - type TestCaseData struct { - TestCaseName string `json:"testCaseName"` - Vulnerabilities [][]string `json:"vulnerabilities"` - OptionalVulnerabilities [][]string `json:"optionalVulnerabilities,omitempty"` - } - - type AnswerData struct { - TestCases []TestCaseData `json:"testCases"` - } - - var answers AnswerData - if err := json.NewDecoder(reader).Decode(&answers); err != nil { - return nil, nil, fmt.Errorf("failed to decode answers from %s: %w", source, err) - } - - // Find the matching test case - for _, testCase := range answers.TestCases { - if testCase.TestCaseName == testCaseName { - var cveList []string - var optionalCveList []string - - // Extract CVE IDs from vulnerabilities (first element of each pair) - for _, vuln := range testCase.Vulnerabilities { - if len(vuln) > 0 && strings.HasPrefix(vuln[0], "CVE-") { - cveList = append(cveList, vuln[0]) - } - } - - // Extract CVE IDs from optional vulnerabilities (first element of each pair) - for _, vuln := range testCase.OptionalVulnerabilities { - if len(vuln) > 0 && strings.HasPrefix(vuln[0], "CVE-") { - optionalCveList = append(optionalCveList, vuln[0]) - } - } - - return cveList, optionalCveList, nil - } - } - - return nil, nil, fmt.Errorf("test case %s not found in answers source %s", testCaseName, source) -} - -// separateDockerStreams separates Docker's multiplexed stream into stdout and stderr -func separateDockerStreams(reader io.Reader) (stdout []string, stderr []string, err error) { - for { - // Read the 8-byte header - header := make([]byte, 8) - n, err := io.ReadFull(reader, header) - if err == io.EOF { - break - } - if err != nil { - return nil, nil, fmt.Errorf("error reading docker stream header: %w", err) - } - if n != 8 { - return nil, nil, fmt.Errorf("incomplete docker stream header: got %d bytes, expected 8", n) - } - - // Parse header: byte 0 is stream type, bytes 4-7 are payload size (big-endian) - streamType := header[0] - payloadSize := int(header[4])<<24 | int(header[5])<<16 | int(header[6])<<8 | int(header[7]) - - // Read the payload - payload := make([]byte, payloadSize) - n, err = io.ReadFull(reader, payload) - if err != nil { - return nil, nil, fmt.Errorf("error reading docker stream payload: %w", err) - } - if n != payloadSize { - return nil, nil, fmt.Errorf("incomplete docker stream payload: got %d bytes, expected %d", n, payloadSize) - } - - // Split payload into lines and append to appropriate stream - scanner := bufio.NewScanner(strings.NewReader(string(payload))) - for scanner.Scan() { - line := scanner.Text() - switch streamType { - case dockerStdoutStream: - stdout = append(stdout, line) - case dockerStderrStream: - stderr = append(stderr, line) - default: - // Unknown stream type, treat as stdout for safety - stdout = append(stdout, line) - } - } - - if err := scanner.Err(); err != nil { - return nil, nil, fmt.Errorf("error parsing docker stream payload: %w", err) - } - } - - return stdout, stderr, nil -} - -// parseCVEsFromOutput extracts CVE IDs from scanner output -func parseCVEsFromOutput(lines []string) []string { - var cves []string - for _, line := range lines { - line = strings.TrimSpace(line) - // Check if the line looks like a CVE ID (CVE-YYYY-NNNNN format) - if strings.HasPrefix(line, "CVE-") && len(line) >= 13 { - // Basic validation: CVE-YYYY-NNNNN (at least 4 digits for year and 4+ for number) - parts := strings.Split(line, "-") - if len(parts) >= 3 && len(parts[1]) == 4 && len(parts[2]) >= 4 { - cves = append(cves, line) - } - } - } - return cves -} - -func compareCVEs(expected, optional, actual []string) (falsePos, falseNeg []string) { - expectedSet := make(map[string]bool) - optionalSet := make(map[string]bool) - actualSet := make(map[string]bool) - - for _, cve := range expected { - expectedSet[cve] = true - } - for _, cve := range optional { - optionalSet[cve] = true - } - for _, cve := range actual { - actualSet[cve] = true - } - - // Find false positives (in actual but not in expected or optional) - for cve := range actualSet { - if !expectedSet[cve] && !optionalSet[cve] { - falsePos = append(falsePos, cve) - } - } - - // Find false negatives (in expected but not actual) - for cve := range expectedSet { - if !actualSet[cve] { - falseNeg = append(falseNeg, cve) - } - } - - return falsePos, falseNeg -} - -func generateHTMLReport(report AuditReport, outputPath string) error { - htmlTemplate := ` - - - Scanner Audit Report - - - - - -
-

Scanner Audit Report

-

Generated: {{.Timestamp.Format "2006-01-02 15:04:05"}}

-

Test cases from: github.com/chainguard-dev/vulnerability-scanner-support

-
- -
-

Env: {{.ScannerInfo.EnvName}}

-

Wrapper Image: {{.ScannerInfo.WrapperImage}}

- {{if .ScannerInfo.RequiredVars}} -

Required Environment Variables: {{range $i, $env := .ScannerInfo.RequiredVars}}{{if $i}}, {{end}}{{$env}}{{end}}

- {{end}} - -
- Audit Env -
{{.ScannerInfo.AuditEnvContent}}
-
- -
- Wrapper Script -
{{.ScannerInfo.WrapperScript}}
-
-
- -
-

Overall Result: {{if .OverallPassed}}PASSED{{else}}FAILED{{end}}

-

{{.ExecutedTests}} test case{{if ne .ExecutedTests 1}}s{{end}} executed across {{.ExecutedDistros}} distribution{{if ne .ExecutedDistros 1}}s{{end}}

- {{if gt .SkippedTests 0}}

{{.SkippedTests}} test case{{if ne .SkippedTests 1}}s{{end}} skipped across {{.SkippedDistros}} distribution{{if ne .SkippedDistros 1}}s{{end}}

{{end}} -
- - {{range .Distros}} -
-

-
- - {{.Name}} - {{if .Skipped}}SKIPPED ({{len .TestCases}} test cases){{else if .Passed}}PASSED ({{.ExecutedTests}} test cases){{else}}FAILED ({{.FailedTests}} out of {{.ExecutedTests}} test cases){{end}} -
- {{if eq .Name "wolfi"}} - 📊 answers.json - {{else if eq .Name "chainguard"}} - 📊 answers-chainguard.json - {{end}} -

-
-
- Status: {{if .Skipped}}SKIPPED{{else if .Passed}}PASSED{{else}}FAILED{{end}} - {{if .Skipped}}({{len .TestCases}} test cases){{else if .Passed}}({{.ExecutedTests}} test cases){{else}}({{.FailedTests}} out of {{.ExecutedTests}} test cases){{end}} -
- - - - - - - - - {{range .TestCases}} - - - - - - - - {{end}} - -
Test CaseResult
{{.Name}} - {{if .Skipped}}SKIP{{else if .Passed}}PASS{{else}}FAIL{{end}} -
-
-

Test Case Details: {{.Name}} ({{.Distro}}) - {{if .DocLink}}📖 test case description{{end}} -

- -
Docker Command:
-
{{.DockerCmd}}
- - {{if .Skipped}} -

⏭️ Test skipped due to filtering options

- {{else if ne .ExitCode 0}} -
- ⚠️ WARNING: Container exited with non-zero code ({{.ExitCode}})
- The container did not exit successfully. Please review the scanner output below to diagnose the issue. -
- {{if .FalsePos}} -
False Positives ({{len .FalsePos}}):
-
    - {{range .FalsePos}}
  • {{.}}
  • {{end}} -
- {{end}} - {{if .FalseNeg}} -
False Negatives ({{len .FalseNeg}}):
-
    - {{range .FalseNeg}}
  • {{.}}
  • {{end}} -
- {{end}} - {{else if not .Passed}} - {{if .FalsePos}} -
False Positives ({{len .FalsePos}}):
-
    - {{range .FalsePos}}
  • {{.}}
  • {{end}} -
- {{end}} - {{if .FalseNeg}} -
False Negatives ({{len .FalseNeg}}):
-
    - {{range .FalseNeg}}
  • {{.}}
  • {{end}} -
- {{end}} - {{else}} -

✅ Test passed successfully - no discrepancies detected

- {{end}} - - {{if .ExpectedCVEs}} -
Expected CVEs ({{len .ExpectedCVEs}}):
-
    - {{range .ExpectedCVEs}}
  • {{.}}
  • {{end}} -
- {{end}} - - {{if .ActualCVEs}} -
Actual CVEs ({{len .ActualCVEs}}):
-
    - {{range .ActualCVEs}}
  • {{.}}
  • {{end}} -
- {{end}} - - {{if .StderrOutput}} -
Scanner Stderr:
-
{{.StderrOutput}}
- {{end}} -
-
-
-
- {{end}} - -` - - tmpl, err := template.New("report").Parse(htmlTemplate) - if err != nil { - return fmt.Errorf("failed to parse template: %w", err) - } - - file, err := os.Create(outputPath) - if err != nil { - return fmt.Errorf("failed to create %s: %w", outputPath, err) - } - defer file.Close() - - if err := tmpl.Execute(file, report); err != nil { - return fmt.Errorf("failed to execute template: %w", err) - } - - return nil -} diff --git a/scanner-audit/scanner-audit-screenshot.png b/scanner-audit/scanner-audit-screenshot.png deleted file mode 100644 index 18799b5..0000000 Binary files a/scanner-audit/scanner-audit-screenshot.png and /dev/null differ