diff --git a/.binny.yaml b/.binny.yaml index b1f2877964d..806e4f8fc40 100644 --- a/.binny.yaml +++ b/.binny.yaml @@ -2,7 +2,7 @@ tools: # we want to use a pinned version of binny to manage the toolchain (so binny manages itself!) - name: binny version: - want: v0.9.0 + want: v0.10.0 method: github-release with: repo: anchore/binny @@ -26,7 +26,7 @@ tools: # used for linting - name: golangci-lint version: - want: v2.2.1 + want: v2.5.0 method: github-release with: repo: golangci/golangci-lint @@ -42,7 +42,7 @@ tools: # used for signing the checksums file at release - name: cosign version: - want: v2.5.2 + want: v3.0.1 method: github-release with: repo: sigstore/cosign @@ -58,7 +58,7 @@ tools: # used to release all artifacts - name: goreleaser version: - want: v2.10.2 + want: v2.12.5 method: github-release with: repo: goreleaser/goreleaser @@ -90,7 +90,7 @@ tools: # used for running all local and CI tasks - name: task version: - want: v3.44.0 + want: v3.45.4 method: github-release with: repo: go-task/task @@ -98,7 +98,7 @@ tools: # used for triggering a release - name: gh version: - want: v2.74.2 + want: v2.81.0 method: github-release with: repo: cli/cli @@ -106,7 +106,7 @@ tools: # used to upload test fixture cache - name: oras version: - want: v1.2.3 + want: v1.3.0 method: github-release with: repo: oras-project/oras @@ -114,7 +114,7 @@ tools: # used to upload test fixture cache - name: yq version: - want: v4.45.4 + want: v4.47.2 method: github-release with: repo: mikefarah/yq diff --git a/.github/actions/bootstrap/action.yaml b/.github/actions/bootstrap/action.yaml index 176a67a98e4..9c37c572c9e 100644 --- a/.github/actions/bootstrap/action.yaml +++ b/.github/actions/bootstrap/action.yaml @@ -29,7 +29,7 @@ runs: using: "composite" steps: # note: go mod and build is automatically cached on default with v4+ - - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + - uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0 if: inputs.go-version != '' with: go-version: ${{ inputs.go-version }} @@ -37,7 +37,7 @@ runs: - name: Restore tool cache if: inputs.tools == 'true' id: tool-cache - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ${{ github.workspace }}/.tool key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('.binny.yaml') }} @@ -55,12 +55,15 @@ runs: - name: Install apt packages if: inputs.bootstrap-apt-packages != '' shell: bash + env: + APT_PACKAGES: ${{ inputs.bootstrap-apt-packages }} run: | - DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y ${{ inputs.bootstrap-apt-packages }} + IFS=' ' read -ra packages <<< "$APT_PACKAGES" + DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y "${packages[@]}" - name: Restore ORAS cache from github actions if: inputs.download-test-fixture-cache == 'true' - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ${{ github.workspace }}/.tmp/oras-cache key: ${{ inputs.cache-key-prefix }}-oras-cache diff --git a/.github/scripts/update-version-file.sh b/.github/scripts/update-version-file.sh deleted file mode 100755 index c8a039c59b8..00000000000 --- a/.github/scripts/update-version-file.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -set -ue - -BIN="syft" -VERSION_FILE="VERSION" -VERSION=$1 - -# the source of truth as to whether we want to notify users of an update is if the release just created is NOT -# flagged as a pre-release on github -if [[ "$(curl -SsL https://api.github.com/repos/anchore/${BIN}/releases/tags/${VERSION} | jq .prerelease)" == "true" ]] ; then - echo "skipping publishing a version file (this is a pre-release: ${VERSION})" - exit 0 -fi - -echo "creating and publishing version file (${VERSION})" - -# create a version file for version-update checks -echo "${VERSION}" | tee "${VERSION_FILE}" - -# upload the version file that supports the application version update check -export AWS_DEFAULT_REGION=us-west-2 -aws s3 cp "${VERSION_FILE}" s3://toolbox-data.anchore.io/${BIN}/releases/latest/VERSION diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 2a36b21ecb5..c8af41495a3 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -36,16 +36,18 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - name: Install Go - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 #v5.5.0 + uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 #v6.0.0 with: go-version-file: go.mod # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b #v3.29.2 + uses: github/codeql-action/init@e296a935590eb16afc0c0108289f68c87e2a89a5 #v3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +58,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@181d5eefc20863364f96762470ba6f862bdef56b #v3.29.2 + uses: github/codeql-action/autobuild@e296a935590eb16afc0c0108289f68c87e2a89a5 #v3.29.5 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +72,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b #v3.29.2 + uses: github/codeql-action/analyze@e296a935590eb16afc0c0108289f68c87e2a89a5 #v3.29.5 diff --git a/.github/workflows/detect-schema-changes.yaml b/.github/workflows/detect-schema-changes.yaml index d69f1820cb7..74c2455ccf0 100644 --- a/.github/workflows/detect-schema-changes.yaml +++ b/.github/workflows/detect-schema-changes.yaml @@ -28,9 +28,15 @@ jobs: label: name: "Label changes" runs-on: ubuntu-22.04 + permissions: + contents: read + pull-requests: write + issues: write steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - run: python .github/scripts/labeler.py env: @@ -40,7 +46,7 @@ jobs: - name: Delete existing comment if: ${{ hashFiles( env.CI_COMMENT_FILE ) == '' }} - uses: marocchino/sticky-pull-request-comment@d2ad0de260ae8b0235ce059e63f2949ba9e05943 #v2.9.3 + uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 #v2.9.4 with: header: ${{ env.COMMENT_HEADER }} hide: true @@ -48,7 +54,7 @@ jobs: - name: Add comment if: ${{ hashFiles( env.CI_COMMENT_FILE ) != '' }} - uses: marocchino/sticky-pull-request-comment@d2ad0de260ae8b0235ce059e63f2949ba9e05943 #v2.9.3 + uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 #v2.9.4 with: header: ${{ env.COMMENT_HEADER }} path: ${{ env.CI_COMMENT_FILE }} diff --git a/.github/workflows/release-version-file.yaml b/.github/workflows/release-version-file.yaml deleted file mode 100644 index 434bfb43759..00000000000 --- a/.github/workflows/release-version-file.yaml +++ /dev/null @@ -1,31 +0,0 @@ -name: "Release: version file" - -on: - - workflow_dispatch: - inputs: - version: - description: release version to update the version file with (prefixed with v) - required: true - - workflow_call: - inputs: - version: - type: string - description: release version to update the version file with (prefixed with v) - required: true - -jobs: - - release: - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 - - - name: Update version file - run: make ci-release-version-file - env: - RELEASE_VERSION: ${{ github.event.inputs.version }} - # for updating the VERSION file in S3... - AWS_ACCESS_KEY_ID: ${{ secrets.TOOLBOX_AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.TOOLBOX_AWS_SECRET_ACCESS_KEY }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 0e7ea1f8549..b6f42fbd5f1 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -15,7 +15,9 @@ jobs: environment: release runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - name: Check if running on main if: github.ref != 'refs/heads/main' @@ -28,8 +30,10 @@ jobs: - name: Check if tag already exists # note: this will fail if the tag already exists run: | - [[ "${{ github.event.inputs.version }}" == v* ]] || (echo "version '${{ github.event.inputs.version }}' does not have a 'v' prefix" && exit 1) - git tag ${{ github.event.inputs.version }} + [[ "$VERSION" == v* ]] || (echo "version '$VERSION' does not have a 'v' prefix" && exit 1) + git tag "$VERSION" + env: + VERSION: ${{ github.event.inputs.version }} - name: Check static analysis results uses: fountainhead/action-wait-for-check@5a908a24814494009c4bb27c242ea38c93c593be # v1.2.0 @@ -87,13 +91,20 @@ jobs: - name: Quality gate if: steps.static-analysis.outputs.conclusion != 'success' || steps.unit.outputs.conclusion != 'success' || steps.integration.outputs.conclusion != 'success' || steps.cli-linux.outputs.conclusion != 'success' || steps.acceptance-linux.outputs.conclusion != 'success' || steps.acceptance-mac.outputs.conclusion != 'success' + env: + STATIC_ANALYSIS_STATUS: ${{ steps.static-analysis.conclusion }} + UNIT_TEST_STATUS: ${{ steps.unit.outputs.conclusion }} + INTEGRATION_TEST_STATUS: ${{ steps.integration.outputs.conclusion }} + ACCEPTANCE_LINUX_STATUS: ${{ steps.acceptance-linux.outputs.conclusion }} + ACCEPTANCE_MAC_STATUS: ${{ steps.acceptance-mac.outputs.conclusion }} + CLI_LINUX_STATUS: ${{ steps.cli-linux.outputs.conclusion }} run: | - echo "Static Analysis Status: ${{ steps.static-analysis.conclusion }}" - echo "Unit Test Status: ${{ steps.unit.outputs.conclusion }}" - echo "Integration Test Status: ${{ steps.integration.outputs.conclusion }}" - echo "Acceptance Test (Linux) Status: ${{ steps.acceptance-linux.outputs.conclusion }}" - echo "Acceptance Test (Mac) Status: ${{ steps.acceptance-mac.outputs.conclusion }}" - echo "CLI Test (Linux) Status: ${{ steps.cli-linux.outputs.conclusion }}" + echo "Static Analysis Status: $STATIC_ANALYSIS_STATUS" + echo "Unit Test Status: $UNIT_TEST_STATUS" + echo "Integration Test Status: $INTEGRATION_TEST_STATUS" + echo "Acceptance Test (Linux) Status: $ACCEPTANCE_LINUX_STATUS" + echo "Acceptance Test (Mac) Status: $ACCEPTANCE_MAC_STATUS" + echo "CLI Test (Linux) Status: $CLI_LINUX_STATUS" false release: @@ -105,21 +116,22 @@ jobs: # required for goreleaser signs section with cosign id-token: write steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 with: fetch-depth: 0 + persist-credentials: true - name: Bootstrap environment uses: ./.github/actions/bootstrap - name: Login to Docker Hub - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 #v3.4.0 + uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 #v3.5.0 with: username: ${{ secrets.ANCHOREOSSWRITE_DH_USERNAME }} password: ${{ secrets.ANCHOREOSSWRITE_DH_PAT }} - name: Login to GitHub Container Registry - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 #v3.4.0 + uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 #v3.5.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -129,10 +141,11 @@ jobs: run: | git config --global user.name "anchoreci" git config --global user.email "anchoreci@users.noreply.github.com" - git tag -a ${{ github.event.inputs.version }} -m "Release ${{ github.event.inputs.version }}" + git tag -a "$VERSION" -m "Release $VERSION" git push origin --tags env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VERSION: ${{ github.event.inputs.version }} - name: Build & publish release artifacts run: make ci-release @@ -148,13 +161,13 @@ jobs: # for updating brew formula in anchore/homebrew-syft GITHUB_BREW_TOKEN: ${{ secrets.ANCHOREOPS_GITHUB_OSS_WRITE_TOKEN }} - - uses: anchore/sbom-action@9246b90769f852b3a8921f330c59e0b3f439d6e9 #v0.20.1 + - uses: anchore/sbom-action@f8bdd1d8ac5e901a77a92f111440fdb1b593736b #v0.20.6 continue-on-error: true with: file: go.mod artifact-name: sbom.spdx.json - - uses: 8398a7/action-slack@1750b5085f3ec60384090fb7c52965ef822e869e #v3.18.0 + - uses: 8398a7/action-slack@77eaa4f1c608a7d68b38af4e3f739dcd8cba273e #v3.19.0 continue-on-error: true with: status: ${{ job.status }} @@ -164,9 +177,17 @@ jobs: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }} if: ${{ success() }} - release-version-file: + release-install-script: needs: [release] - uses: ./.github/workflows/release-version-file.yaml + if: ${{ needs.release.result == 'success' }} + uses: "anchore/workflows/.github/workflows/release-install-script.yaml@main" with: - version: ${{ github.event.inputs.version }} - secrets: inherit + tag: ${{ github.event.inputs.version }} + secrets: + # needed for r2... + R2_INSTALL_ACCESS_KEY_ID: ${{ secrets.OSS_R2_INSTALL_ACCESS_KEY_ID }} + R2_INSTALL_SECRET_ACCESS_KEY: ${{ secrets.OSS_R2_INSTALL_SECRET_ACCESS_KEY }} + R2_ENDPOINT: ${{ secrets.TOOLBOX_CLOUDFLARE_R2_ENDPOINT }} + # needed for s3... + S3_INSTALL_AWS_ACCESS_KEY_ID: ${{ secrets.TOOLBOX_AWS_ACCESS_KEY_ID }} + S3_INSTALL_AWS_SECRET_ACCESS_KEY: ${{ secrets.TOOLBOX_AWS_SECRET_ACCESS_KEY }} diff --git a/.github/workflows/remove-awaiting-response-label.yaml b/.github/workflows/remove-awaiting-response-label.yaml index 0f3b50c4f41..cb27571efa6 100644 --- a/.github/workflows/remove-awaiting-response-label.yaml +++ b/.github/workflows/remove-awaiting-response-label.yaml @@ -6,6 +6,10 @@ on: jobs: run: + permissions: + contents: read + issues: write + pull-requests: write uses: "anchore/workflows/.github/workflows/remove-awaiting-response-label.yaml@main" secrets: token: ${{ secrets.OSS_PROJECT_GH_TOKEN }} diff --git a/.github/workflows/test-fixture-cache-publish.yaml b/.github/workflows/test-fixture-cache-publish.yaml index 21288ecbc29..88b89a5c4a0 100644 --- a/.github/workflows/test-fixture-cache-publish.yaml +++ b/.github/workflows/test-fixture-cache-publish.yaml @@ -19,7 +19,9 @@ jobs: permissions: packages: write steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -34,7 +36,9 @@ jobs: DOWNLOAD_TEST_FIXTURE_CACHE: "false" - name: Login to GitHub Container Registry (ORAS) - run: echo "${{ secrets.GITHUB_TOKEN }}" | .tool/oras login ghcr.io -u ${{ github.actor }} --password-stdin + run: echo "${{ secrets.GITHUB_TOKEN }}" | .tool/oras login ghcr.io -u "$ACTOR" --password-stdin + env: + ACTOR: ${{ github.actor }} - name: Publish test fixture cache run: make upload-test-fixture-cache diff --git a/.github/workflows/update-anchore-dependencies.yml b/.github/workflows/update-anchore-dependencies.yml index bf0a3d19025..04fffdb0117 100644 --- a/.github/workflows/update-anchore-dependencies.yml +++ b/.github/workflows/update-anchore-dependencies.yml @@ -15,7 +15,9 @@ jobs: runs-on: ubuntu-latest if: github.repository_owner == 'anchore' # only run for main repo (not forks) steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - name: Bootstrap environment uses: ./.github/actions/bootstrap diff --git a/.github/workflows/update-bootstrap-tools.yml b/.github/workflows/update-bootstrap-tools.yml index d4c1f62f7a7..58f09ca8a8b 100644 --- a/.github/workflows/update-bootstrap-tools.yml +++ b/.github/workflows/update-bootstrap-tools.yml @@ -13,7 +13,9 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'anchore/syft' # only run for main repo steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - name: Bootstrap environment uses: ./.github/actions/bootstrap diff --git a/.github/workflows/update-cpe-dictionary-index.yml b/.github/workflows/update-cpe-dictionary-index.yml index 8263d2ccb4f..21037dd957c 100644 --- a/.github/workflows/update-cpe-dictionary-index.yml +++ b/.github/workflows/update-cpe-dictionary-index.yml @@ -16,7 +16,9 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'anchore/syft' # only run for main repo steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -45,7 +47,7 @@ jobs: Update CPE dictionary index based on the latest available CPE dictionary token: ${{ steps.generate-token.outputs.token }} - - uses: 8398a7/action-slack@1750b5085f3ec60384090fb7c52965ef822e869e #v3.18.0 + - uses: 8398a7/action-slack@77eaa4f1c608a7d68b38af4e3f739dcd8cba273e #v3.19.0 with: status: ${{ job.status }} fields: workflow,eventName,job diff --git a/.github/workflows/validate-github-actions.yaml b/.github/workflows/validate-github-actions.yaml new file mode 100644 index 00000000000..afd39914e06 --- /dev/null +++ b/.github/workflows/validate-github-actions.yaml @@ -0,0 +1,35 @@ +name: "Validate GitHub Actions" + +on: + pull_request: + paths: + - '.github/workflows/**' + - '.github/actions/**' + push: + branches: + - main + paths: + - '.github/workflows/**' + - '.github/actions/**' + +permissions: + contents: read + +jobs: + zizmor: + name: "Lint" + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write # for uploading SARIF results + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + + - name: "Run zizmor" + uses: zizmorcore/zizmor-action@e673c3917a1aef3c65c972347ed84ccd013ecda4 # v0.2.0 + with: + config-file: .github/zizmor.yml + sarif-upload: true + inputs: .github diff --git a/.github/workflows/validations.yaml b/.github/workflows/validations.yaml index 910444a6666..296c7e6bd58 100644 --- a/.github/workflows/validations.yaml +++ b/.github/workflows/validations.yaml @@ -17,7 +17,9 @@ jobs: name: "Static analysis" runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -32,7 +34,9 @@ jobs: # we need more storage than what's on the default runner runs-on: ubuntu-22.04-4core-16gb steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -48,7 +52,9 @@ jobs: name: "Integration tests" runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -66,7 +72,9 @@ jobs: name: "Build snapshot artifacts" runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -82,7 +90,7 @@ jobs: # why not use actions/upload-artifact? It is very slow (3 minutes to upload ~600MB of data, vs 10 seconds with this approach). # see https://github.com/actions/upload-artifact/issues/199 for more info - name: Upload snapshot artifacts - uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3 + uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 #v4.3.0 with: # we need to preserve the snapshot data itself as well as the task data that confirms if the # snapshot build is stale or not. Otherwise the downstream jobs will attempt to rebuild the snapshot @@ -99,7 +107,9 @@ jobs: needs: [Build-Snapshot-Artifacts] runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -108,7 +118,7 @@ jobs: - name: Download snapshot build id: snapshot-cache - uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3 + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 #v4.3.0 with: path: | snapshot @@ -123,7 +133,7 @@ jobs: - run: npm install @actions/artifact@2.2.2 - - uses: actions/github-script@v7 + - uses: actions/github-script@v8 with: script: | const { readdirSync } = require('fs') @@ -154,7 +164,9 @@ jobs: needs: [Build-Snapshot-Artifacts] runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -163,7 +175,7 @@ jobs: - name: Download snapshot build id: snapshot-cache - uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3 + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 #v4.3.0 with: path: | snapshot @@ -198,9 +210,11 @@ jobs: runs-on: macos-latest steps: - name: Install Cosign - uses: sigstore/cosign-installer@v3.9.1 + uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0 - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -211,7 +225,7 @@ jobs: - name: Download snapshot build id: snapshot-cache - uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3 + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 #v4.3.0 with: path: | snapshot @@ -237,7 +251,9 @@ jobs: needs: [Build-Snapshot-Artifacts] runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - name: Bootstrap environment uses: ./.github/actions/bootstrap @@ -246,7 +262,7 @@ jobs: - name: Download snapshot build id: snapshot-cache - uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3 + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 #v4.3.0 with: path: | snapshot @@ -275,7 +291,9 @@ jobs: - Cli-Linux - Upload-Snapshot-Artifacts steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0 + with: + persist-credentials: false - name: Delete snapshot cache run: gh cache delete "snapshot-build-${{ github.run_id }}" diff --git a/.github/zizmor.yml b/.github/zizmor.yml new file mode 100644 index 00000000000..5e92012af2a --- /dev/null +++ b/.github/zizmor.yml @@ -0,0 +1,11 @@ +rules: + unpinned-uses: + ignore: + # Allow unpinned uses of trusted internal anchore/workflows actions + - update-anchore-dependencies.yml + + dangerous-triggers: + ignore: + # Safe use of pull_request_target - only runs trusted scripts from base repo, + # never checks out PR code, needs secrets for labeling PRs from forks + - detect-schema-changes.yaml diff --git a/.goreleaser.yaml b/.goreleaser.yaml index de69b0ebead..bb278f1a94c 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -42,18 +42,19 @@ builds: dir: ./cmd/syft binary: syft goos: [windows] - goarch: [amd64] + goarch: [amd64, arm64] mod_timestamp: *build-timestamp ldflags: *build-ldflags archives: - id: linux-archives - builds: [linux-build] + ids: [linux-build] - id: darwin-archives - builds: [darwin-build] + ids: [darwin-build] - id: windows-archives - format: zip - builds: [windows-build] + formats: + - zip + ids: [windows-build] nfpms: - license: "Apache 2.0" diff --git a/DEVELOPING.md b/DEVELOPING.md index 91cdc3f8062..8fd5b57f3e9 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -27,7 +27,7 @@ Also double check that the docker context being used is the default context. If `docker context use default` -After cloning the following step can help you get setup: +After cloning, the following steps can help you get setup: 1. run `make bootstrap` to download go mod dependencies, create the `/.tmp` dir, and download helper utilities. 2. run `make` to view the selection of developer commands in the Makefile 3. run `make build` to build the release snapshot binaries and packages @@ -120,7 +120,7 @@ sequenceDiagram source-->>+sbom: add source to SBOM struct source-->>+catalog: pass src to generate catalog catalog-->-sbom: add cataloging results onto SBOM - sbom-->>encoder: pass SBOM and format desiered to syft encoder + sbom-->>encoder: pass SBOM and format desired to syft encoder encoder-->>source: return bytes that are the SBOM of the original input Note right of catalog: cataloger configuration is done based on src @@ -186,7 +186,7 @@ Cataloger names should be unique and named with the following rules of thumb in - Use lowercase letters, numbers, and hyphens only - Use hyphens to separate words - Catalogers for language ecosystems should start with the language name (e.g. `python-` for a cataloger that raises up python packages) -- Distinct between when the cataloger is searching for evidence of installed packages vs declared packages. For example, there are currently two different gemspec-based catalogers, the `ruby-gemspec-cataloger` and `ruby-installed-gemspec-cataloger`, where the latter requires that the gemspec is found within a `specifications` directory (which means it was installed, not just at the root of a source repo). +- Distinguish between when the cataloger is searching for evidence of installed packages vs declared packages. For example, there are currently two different gemspec-based catalogers, the `ruby-gemspec-cataloger` and `ruby-installed-gemspec-cataloger`, where the latter requires that the gemspec is found within a `specifications` directory (which means it was installed, not just at the root of a source repo). #### Building a new Cataloger diff --git a/Makefile b/Makefile index 2f1ae1f8e5b..a1430e7f5fc 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ TASK = $(TOOL_DIR)/task # note: we need to assume that binny and task have not already been installed $(BINNY): @mkdir -p $(TOOL_DIR) - @curl -sSfL https://raw.githubusercontent.com/$(OWNER)/binny/main/install.sh | sh -s -- -b $(TOOL_DIR) + @curl -sSfL https://get.anchore.io/binny | sh -s -- -b $(TOOL_DIR) # note: we need to assume that binny and task have not already been installed .PHONY: task diff --git a/README.md b/README.md index 43cba0a34ce..12577f10fea 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,8 @@ Syft development is sponsored by [Anchore](https://anchore.com/), and is release Syft binaries are provided for Linux, macOS and Windows. ### Recommended -> ```bash -> curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin +> ```bash +> curl -sSfL https://get.anchore.io/syft | sudo sh -s -- -b /usr/local/bin > ``` Install script options: @@ -133,6 +133,7 @@ Note that flags using the @ can be used for earlier versions of each sp - Elixir (mix) - Erlang (rebar3) - Go (go.mod, Go binaries) +- GitHub (workflows, actions) - Haskell (cabal, stack) - Java (jar, ear, war, par, sar, nar, native-image) - JavaScript (npm, yarn) @@ -141,7 +142,7 @@ Note that flags using the @ can be used for earlier versions of each sp - Linux kernel modules (ko) - Nix (outputs in /nix/store) - PHP (composer, PECL, Pear) -- Python (wheel, egg, poetry, requirements.txt) +- Python (wheel, egg, poetry, requirements.txt, uv) - Red Hat (rpm) - Ruby (gem) - Rust (cargo.lock, auditable binary) @@ -157,7 +158,7 @@ Our [wiki](https://github.com/anchore/syft/wiki) contains further details on the * [File Selection](https://github.com/anchore/syft/wiki/file-selection) * [Excluding file paths](https://github.com/anchore/syft/wiki/excluding-file-paths) * [Output formats](https://github.com/anchore/syft/wiki/output-formats) -* [Package Cataloger Selection](https://github.com/anchore/syft/wiki/package-cataloger-selection) +* [Package Cataloger Selection](https://github.com/anchore/syft/wiki/package-cataloger-selection) * [Concepts](https://github.com/anchore/syft/wiki/package-cataloger-selection#concepts) * [Examples](https://github.com/anchore/syft/wiki/package-cataloger-selection#examples) * [Using templates](https://github.com/anchore/syft/wiki/using-templates) @@ -177,8 +178,8 @@ Check out our [contributing](/CONTRIBUTING.md) guide and [developer](/DEVELOPING ## Syft Team Meetings -The Syft Team hold regular community meetings online. All are welcome to join to bring topics for discussion. -- Check the [calendar](https://calendar.google.com/calendar/u/0/r?cid=Y182OTM4dGt0MjRtajI0NnNzOThiaGtnM29qNEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t) for the next meeting date. +The Syft Team hold regular community meetings online. All are welcome to join to bring topics for discussion. +- Check the [calendar](https://calendar.google.com/calendar/u/0/r?cid=Y182OTM4dGt0MjRtajI0NnNzOThiaGtnM29qNEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t) for the next meeting date. - Add items to the [agenda](https://docs.google.com/document/d/1ZtSAa6fj2a6KRWviTn3WoJm09edvrNUp4Iz_dOjjyY8/edit?usp=sharing) (join [this group](https://groups.google.com/g/anchore-oss-community) for write access to the [agenda](https://docs.google.com/document/d/1ZtSAa6fj2a6KRWviTn3WoJm09edvrNUp4Iz_dOjjyY8/edit?usp=sharing)) - See you there! diff --git a/SECURITY.md b/SECURITY.md index aa459a76151..9163ece3cf4 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -29,4 +29,4 @@ To report a security issue, please email with a description of the issue, the steps you took to create the issue, affected versions, and, if known, mitigations for the issue. -All support will be made on the best effort base, so please indicate the "urgency level" of the vulnerability as Critical, High, Medium or Low. +All support will be made on a best effort basis, so please indicate the "urgency level" of the vulnerability as Critical, High, Medium or Low. diff --git a/Taskfile.yaml b/Taskfile.yaml index b90671cd9e2..7fb020ab594 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -91,7 +91,7 @@ tasks: - "{{ .TOOL_DIR }}/binny" status: - "test -f {{ .TOOL_DIR }}/binny" - cmd: "curl -sSfL https://raw.githubusercontent.com/anchore/binny/main/install.sh | sh -s -- -b .tool" + cmd: "curl -sSfL https://get.anchore.io/binny | sh -s -- -b .tool" silent: true tools: @@ -502,7 +502,7 @@ tasks: generate-json-schema: desc: Generate a new JSON schema cmds: - - "cd syft/internal && go generate . && cd jsonschema && go run . && go fmt ../..." + - "cd ./internal && go generate . && cd ./jsonschema && go run . && go fmt ../..." generate-license-list: desc: Generate an updated license processing code off of the latest available SPDX license list @@ -604,16 +604,6 @@ tasks: silent: true - "{{ .RELEASE_CMD }}" - ci-release-version-file: - # desc: "[CI only] Update the version file" - deps: [tools] - cmds: - - task: ci-check - - ".github/scripts/update-version-file.sh {{ .RELEASE_VERSION }}" - requires: - vars: - - RELEASE_VERSION - ## Cleanup targets ################################# diff --git a/cmd/syft/internal/commands/scan.go b/cmd/syft/internal/commands/scan.go index 0d730fbdca9..c44b66d1973 100644 --- a/cmd/syft/internal/commands/scan.go +++ b/cmd/syft/internal/commands/scan.go @@ -10,7 +10,7 @@ import ( "github.com/hashicorp/go-multierror" "github.com/spf13/cobra" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" "github.com/anchore/clio" "github.com/anchore/fangs" @@ -218,8 +218,9 @@ func getSource(ctx context.Context, opts *options.Catalog, userInput string, sou cfg := syft.DefaultGetSourceConfig(). WithRegistryOptions(opts.Registry.ToOptions()). WithAlias(source.Alias{ - Name: opts.Source.Name, - Version: opts.Source.Version, + Name: opts.Source.Name, + Version: opts.Source.Version, + Supplier: opts.Source.Supplier, }). WithExcludeConfig(source.ExcludeConfig{ Paths: opts.Exclusions, diff --git a/cmd/syft/internal/options/catalog.go b/cmd/syft/internal/options/catalog.go index b853518d8ab..652d6a40d57 100644 --- a/cmd/syft/internal/options/catalog.go +++ b/cmd/syft/internal/options/catalog.go @@ -259,6 +259,9 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) { flags.StringVarP(&cfg.Source.BasePath, "base-path", "", "base directory for scanning, no links will be followed above this directory, and all paths will be reported relative to this directory") + + flags.StringVarP(&cfg.Source.Supplier, "source-supplier", "", + "the organization that supplied the component, which often may be the manufacturer, distributor, or repackager") } func (cfg *Catalog) DescribeFields(descriptions fangs.FieldDescriptionSet) { diff --git a/cmd/syft/internal/options/format.go b/cmd/syft/internal/options/format.go index 4540b5fee46..edbe05bc4d9 100644 --- a/cmd/syft/internal/options/format.go +++ b/cmd/syft/internal/options/format.go @@ -43,9 +43,9 @@ over to the final syft 1.0 json output this option can be used to ease the trans Note: long term support for this option is not guaranteed (it may change or break at any time)`) - descriptions.Add(&o.Template.Path, `path to the template file to use when rendering the output with the template output format. + descriptions.Add(&o.Template.Path, `path to the template file to use when rendering the output with the template output format. Note that all template paths are based on the current syft-json schema`) - descriptions.Add(&o.Template.Legacy, `if true, uses the go structs for the syft-json format for templating. + descriptions.Add(&o.Template.Legacy, `if true, uses the go structs for the syft-json format for templating. if false, uses the syft-json output for templating (which follows the syft JSON schema exactly). Note: long term support for this option is not guaranteed (it may change or break at any time)`) diff --git a/cmd/syft/internal/options/source.go b/cmd/syft/internal/options/source.go index 97e81b9459f..76cae45808c 100644 --- a/cmd/syft/internal/options/source.go +++ b/cmd/syft/internal/options/source.go @@ -16,6 +16,8 @@ import ( type sourceConfig struct { Name string `json:"name" yaml:"name" mapstructure:"name"` Version string `json:"version" yaml:"version" mapstructure:"version"` + Supplier string `json:"supplier" yaml:"supplier" mapstructure:"supplier"` + Source string `json:"source" yaml:"source" mapstructure:"source"` BasePath string `yaml:"base-path" json:"base-path" mapstructure:"base-path"` // specify base path for all file paths File fileSource `json:"file" yaml:"file" mapstructure:"file"` Image imageSource `json:"image" yaml:"image" mapstructure:"image"` diff --git a/cmd/syft/internal/test/integration/catalog_packages_test.go b/cmd/syft/internal/test/integration/catalog_packages_test.go index a949090eeb8..9fc65fdb02a 100644 --- a/cmd/syft/internal/test/integration/catalog_packages_test.go +++ b/cmd/syft/internal/test/integration/catalog_packages_test.go @@ -87,6 +87,7 @@ func TestPkgCoverageImage(t *testing.T) { definedPkgs.Remove(string(pkg.GithubActionWorkflowPkg)) definedPkgs.Remove(string(pkg.TerraformPkg)) definedPkgs.Remove(string(pkg.PhpPeclPkg)) // we have coverage for pear instead + definedPkgs.Remove(string(pkg.CondaPkg)) var cases []testCase cases = append(cases, commonTestCases...) @@ -159,6 +160,7 @@ func TestPkgCoverageDirectory(t *testing.T) { definedPkgs.Remove(string(pkg.LinuxKernelModulePkg)) definedPkgs.Remove(string(pkg.Rpkg)) definedPkgs.Remove(string(pkg.UnknownPkg)) + definedPkgs.Remove(string(pkg.CondaPkg)) definedPkgs.Remove(string(pkg.PhpPeclPkg)) // this is covered as pear packages // for directory scans we should not expect to see any of the following package types diff --git a/cmd/syft/internal/test/integration/encode_decode_cycle_test.go b/cmd/syft/internal/test/integration/encode_decode_cycle_test.go index dd3a99a8552..85821f301e7 100644 --- a/cmd/syft/internal/test/integration/encode_decode_cycle_test.go +++ b/cmd/syft/internal/test/integration/encode_decode_cycle_test.go @@ -78,7 +78,10 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) { t.Run(test.name, func(t *testing.T) { for _, image := range images { originalSBOM, _ := catalogFixtureImage(t, image, source.SquashedScope) - + // we need a way to inject supplier into this test + // supplier is not available as part of the SBOM Config API since the flag + // is used in conjunction with the SourceConfig which is injected into generateSBOM during scan + originalSBOM.Source.Supplier = "anchore" f := encoders.GetByString(test.name) require.NotNil(t, f) diff --git a/examples/create_custom_sbom/main.go b/examples/create_custom_sbom/main.go index 11f1757c956..459bb632cf3 100644 --- a/examples/create_custom_sbom/main.go +++ b/examples/create_custom_sbom/main.go @@ -6,7 +6,8 @@ import ( "fmt" "os" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" + _ "modernc.org/sqlite" // required for rpmdb and other features "github.com/anchore/syft/syft" "github.com/anchore/syft/syft/cataloging" diff --git a/examples/create_simple_sbom/main.go b/examples/create_simple_sbom/main.go index 9116f0561e0..788e8e53019 100644 --- a/examples/create_simple_sbom/main.go +++ b/examples/create_simple_sbom/main.go @@ -5,6 +5,8 @@ import ( "fmt" "os" + _ "modernc.org/sqlite" // required for rpmdb and other features + "github.com/anchore/syft/syft" "github.com/anchore/syft/syft/format" "github.com/anchore/syft/syft/format/syftjson" diff --git a/examples/select_catalogers/main.go b/examples/select_catalogers/main.go index 3ff3ecd8db2..bc8c6c81368 100644 --- a/examples/select_catalogers/main.go +++ b/examples/select_catalogers/main.go @@ -5,6 +5,8 @@ import ( "encoding/json" "os" + _ "modernc.org/sqlite" // required for rpmdb and other features + "github.com/anchore/syft/syft" "github.com/anchore/syft/syft/cataloging" "github.com/anchore/syft/syft/cataloging/pkgcataloging" diff --git a/examples/source_from_registry/main.go b/examples/source_from_registry/main.go index 15873125989..c43ad8afd7f 100644 --- a/examples/source_from_registry/main.go +++ b/examples/source_from_registry/main.go @@ -4,6 +4,8 @@ import ( "context" "os" + _ "modernc.org/sqlite" // required for rpmdb and other features + "github.com/anchore/syft/syft" "github.com/anchore/syft/syft/format/syftjson" ) diff --git a/go.mod b/go.mod index e949adc2744..568c4afad65 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.24.1 require ( github.com/BurntSushi/toml v1.5.0 - github.com/CycloneDX/cyclonedx-go v0.9.2 + github.com/CycloneDX/cyclonedx-go v0.9.3 github.com/Masterminds/semver/v3 v3.4.0 github.com/Masterminds/sprig/v3 v3.3.0 github.com/OneOfOne/xxhash v1.2.8 @@ -24,51 +24,51 @@ require ( github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b github.com/anchore/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115 - github.com/anchore/stereoscope v0.1.6 + github.com/anchore/stereoscope v0.1.10 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be github.com/aquasecurity/go-pep440-version v0.0.1 github.com/bitnami/go-version v0.0.0-20250131085805-b1f57a8634ef github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb - github.com/bmatcuk/doublestar/v4 v4.8.1 + github.com/bmatcuk/doublestar/v4 v4.9.1 github.com/charmbracelet/bubbles v0.21.0 - github.com/charmbracelet/bubbletea v1.3.5 + github.com/charmbracelet/bubbletea v1.3.10 github.com/charmbracelet/lipgloss v1.1.0 github.com/dave/jennifer v1.7.1 github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da - github.com/diskfs/go-diskfs v1.6.1-0.20250601133945-2af1c7ece24c + github.com/diskfs/go-diskfs v1.7.0 github.com/distribution/reference v0.6.0 github.com/dustin/go-humanize v1.0.1 github.com/elliotchance/phpserialize v1.4.0 github.com/facebookincubator/nvdtools v0.1.5 github.com/github/go-spdx/v2 v2.3.3 - github.com/gkampitakis/go-snaps v0.5.13 + github.com/gkampitakis/go-snaps v0.5.15 github.com/go-git/go-billy/v5 v5.6.2 - github.com/go-git/go-git/v5 v5.16.2 + github.com/go-git/go-git/v5 v5.16.3 github.com/go-test/deep v1.1.1 - github.com/go-viper/mapstructure/v2 v2.3.0 - github.com/gohugoio/hashstructure v0.5.0 + github.com/go-viper/mapstructure/v2 v2.4.0 + github.com/gohugoio/hashstructure v0.6.0 github.com/google/go-cmp v0.7.0 github.com/google/go-containerregistry v0.20.6 github.com/google/licensecheck v0.3.1 github.com/google/uuid v1.6.0 - github.com/gookit/color v1.5.4 + github.com/gookit/color v1.6.0 github.com/hashicorp/go-cleanhttp v0.5.2 - github.com/hashicorp/go-getter v1.7.8 + github.com/hashicorp/go-getter v1.8.2 github.com/hashicorp/go-multierror v1.1.1 - github.com/hashicorp/hcl/v2 v2.23.0 + github.com/hashicorp/hcl/v2 v2.24.0 github.com/iancoleman/strcase v0.3.0 github.com/invopop/jsonschema v0.7.0 - github.com/jedib0t/go-pretty/v6 v6.6.7 + github.com/jedib0t/go-pretty/v6 v6.6.8 github.com/jinzhu/copier v0.4.0 github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953 github.com/magiconair/properties v1.8.10 github.com/mholt/archives v0.1.3 github.com/moby/sys/mountinfo v0.7.2 github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 - github.com/olekukonko/tablewriter v1.0.7 + github.com/olekukonko/tablewriter v1.0.9 github.com/opencontainers/go-digest v1.0.0 github.com/pelletier/go-toml v1.9.5 - github.com/quasilyte/go-ruleguard/dsl v0.3.22 + github.com/quasilyte/go-ruleguard/dsl v0.3.23 github.com/rust-secure-code/go-rustaudit v0.0.0-20250226111315-e20ec32e963c github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d github.com/sanity-io/litter v1.5.8 @@ -78,21 +78,21 @@ require ( github.com/sergi/go-diff v1.4.0 github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb github.com/spdx/tools-golang v0.5.5 - github.com/spf13/afero v1.14.0 - github.com/spf13/cobra v1.9.1 - github.com/stretchr/testify v1.10.0 - github.com/vbatts/go-mtree v0.5.4 + github.com/spf13/afero v1.15.0 + github.com/spf13/cobra v1.10.1 + github.com/stretchr/testify v1.11.1 + github.com/vbatts/go-mtree v0.6.0 github.com/vifraa/gopom v1.0.0 github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0 github.com/xeipuuv/gojsonschema v1.2.0 github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1 go.uber.org/goleak v1.3.0 - golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 - golang.org/x/mod v0.25.0 - golang.org/x/net v0.41.0 - gopkg.in/yaml.v3 v3.0.1 - modernc.org/sqlite v1.38.0 + go.yaml.in/yaml/v3 v3.0.4 + golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b + golang.org/x/mod v0.28.0 + golang.org/x/net v0.46.0 + modernc.org/sqlite v1.39.0 ) require ( @@ -109,17 +109,15 @@ require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/hcsshim v0.11.7 // indirect - github.com/ProtonMail/go-crypto v1.2.0 // indirect + github.com/ProtonMail/go-crypto v1.3.0 // indirect github.com/STARRY-S/zip v0.2.1 // indirect github.com/agext/levenshtein v1.2.1 // indirect; indirectt github.com/anchore/go-lzo v0.1.0 // indirect github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3 // indirect - github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/aquasecurity/go-version v0.0.1 // indirect github.com/atotto/clipboard v0.1.4 // indirect - github.com/aws/aws-sdk-go v1.44.122 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/becheran/wildmatch-go v1.0.0 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect @@ -128,12 +126,12 @@ require ( github.com/bodgit/windows v1.0.1 // indirect github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect github.com/charmbracelet/harmonica v0.2.0 // indirect - github.com/charmbracelet/x/ansi v0.8.0 // indirect + github.com/charmbracelet/x/ansi v0.10.1 // indirect github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect github.com/charmbracelet/x/term v0.2.1 // indirect github.com/cloudflare/circl v1.6.1 // indirect github.com/containerd/cgroups v1.1.0 // indirect - github.com/containerd/containerd v1.7.27 // indirect + github.com/containerd/containerd v1.7.28 // indirect github.com/containerd/containerd/api v1.8.0 // indirect github.com/containerd/continuity v0.4.4 // indirect github.com/containerd/errdefs v1.0.0 // indirect @@ -146,17 +144,17 @@ require ( github.com/containerd/typeurl/v2 v2.2.0 // indirect github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/docker/cli v28.3.0+incompatible // indirect + github.com/docker/cli v28.4.0+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker v28.2.2+incompatible // indirect + github.com/docker/docker v28.4.0+incompatible // indirect github.com/docker/docker-credential-helpers v0.9.3 // indirect - github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-connections v0.6.0 // indirect github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect - github.com/fatih/color v1.17.0 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/felixge/fgprof v0.9.5 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect @@ -176,14 +174,12 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect github.com/googleapis/gax-go/v2 v2.13.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-safetemp v1.0.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/huandu/xstrings v1.5.0 // indirect - github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect + github.com/iancoleman/orderedmap v0.3.0 github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/compress v1.18.0 // indirect github.com/klauspost/pgzip v1.2.6 // indirect @@ -192,7 +188,7 @@ require ( github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/maruel/natural v1.1.1 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect @@ -201,7 +197,6 @@ require ( github.com/minio/minlz v1.0.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -215,9 +210,9 @@ require ( github.com/muesli/termenv v0.16.0 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect github.com/nwaples/rardecode v1.1.3 // indirect - github.com/nwaples/rardecode/v2 v2.1.0 // indirect - github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6 // indirect - github.com/olekukonko/ll v0.0.8 // indirect + github.com/nwaples/rardecode/v2 v2.2.0 // indirect + github.com/olekukonko/errors v1.1.0 // indirect + github.com/olekukonko/ll v0.0.9 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/opencontainers/runtime-spec v1.1.0 // indirect github.com/opencontainers/selinux v1.11.0 // indirect @@ -240,25 +235,25 @@ require ( github.com/sorairolake/lzip-go v0.3.5 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/cast v1.7.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/pflag v1.0.9 // indirect github.com/spf13/viper v1.20.0 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/sylabs/sif/v2 v2.21.1 // indirect + github.com/sylabs/sif/v2 v2.22.0 // indirect github.com/sylabs/squashfs v1.0.6 // indirect github.com/therootcompany/xz v1.0.1 // indirect github.com/tidwall/gjson v1.18.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect - github.com/ulikunitz/xz v0.5.12 // indirect + github.com/ulikunitz/xz v0.5.15 // indirect github.com/vbatts/tar-split v0.12.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - github.com/zclconf/go-cty v1.13.0 // indirect + github.com/zclconf/go-cty v1.16.3 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect @@ -269,27 +264,50 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/crypto v0.39.0 // indirect + golang.org/x/crypto v0.43.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.15.0 // indirect - golang.org/x/sys v0.33.0 // indirect - golang.org/x/term v0.32.0 // indirect - golang.org/x/text v0.26.0 // indirect - golang.org/x/time v0.7.0 // indirect - golang.org/x/tools v0.34.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.37.0 // indirect + golang.org/x/term v0.36.0 // indirect + golang.org/x/text v0.30.0 // indirect + golang.org/x/time v0.12.0 // indirect + golang.org/x/tools v0.37.0 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/api v0.203.0 // indirect google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241113202542-65e8d215514f // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect google.golang.org/grpc v1.67.3 // indirect - google.golang.org/protobuf v1.36.4 // indirect + google.golang.org/protobuf v1.36.6 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - modernc.org/libc v1.65.10 // indirect + gopkg.in/yaml.v3 v3.0.1 + modernc.org/libc v1.66.3 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.11.0 // indirect ) +require ( + github.com/aws/aws-sdk-go-v2 v1.36.5 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect + github.com/aws/aws-sdk-go-v2/config v1.29.17 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.70 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.80.1 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 // indirect + github.com/aws/smithy-go v1.22.4 // indirect + github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.65 // indirect +) + retract ( v1.25.0 // published with a replace directive (confusing for API users) v0.53.2 diff --git a/go.sum b/go.sum index 0ef527ba870..99d543fa79e 100644 --- a/go.sum +++ b/go.sum @@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -16,7 +15,6 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= @@ -29,590 +27,41 @@ cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= -cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= -cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= -cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= -cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= -cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= -cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= -cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= -cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= -cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= -cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= -cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= -cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= -cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= -cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= -cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= -cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= -cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= -cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= -cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= -cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= -cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= -cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= -cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= -cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= -cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= -cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= -cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= -cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= -cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= -cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= -cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= -cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= -cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= -cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= -cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= -cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= -cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= -cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= -cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= -cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= -cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= -cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= -cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= -cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= -cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= -cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= -cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= -cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= -cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= -cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= -cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= -cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= -cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= -cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= -cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= -cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= -cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= -cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= -cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= -cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= -cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= -cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= -cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= -cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= -cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= cloud.google.com/go/auth v0.9.9 h1:BmtbpNQozo8ZwW2t7QJjnrQtdganSdmqeIBxHxNkEZQ= cloud.google.com/go/auth v0.9.9/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= -cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= -cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= -cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= -cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= -cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= -cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= -cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= -cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= -cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= -cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= -cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= -cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= -cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= -cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= -cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= -cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= -cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= -cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= -cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= -cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= -cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= -cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= -cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= -cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= -cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= -cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= -cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= -cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= -cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= -cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= -cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= -cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= -cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= -cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= -cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= -cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= -cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= -cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= -cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= -cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= -cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= -cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= -cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= -cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= -cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= -cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= -cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= -cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= -cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= -cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= -cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= -cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= -cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= -cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= -cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= -cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= -cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= -cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= -cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= -cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= -cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU= cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo= -cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= -cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= -cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= -cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= -cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= -cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= -cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= -cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= -cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= -cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= -cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= -cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= -cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= -cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= -cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= -cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= -cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= -cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= -cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= -cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= -cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= -cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= -cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= -cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= -cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= -cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= -cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= -cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= -cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= -cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= -cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= -cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= -cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= -cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= -cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= -cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= -cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= -cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= -cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= -cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= -cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= -cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= -cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= -cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= -cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= -cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= -cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= -cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= -cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= -cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= -cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= -cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= -cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= -cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= -cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= -cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= -cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= -cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= -cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= -cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= -cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= -cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= -cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= -cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= -cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= -cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= -cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= -cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= -cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= -cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= -cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= -cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= -cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= -cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= -cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= -cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= -cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= -cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= -cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= -cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= -cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= -cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= -cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= -cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= -cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= -cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= -cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= -cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= -cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= -cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= -cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= -cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= -cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= -cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= -cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= -cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= -cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= -cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= -cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= -cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= -cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= -cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= -cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= -cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= -cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= -cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= -cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= -cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= -cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= -cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= -cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= -cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= -cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= -cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= -cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= -cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= -cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= -cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= -cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= -cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= -cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= -cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= -cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= -cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA= cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= -cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= -cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= -cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= -cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= -cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= -cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= -cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= -cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= -cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= -cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= -cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= -cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= -cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= -cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= -cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= -cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= -cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= -cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= -cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= -cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= -cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= -cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= -cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= -cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= -cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= -cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= -cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= -cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= -cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= -cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= -cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc= cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= -cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= -cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= -cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= -cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= -cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= -cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= -cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= -cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= -cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= -cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= -cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= -cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= -cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= -cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= -cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= -cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= -cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= -cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= -cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= -cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= -cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= -cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= -cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= -cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= -cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= -cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= -cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= -cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= -cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= -cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= -cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= -cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= -cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= -cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= -cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= -cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= -cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= -cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= -cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= -cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= -cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= -cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= -cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= -cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= -cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= -cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= -cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= -cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= -cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= -cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= -cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= -cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= -cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= -cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= -cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= -cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= -cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= -cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= -cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= -cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= -cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= -cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= -cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= -cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= -cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= -cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= -cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= -cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= -cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= -cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= -cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= -cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= -cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= -cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= -cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= -cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= -cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= -cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= -cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= -cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= -cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= -cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= -cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= -cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= -cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= -cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= -cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= -cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= -cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= -cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= -cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= -cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= -cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= -cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= -cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= -cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= -cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= -cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= -cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= -cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= -cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= -cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= -cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= -cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= -cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= -cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= -cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= -cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= -cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= -cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= -cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= -cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= -cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= -cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= -cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= -cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= -cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= -cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= -cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= -cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= -cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= -cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= -cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= -cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= -cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= -cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= -cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= -cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= -cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= -cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= -cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= -cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= -cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= -cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= -cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= -cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= -cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= -cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= -cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= -cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= -cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= -cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= -cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= -cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= -cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= -cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= -cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= -cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= -cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= -cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= -cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= -cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= -cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= -cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= -cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= -cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= -cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= -cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= -cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= -cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= -cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= -cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= -cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= -cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= -cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= -cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= -cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= -cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= -cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= -cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= -cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= -cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= -cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= -cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= -cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= -cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= -cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= -cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= -cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= -cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= -cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= -cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= -cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= -cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= -cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= -cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= -cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= -cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= -cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= -cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= -cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= -cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= -cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= -cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= -cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= -cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= -cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= -cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= -cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= -cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= -cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= -cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= -cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= -cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= -cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= -cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= -cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= -cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= -cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= -cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= -cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= -cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= -cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= -cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= -cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= -cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= -cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= -cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= -cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= -cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= -cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= -cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= -cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= -cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= -cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= -cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= -cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= -cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= -cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= -cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= -cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= -git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA= @@ -624,12 +73,11 @@ github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CycloneDX/cyclonedx-go v0.9.2 h1:688QHn2X/5nRezKe2ueIVCt+NRqf7fl3AVQk+vaFcIo= -github.com/CycloneDX/cyclonedx-go v0.9.2/go.mod h1:vcK6pKgO1WanCdd61qx4bFnSsDJQ6SbM2ZuMIgq86Jg= +github.com/CycloneDX/cyclonedx-go v0.9.3 h1:Pyk/lwavPz7AaZNvugKFkdWOm93MzaIyWmBwmBo3aUI= +github.com/CycloneDX/cyclonedx-go v0.9.3/go.mod h1:vcK6pKgO1WanCdd61qx4bFnSsDJQ6SbM2ZuMIgq86Jg= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= -github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= @@ -644,8 +92,8 @@ github.com/Microsoft/hcsshim v0.11.7/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= -github.com/ProtonMail/go-crypto v1.2.0 h1:+PhXXn4SPGd+qk76TlEePBfOfivE0zkWFenhGhFLzWs= -github.com/ProtonMail/go-crypto v1.2.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= +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/STARRY-S/zip v0.2.1 h1:pWBd4tuSGm3wtpoqRZZ2EAwOmcHK6XFf7bU9qcJXyFg= github.com/STARRY-S/zip v0.2.1/go.mod h1:xNvshLODWtC4EJ702g7cTYn13G53o1+X9BWnPFpcWV4= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= @@ -656,10 +104,6 @@ github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= -github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -694,20 +138,14 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115 h1:ZyRCmiEjnoGJZ1+Ah0ZZ/mKKqNhGcUZBl0s7PTTDzvY= github.com/anchore/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115/go.mod h1:KoYIv7tdP5+CC9VGkeZV4/vGCKsY55VvoG+5dadg4YI= -github.com/anchore/stereoscope v0.1.6 h1:DxaPHugD9EndPxOaIMaEYjHJJURjKNaHzD1NyQUUmdU= -github.com/anchore/stereoscope v0.1.6/go.mod h1:ejAlYkAb/cRvSMlxQlrG2dMruqQpcJAh4w2Fu02FEYQ= +github.com/anchore/stereoscope v0.1.10 h1:BogafIMaW/L1lOUoVS96Hu1jTSP2JktxIayVqcxvcBI= +github.com/anchore/stereoscope v0.1.10/go.mod h1:RWFAkQE8tp8yyaf4V83Kq1bO6hX3bzi8gpLCcKgZLIk= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3 h1:8PmGpDEZl9yDpcdEr6Odf23feCxK3LNUNMxjXg41pZQ= github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= 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/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= -github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= -github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= -github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= -github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/aquasecurity/go-pep440-version v0.0.1 h1:8VKKQtH2aV61+0hovZS3T//rUF+6GDn18paFTVS0h0M= @@ -723,8 +161,42 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= -github.com/aws/aws-sdk-go v1.44.122 h1:p6mw01WBaNpbdP2xrisz5tIkcNwzj/HysobNoaAHjgo= -github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/aws/aws-sdk-go-v2 v1.36.5 h1:0OF9RiEMEdDdZEMqF9MRjevyxAQcf6gY+E7vwBILFj0= +github.com/aws/aws-sdk-go-v2 v1.36.5/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 h1:zAybnyUQXIZ5mok5Jqwlf58/TFE7uvd3IAsa1aF9cXs= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10/go.mod h1:qqvMj6gHLR/EXWZw4ZbqlPbQUyenf4h82UQUlKc+l14= +github.com/aws/aws-sdk-go-v2/config v1.29.17 h1:jSuiQ5jEe4SAMH6lLRMY9OVC+TqJLP5655pBGjmnjr0= +github.com/aws/aws-sdk-go-v2/config v1.29.17/go.mod h1:9P4wwACpbeXs9Pm9w1QTh6BwWwJjwYvJ1iCt5QbCXh8= +github.com/aws/aws-sdk-go-v2/credentials v1.17.70 h1:ONnH5CM16RTXRkS8Z1qg7/s2eDOhHhaXVd72mmyv4/0= +github.com/aws/aws-sdk-go-v2/credentials v1.17.70/go.mod h1:M+lWhhmomVGgtuPOhO85u4pEa3SmssPTdcYpP/5J/xc= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 h1:KAXP9JSHO1vKGCr5f4O6WmlVKLFFXgWYAGoJosorxzU= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32/go.mod h1:h4Sg6FQdexC1yYG9RDnOvLbW1a/P986++/Y/a+GyEM8= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 h1:SsytQyTMHMDPspp+spo7XwXTP44aJZZAC7fBV2C5+5s= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36/go.mod h1:Q1lnJArKRXkenyog6+Y+zr7WDpk4e6XlR6gs20bbeNo= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 h1:i2vNHQiXUvKhs3quBR6aqlgJaiaexz/aNvdCktW/kAM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36/go.mod h1:UdyGa7Q91id/sdyHPwth+043HhmP6yP9MBHgbZM0xo8= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 h1:ZNTqv4nIdE/DiBfUUfXcLZ/Spcuz+RjeziUtNJackkM= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34/go.mod h1:zf7Vcd1ViW7cPqYWEHLHJkS50X0JS2IKz9Cgaj6ugrs= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 h1:CXV68E2dNqhuynZJPB80bhPQwAKqBWVer887figW6Jc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4/go.mod h1:/xFi9KtvBXP97ppCz1TAEvU1Uf66qvid89rbem3wCzQ= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.2 h1:BCG7DCXEXpNCcpwCxg1oi9pkJWH2+eZzTn9MY56MbVw= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.2/go.mod h1:iu6FSzgt+M2/x3Dk8zhycdIcHjEFb36IS8HVUVFoMg0= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 h1:t0E6FzREdtCsiLIoLCWsYliNsRBgyGD/MCK571qk4MI= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17/go.mod h1:ygpklyoaypuyDvOM5ujWGrYWpAK3h7ugnmKCU/76Ys4= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 h1:moLQUoVq91LiqT1nbvzDukyqAlCv89ZmwaHw/ZFlFZg= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15/go.mod h1:ZH34PJUc8ApjBIfgQCFvkWcUDBtl/WTD+uiYHjd8igA= +github.com/aws/aws-sdk-go-v2/service/s3 v1.80.1 h1:xYEAf/6QHiTZDccKnPMbsMwlau13GsDsTgdue3wmHGw= +github.com/aws/aws-sdk-go-v2/service/s3 v1.80.1/go.mod h1:qbn305Je/IofWBJ4bJz/Q7pDEtnnoInw/dGt71v6rHE= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 h1:AIRJ3lfb2w/1/8wOOSqYb9fUKGwQbtysJ2H1MofRUPg= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.5/go.mod h1:b7SiVprpU+iGazDUqvRSLf5XmCdn+JtT1on7uNL6Ipc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 h1:BpOxT3yhLwSJ77qIY3DoHAQjZsc4HEGfMCE4NGy3uFg= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3/go.mod h1:vq/GQR1gOFLquZMSrxUK/cpvKCNVYibNyJ1m7JrU88E= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 h1:NFOJ/NXEGV4Rq//71Hs1jC/NvPs1ezajK+yQmkwnPV0= +github.com/aws/aws-sdk-go-v2/service/sts v1.34.0/go.mod h1:7ph2tGpfQvwzgistp2+zga9f+bCjlQJPkPUmMgDSD7w= +github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw= +github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= 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/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= @@ -741,49 +213,44 @@ github.com/bitnami/go-version v0.0.0-20250131085805-b1f57a8634ef h1:TSFnfbbu2oAO github.com/bitnami/go-version v0.0.0-20250131085805-b1f57a8634ef/go.mod h1:9iglf1GG4oNRJ39bZ5AZrjgAFD2RwQbXw6Qf7Cs47wo= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= -github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38= -github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE= +github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bodgit/plumbing v1.3.0 h1:pf9Itz1JOQgn7vEOE7v7nlEfBykYqvUYioC61TwWCFU= github.com/bodgit/plumbing v1.3.0/go.mod h1:JOTb4XiRu5xfnmdnDJo6GmSbSbtSyufrsyZFByMtKEs= github.com/bodgit/sevenzip v1.6.0 h1:a4R0Wu6/P1o1pP/3VV++aEOcyeBxeO/xE2Y9NSTrr6A= github.com/bodgit/sevenzip v1.6.0/go.mod h1:zOBh9nJUof7tcrlqJFv1koWRrhz3LbDbUNngkuZxLMc= github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4= github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM= -github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 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/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs= github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg= -github.com/charmbracelet/bubbletea v1.3.5 h1:JAMNLTbqMOhSwoELIr0qyP4VidFq72/6E9j7HHmRKQc= -github.com/charmbracelet/bubbletea v1.3.5/go.mod h1:TkCnmH+aBd4LrXhXcqrKiYwRs7qyQx5rBgH5fVY3v54= +github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= +github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= 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/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= -github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= +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-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8= github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ= github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= -github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= @@ -802,20 +269,16 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/containerd/containerd v1.7.27 h1:yFyEyojddO3MIGVER2xJLWoCIn+Up4GaHFquP7hsFII= -github.com/containerd/containerd v1.7.27/go.mod h1:xZmPnl75Vc+BLGt4MIfu6bp+fy03gdHAn9bz+FreFR0= +github.com/containerd/containerd v1.7.28 h1:Nsgm1AtcmEh4AHAJ4gGlNSaKgXiNccU270Dnf81FQ3c= +github.com/containerd/containerd v1.7.28/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs= github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0= github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc= github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII= @@ -853,31 +316,29 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da h1:ZOjWpVsFZ06eIhnh4mkaceTiVoktdU67+M7KDHJ268M= github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da/go.mod h1:B3tI9iGHi4imdLi4Asdha1Sc6feLMTfPLXh9IUYmysk= github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= -github.com/diskfs/go-diskfs v1.6.1-0.20250601133945-2af1c7ece24c h1:Vg+RNk+3Kwbe3wUYsgXsk43+7oyOJ5tRDzOrcpV40yQ= -github.com/diskfs/go-diskfs v1.6.1-0.20250601133945-2af1c7ece24c/go.mod h1:LhQyXqOugWFRahYUSw47NyZJPezFzB9UELwhpszLP/k= +github.com/diskfs/go-diskfs v1.7.0 h1:vonWmt5CMowXwUc79jWyGrf2DIMeoOjkLlMnQYGVOs8= +github.com/diskfs/go-diskfs v1.7.0/go.mod h1:LhQyXqOugWFRahYUSw47NyZJPezFzB9UELwhpszLP/k= 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/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= -github.com/docker/cli v28.3.0+incompatible h1:s+ttruVLhB5ayeuf2BciwDVxYdKi+RoUlxmwNHV3Vfo= -github.com/docker/cli v28.3.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v28.4.0+incompatible h1:RBcf3Kjw2pMtwui5V0DIMdyeab8glEw5QY0UUU4C9kY= +github.com/docker/cli v28.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v28.2.2+incompatible h1:CjwRSksz8Yo4+RmQ339Dp/D2tGO5JxwYeqtMOEe0LDw= -github.com/docker/docker v28.2.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v28.4.0+incompatible h1:KVC7bz5zJY/4AZe/78BIvCnPsLaC9T/zh72xnlrTTOk= +github.com/docker/docker v28.4.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8= github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +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-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= 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/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4= github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 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= @@ -897,14 +358,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= -github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= -github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= -github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/facebookincubator/flog v0.0.0-20190930132826-d2511d0ce33c/go.mod h1:QGzNH9ujQ2ZUr/CjDGZGWeDAVStrWNjHeEcjJL96Nuk= @@ -913,8 +368,8 @@ github.com/facebookincubator/nvdtools v0.1.5/go.mod h1:Kh55SAWnjckS96TBSrXI99KrE github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= -github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +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/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA= github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= @@ -922,8 +377,6 @@ github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY= github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= @@ -938,32 +391,25 @@ github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BN github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M= github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk= -github.com/gkampitakis/go-snaps v0.5.13 h1:Hhjmvv1WboSCxkR9iU2mj5PQ8tsz/y8ECGrIbjjPF8Q= -github.com/gkampitakis/go-snaps v0.5.13/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc= +github.com/gkampitakis/go-snaps v0.5.15 h1:amyJrvM1D33cPHwVrjo9jQxX8g/7E2wYdZ+01KS3zGE= +github.com/gkampitakis/go-snaps v0.5.15/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc= github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4= github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3q+ihjqxC9u0= github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= -github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= -github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= 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.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= 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.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM= -github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= +github.com/go-git/go-git/v5 v5.16.3 h1:Z8BtvxZ09bYm/yYNgPKCzgWtaRqDTgIKRgIRHBfU6Z8= +github.com/go-git/go-git/v5 v5.16.3/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= -github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -971,32 +417,26 @@ 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-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= -github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-restruct/restruct v1.2.0-alpha h1:2Lp474S/9660+SJjpVxoKuWX09JsXHSrdV7Nv3/gkvc= github.com/go-restruct/restruct v1.2.0-alpha/go.mod h1:KqrpKpn4M8OLznErihXTGLlsXFGeLxHUrLRRI/1YjGk= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk= -github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= -github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/gohugoio/hashstructure v0.5.0 h1:G2fjSBU36RdwEJBWJ+919ERvOVqAg9tfcYp47K9swqg= -github.com/gohugoio/hashstructure v0.5.0/go.mod h1:Ser0TniXuu/eauYmrwM4o64EBvySxNzITEOLlm4igec= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/gohugoio/hashstructure v0.6.0 h1:7wMB/2CfXoThFYhdWRGv3u3rUM761Cq29CxUW+NltUg= +github.com/gohugoio/hashstructure v0.6.0/go.mod h1:lapVLk9XidheHG1IQ4ZSbyYrXcaILU1ZEP/+vno5rBQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -1029,7 +469,6 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -1037,7 +476,6 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= 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= @@ -1050,8 +488,6 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -1066,7 +502,6 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= 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/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -1078,7 +513,6 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= @@ -1092,40 +526,27 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0/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.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gookit/assert v0.1.1 h1:lh3GcawXe/p+cU7ESTZ5Ui3Sm/x8JWpIis4/1aF0mY0= +github.com/gookit/assert v0.1.1/go.mod h1:jS5bmIVQZTIwk42uXl4lyj4iaaxx32tqH16CFj0VX2E= github.com/gookit/color v1.2.5/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg= -github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= -github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= +github.com/gookit/color v1.6.0 h1:JjJXBTk1ETNyqyilJhkTXJYYigHG24TM9Xa2M1xAhRA= +github.com/gookit/color v1.6.0/go.mod h1:9ACFc7/1IpHGBW8RwuDm/0YEnhg3dwwXpoMsmtyHfjs= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.65 h1:81+kWbE1yErFBMjME0I5k3x3kojjKsWtPYHEAutoPow= +github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.65/go.mod h1:WtMzv9T++tfWVea+qB2MXoaqxw33S8bpJslzUike2mQ= github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -1135,8 +556,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 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-getter v1.7.8 h1:mshVHx1Fto0/MydBekWan5zUipGq7jO0novchgMmSiY= -github.com/hashicorp/go-getter v1.7.8/go.mod h1:2c6CboOEb9jG6YvmC9xdD+tyAFsrUaJPedwXDGr0TM4= +github.com/hashicorp/go-getter v1.8.2 h1:CGCK+bZQLl44PYiwJweVzfpjg7bBwtuXu3AGcLiod2o= +github.com/hashicorp/go-getter v1.8.2/go.mod h1:CUTt9x2bCtJ/sV8ihgrITL3IUE+0BE1j/e4n5P/GIM4= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -1148,8 +569,6 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= -github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -1162,8 +581,8 @@ github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/hcl/v2 v2.23.0 h1:Fphj1/gCylPxHutVSEOf2fBOh1VE4AuLV7+kbJf3qos= -github.com/hashicorp/hcl/v2 v2.23.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA= +github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQxvE= +github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= @@ -1173,8 +592,9 @@ github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKEN github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk= github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= +github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= +github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= @@ -1189,14 +609,10 @@ github.com/invopop/jsonschema v0.7.0 h1:2vgQcBz1n256N+FpX3Jq7Y17AjYt46Ig3zIWyy77 github.com/invopop/jsonschema v0.7.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0= 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/jedib0t/go-pretty/v6 v6.6.7 h1:m+LbHpm0aIAPLzLbMfn8dc3Ht8MW7lsSO4MPItz/Uuo= -github.com/jedib0t/go-pretty/v6 v6.6.7/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= +github.com/jedib0t/go-pretty/v6 v6.6.8 h1:JnnzQeRz2bACBobIaa/r+nqjvws4yEhcmaZ4n1QzsEc= +github.com/jedib0t/go-pretty/v6 v6.6.8/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -1205,23 +621,16 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953 h1:WdAeg/imY2JFPc/9CST4bZ80nNJbiBFCAdSZCSgrS5Y= github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953/go.mod h1:6o+UrvuZWc4UTyBhQf0LGjW9Ld7qJxLz/OqvSOWWlEc= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -1229,8 +638,6 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 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= @@ -1246,9 +653,6 @@ github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/z 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/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= -github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= @@ -1260,23 +664,20 @@ github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +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.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 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-localereader v0.0.2-0.20220822084749-2491eb6c1c75 h1:P8UmIzZMYDR+NGImiFvErt6VWfIRPuGM+vyjiEdkmIw= github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= @@ -1287,8 +688,6 @@ github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKju github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/mikelolasagasti/xz v1.0.1 h1:Q2F2jX0RYJUG3+WsM+FJknv+6eVjsjXNDV0KJXZzkD0= github.com/mikelolasagasti/xz v1.0.1/go.mod h1:muAirjiOUxPRXwm9HdDtB3uoRPrGnL85XHtokL9Hcgc= -github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= -github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/minio/minlz v1.0.0 h1:Kj7aJZ1//LlTP1DM8Jm7lNKvvJS2m74gyyXXn3+uJWQ= github.com/minio/minlz v1.0.0/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= @@ -1297,8 +696,6 @@ github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HK 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/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= -github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -1346,14 +743,14 @@ github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1a github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc= github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= -github.com/nwaples/rardecode/v2 v2.1.0 h1:JQl9ZoBPDy+nIZGb1mx8+anfHp/LV3NE2MjMiv0ct/U= -github.com/nwaples/rardecode/v2 v2.1.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw= -github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6 h1:r3FaAI0NZK3hSmtTDrBVREhKULp8oUeqLT5Eyl2mSPo= -github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= -github.com/olekukonko/ll v0.0.8 h1:sbGZ1Fx4QxJXEqL/6IG8GEFnYojUSQ45dJVwN2FH2fc= -github.com/olekukonko/ll v0.0.8/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g= -github.com/olekukonko/tablewriter v1.0.7 h1:HCC2e3MM+2g72M81ZcJU11uciw6z/p82aEnm4/ySDGw= -github.com/olekukonko/tablewriter v1.0.7/go.mod h1:H428M+HzoUXC6JU2Abj9IT9ooRmdq9CxuDmKMtrOCMs= +github.com/nwaples/rardecode/v2 v2.2.0 h1:4ufPGHiNe1rYJxYfehALLjup4Ls3ck42CWwjKiOqu0A= +github.com/nwaples/rardecode/v2 v2.2.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw= +github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= +github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= +github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI= +github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g= +github.com/olekukonko/tablewriter v1.0.9 h1:XGwRsYLC2bY7bNd93Dk51bcPZksWZmLYuaTHR0FqfL8= +github.com/olekukonko/tablewriter v1.0.9/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo= github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -1374,10 +771,6 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= -github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= -github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= 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.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= @@ -1390,7 +783,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pkg/xattr v0.4.9 h1:5883YPCtkSd8LFbs13nXplj9g9tlrwoJRjgpgMu1/fE= github.com/pkg/xattr v0.4.9/go.mod h1:di8WF84zAKk8jzR1UBTEWh9AUlIZZ7M/JNt8e9B6ktU= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1406,7 +798,6 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1: github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -1414,9 +805,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= -github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/quasilyte/go-ruleguard/dsl v0.3.23 h1:lxjt5B6ZCiBeeNO8/oQsegE6fLeCzuMRoVWSkXC4uvY= +github.com/quasilyte/go-ruleguard/dsl v0.3.23/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -1424,15 +814,12 @@ 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/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= 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/rust-secure-code/go-rustaudit v0.0.0-20250226111315-e20ec32e963c h1:8gOLsYwaY2JwlTMT4brS5/9XJdrdIbmk2obvQ748CC0= github.com/rust-secure-code/go-rustaudit v0.0.0-20250226111315-e20ec32e963c/go.mod h1:kwM/7r/rVluTE8qJbHAffduuqmSv4knVQT2IajGvSiA= -github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= -github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= @@ -1449,8 +836,8 @@ github.com/sassoftware/go-rpmutils v0.4.0/go.mod h1:3goNWi7PGAT3/dlql2lv3+MSN5jN github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e h1:7q6NSFZDeGfvvtIRwBrU/aegEYJYmvev0cHAwo17zZQ= github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sebdah/goldie/v2 v2.5.5 h1:rx1mwF95RxZ3/83sdS4Yp7t2C5TCokvWP4TBRbAyEWY= -github.com/sebdah/goldie/v2 v2.5.5/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= +github.com/sebdah/goldie/v2 v2.7.1 h1:PkBHymaYdtvEkZV7TmyqKxdmn5/Vcj+8TpATWZjnG5E= +github.com/sebdah/goldie/v2 v2.7.1/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= @@ -1475,19 +862,18 @@ github.com/spdx/tools-golang v0.5.5 h1:61c0KLfAcNqAjlg6UNMdkwpMernhw3zVRwDZ2x9XO github.com/spdx/tools-golang v0.5.5/go.mod h1:MVIsXx8ZZzaRWNQpUDhC4Dud34edUYJYecciXgrw5vE= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= -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/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= -github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= -github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= +github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY= github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= @@ -1508,16 +894,15 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +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/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/sylabs/sif/v2 v2.21.1 h1:GZ0b5//AFAqJEChd8wHV/uSKx/l1iuGYwjR8nx+4wPI= -github.com/sylabs/sif/v2 v2.21.1/go.mod h1:YoqEGQnb5x/ItV653bawXHZJOXQaEWpGwHsSD3YePJI= +github.com/sylabs/sif/v2 v2.22.0 h1:Y+xXufp4RdgZe02SR3nWEg7S6q4tPWN237WHYzkDSKA= +github.com/sylabs/sif/v2 v2.22.0/go.mod h1:W1XhWTmG1KcG7j5a3KSYdMcUIFvbs240w/MMVW627hs= github.com/sylabs/squashfs v1.0.6 h1:PvJcDzxr+vIm2kH56mEMbaOzvGu79gK7P7IX+R7BDZI= github.com/sylabs/squashfs v1.0.6/go.mod h1:DlDeUawVXLWAsSRa085Eo0ZenGzAB32JdAUFaB0LZfE= github.com/terminalstatic/go-xsd-validate v0.1.6 h1:TenYeQ3eY631qNi1/cTmLH/s2slHPRKTTHT+XSHkepo= @@ -1536,11 +921,10 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= -github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/vbatts/go-mtree v0.5.4 h1:OMAb8jaCyiFA7zXj0Zc/oARcxBDBoeu2LizjB8BVJl0= -github.com/vbatts/go-mtree v0.5.4/go.mod h1:5GqJbVhm9BBiCc4K5uc/c42FPgXulHaQs4sFUEfIWMo= +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/go-mtree v0.6.0 h1:n4r+Tweta4oH0+zWfv77VmfvWXrO69smspK37xvzgMI= +github.com/vbatts/go-mtree v0.6.0/go.mod h1:W7bcG9PCn6lFY+ljGlZxx9DONkxL3v8a7HyN+PrSrjA= github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo= github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= github.com/vifraa/gopom v1.0.0 h1:L9XlKbyvid8PAIK8nr0lihMApJQg/12OBvMA28BcWh0= @@ -1569,14 +953,11 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zclconf/go-cty v1.13.0 h1:It5dfKTTZHe9aeppbNOda3mN7Ag7sg6QkBNm6TkyFa0= -github.com/zclconf/go-cty v1.13.0/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0= +github.com/zclconf/go-cty v1.16.3 h1:osr++gw2T61A8KVYHoQiFbFd1Lh3JOCXc/jFLJXKTxk= +github.com/zclconf/go-cty v1.16.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= -github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= -github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1 h1:V+UsotZpAVvfj3X/LMoEytoLzSiP6Lg0F7wdVyu9gGg= github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1/go.mod h1:ly2RBz4mnz1yeuVbQA/VFwGjK3mnHGRj1JuoG336Bis= go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= @@ -1612,8 +993,6 @@ go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRa go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -1625,6 +1004,8 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc= go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1636,47 +1017,25 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/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.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= -golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= -golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= +golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= -golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM= -golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= +golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= 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-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1701,16 +1060,9 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= -golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= +golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= 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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1745,7 +1097,6 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= @@ -1753,34 +1104,11 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= -golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= -golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1798,19 +1126,6 @@ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= -golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1824,17 +1139,9 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/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.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= -golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1880,16 +1187,13 @@ golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1903,59 +1207,23 @@ golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/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.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/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.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= 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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= -golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= -golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= +golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= +golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1965,31 +1233,16 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/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.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= -golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= +golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= 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-20190206041539-40960b6deb8e/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-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -2003,7 +1256,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -2033,45 +1285,25 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= -golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= +golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= -gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= -gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -2104,33 +1336,6 @@ google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdr google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= -google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= -google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= -google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= -google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= -google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= -google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= -google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= -google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= google.golang.org/api v0.203.0 h1:SrEeuwU3S11Wlscsn+LA1kb/Y5xT8uggJSkIhD08NAU= google.golang.org/api v0.203.0/go.mod h1:BuOVyCSYEPwJb3npWvDnNmFI92f3GeRnHNkETneT3SI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -2175,13 +1380,10 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= @@ -2206,76 +1408,6 @@ google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= -google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= -google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= -google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= -google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= -google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= -google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= -google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk= google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc= google.golang.org/genproto/googleapis/api v0.0.0-20241113202542-65e8d215514f h1:M65LEviCfuZTfrfzwwEoxVtgvfkFkBUbFnRbxCXuXhU= @@ -2309,20 +1441,6 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= -google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc v1.67.3 h1:OgPcDAFKHnH8X3O4WcO4XUc8GRDeKsKReqbQtiCj7N8= google.golang.org/grpc v1.67.3/go.mod h1:YGaHCc6Oap+FzBJTZLBzkGSYt/cvGPFTPxkn7QfSU8s= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= @@ -2339,20 +1457,14 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= -google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= @@ -2363,7 +1475,6 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 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.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -2378,67 +1489,33 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s= -modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= -modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= -modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= -modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= -modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= +modernc.org/cc/v4 v4.26.2 h1:991HMkLjJzYBIfha6ECZdjrIYz2/1ayr+FL8GN+CNzM= +modernc.org/cc/v4 v4.26.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU= modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE= -modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= -modernc.org/fileutil v1.3.3 h1:3qaU+7f7xxTUmvU1pJTZiDLAIoJVdUSSauJNHg9yXoA= -modernc.org/fileutil v1.3.3/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= +modernc.org/fileutil v1.3.8 h1:qtzNm7ED75pd1C7WgAGcK4edm4fvhtBsEiI/0NQ54YM= +modernc.org/fileutil v1.3.8/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= -modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= -modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= -modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= -modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= -modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= -modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= -modernc.org/libc v1.65.10 h1:ZwEk8+jhW7qBjHIT+wd0d9VjitRyQef9BnzlzGwMODc= -modernc.org/libc v1.65.10/go.mod h1:StFvYpx7i/mXtBAfVOjaU0PWZOvIRoZSgXhrwXzr8Po= -modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= +modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= +modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ= +modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= -modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= -modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= -modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= -modernc.org/sqlite v1.38.0 h1:+4OrfPQ8pxHKuWG4md1JpR/EYAh3Md7TdejuuzE7EUI= -modernc.org/sqlite v1.38.0/go.mod h1:1Bj+yES4SVvBZ4cBOpVZ6QgesMCKpJZDq0nxYzOpmNE= -modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= -modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/sqlite v1.39.0 h1:6bwu9Ooim0yVYA7IZn9demiQk/Ejp0BtTjBWFLymSeY= +modernc.org/sqlite v1.39.0/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E= modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= -modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= -modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/install.sh b/install.sh index 1c2f49f0f5d..41d0a22a829 100755 --- a/install.sh +++ b/install.sh @@ -6,7 +6,8 @@ PROJECT_NAME=syft OWNER=anchore REPO="${PROJECT_NAME}" GITHUB_DOWNLOAD_PREFIX=https://github.com/${OWNER}/${REPO}/releases/download -INSTALL_SH_BASE_URL=https://raw.githubusercontent.com/${OWNER}/${PROJECT_NAME} +INSTALL_SH_BASE_URL=https://get.anchore.io/${PROJECT_NAME} +LEGACY_INSTALL_SH_BASE_URL=https://raw.githubusercontent.com/${OWNER}/${PROJECT_NAME} PROGRAM_ARGS=$@ # signature verification options @@ -836,7 +837,11 @@ EOF if [ "${DOWNLOAD_TAG_INSTALL_SCRIPT}" = "true" ]; then export DOWNLOAD_TAG_INSTALL_SCRIPT=false log_info "fetching release script for tag='${tag}'" - http_copy "${INSTALL_SH_BASE_URL}/${tag}/install.sh" "" | sh -s -- ${PROGRAM_ARGS} + if ! install_script=$(http_copy "${INSTALL_SH_BASE_URL}/${tag}/install.sh" ""); then + log_warn "failed to fetch from ${INSTALL_SH_BASE_URL}, trying fallback URL" + install_script=$(http_copy "${LEGACY_INSTALL_SH_BASE_URL}/${tag}/install.sh" "") + fi + echo "${install_script}" | sh -s -- ${PROGRAM_ARGS} exit $? fi diff --git a/internal/cache/README.md b/internal/cache/README.md index b24a6f93408..5ecf4a04c9d 100644 --- a/internal/cache/README.md +++ b/internal/cache/README.md @@ -18,7 +18,7 @@ based on the _structure_ of the provided type. If the structure changes in any way it will end up with a new version key and all will re populate this new key, ignoring cached values from older, different versions. The resolver will store items using the `json` package to serialize/deserialize values, so to save space -it is encouraged to use `omitempty`. For example: +it is encouraged to use `omitempty`. For example: ```go type myCacheItem struct { diff --git a/internal/constants.go b/internal/constants.go index 5de211174cb..d41a7bf594b 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -3,5 +3,5 @@ package internal const ( // JSONSchemaVersion is the current schema version output by the JSON encoder // This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment. - JSONSchemaVersion = "16.0.34" + JSONSchemaVersion = "16.0.40" ) diff --git a/syft/internal/generate.go b/internal/generate.go similarity index 100% rename from syft/internal/generate.go rename to internal/generate.go diff --git a/internal/jsonschema/README.md b/internal/jsonschema/README.md new file mode 100644 index 00000000000..73a6aa4e527 --- /dev/null +++ b/internal/jsonschema/README.md @@ -0,0 +1 @@ +Please see [schema/json/README.md](../../schema/json/README.md) for more information on the JSON schema files in this directory. \ No newline at end of file diff --git a/internal/jsonschema/comments.go b/internal/jsonschema/comments.go new file mode 100644 index 00000000000..0a2b08df605 --- /dev/null +++ b/internal/jsonschema/comments.go @@ -0,0 +1,159 @@ +package main + +import ( + "fmt" + "go/ast" + "go/parser" + "go/token" + "os" + "path/filepath" + "strings" + + "github.com/invopop/jsonschema" +) + +func copyAliasFieldComments(commentMap map[string]string, repoRoot string) { + // find all type aliases by parsing Go source files + aliases := findTypeAliases(repoRoot) + + // for each alias, copy field comments from the source type + for aliasName, sourceName := range aliases { + // find all field comments for the source type + for key, comment := range commentMap { + // check if this is a field comment for the source type + // format: "github.com/anchore/syft/syft/pkg.SourceType.FieldName" + if strings.Contains(key, "."+sourceName+".") { + // create the corresponding key for the alias + aliasKey := strings.Replace(key, "."+sourceName+".", "."+aliasName+".", 1) + commentMap[aliasKey] = comment + } + } + } +} + +func findTypeAliases(repoRoot string) map[string]string { + aliases := make(map[string]string) + fset := token.NewFileSet() + + // walk through all Go files in the repo + err := filepath.Walk(repoRoot, func(path string, info os.FileInfo, err error) error { + if err != nil || info.IsDir() || !strings.HasSuffix(path, ".go") { + return nil + } + + // parse the file + file, err := parser.ParseFile(fset, path, nil, parser.ParseComments) + if err != nil { + return nil + } + + // look for type alias declarations + ast.Inspect(file, func(n ast.Node) bool { + typeSpec, ok := n.(*ast.TypeSpec) + if !ok { + return true + } + + // check if this is a type alias (e.g., type A B where B is an identifier) + ident, ok := typeSpec.Type.(*ast.Ident) + if !ok { + return true + } + + // store the alias mapping: aliasName -> sourceName + aliases[typeSpec.Name.Name] = ident.Name + return true + }) + + return nil + }) + + if err != nil { + fmt.Fprintf(os.Stderr, "error: failed to find type aliases: %v\n", err) + panic(err) + } + + return aliases +} + +func hasDescriptionInAlternatives(schema *jsonschema.Schema) bool { + // check oneOf alternatives + for _, alt := range schema.OneOf { + if alt.Description != "" { + return true + } + } + // check anyOf alternatives + for _, alt := range schema.AnyOf { + if alt.Description != "" { + return true + } + } + return false +} + +func warnMissingDescriptions(schema *jsonschema.Schema, metadataNames []string) { //nolint:gocognit + var missingTypeDescriptions []string + var missingFieldDescriptions []string + + // check metadata types for missing descriptions + for _, name := range metadataNames { + def, ok := schema.Definitions[name] + if !ok { + continue + } + + // check if type has a description + if def.Description == "" { + missingTypeDescriptions = append(missingTypeDescriptions, name) + } + + // check if fields have descriptions + if def.Properties != nil { + for _, fieldName := range def.Properties.Keys() { + fieldSchemaRaw, _ := def.Properties.Get(fieldName) + fieldSchema, ok := fieldSchemaRaw.(*jsonschema.Schema) + if !ok { + continue + } + + // skip if field has a description + if fieldSchema.Description != "" { + continue + } + + // skip if field is a reference (descriptions come from the referenced type) + if fieldSchema.Ref != "" { + continue + } + + // skip if field is an array/object with items that are references + if fieldSchema.Items != nil && fieldSchema.Items.Ref != "" { + continue + } + + // skip if field uses oneOf/anyOf with descriptions in the alternatives + if hasDescriptionInAlternatives(fieldSchema) { + continue + } + + missingFieldDescriptions = append(missingFieldDescriptions, fmt.Sprintf("%s.%s", name, fieldName)) + } + } + } + + // report findings + if len(missingTypeDescriptions) > 0 { + fmt.Fprintf(os.Stderr, "\nwarning: %d metadata types are missing descriptions:\n", len(missingTypeDescriptions)) + for _, name := range missingTypeDescriptions { + fmt.Fprintf(os.Stderr, " - %s\n", name) + } + } + + if len(missingFieldDescriptions) > 0 { + fmt.Fprintf(os.Stderr, "\nwarning: %d fields are missing descriptions:\n", len(missingFieldDescriptions)) + for _, field := range missingFieldDescriptions { + fmt.Fprintf(os.Stderr, " - %s\n", field) + } + } +} diff --git a/internal/jsonschema/comments_test.go b/internal/jsonschema/comments_test.go new file mode 100644 index 00000000000..2d0f4fa2cfc --- /dev/null +++ b/internal/jsonschema/comments_test.go @@ -0,0 +1,382 @@ +package main + +import ( + "os" + "path/filepath" + "testing" + + "github.com/iancoleman/orderedmap" + "github.com/invopop/jsonschema" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestCopyAliasFieldComments verifies that field comments from source types are correctly copied to alias types. +// This is important for type aliases like `type RpmArchive RpmDBEntry` where the alias should inherit all field descriptions. +func TestCopyAliasFieldComments(t *testing.T) { + tests := []struct { + name string + commentMap map[string]string + aliases map[string]string + wantComments map[string]string + }{ + { + name: "copies field comments from source type to alias", + commentMap: map[string]string{ + "github.com/anchore/syft/syft/pkg.RpmDBEntry": "RpmDBEntry represents all captured data from a RPM DB package entry.", + "github.com/anchore/syft/syft/pkg.RpmDBEntry.Name": "Name is the RPM package name.", + "github.com/anchore/syft/syft/pkg.RpmDBEntry.Epoch": "Epoch is the version epoch.", + }, + aliases: map[string]string{ + "RpmArchive": "RpmDBEntry", + }, + wantComments: map[string]string{ + "github.com/anchore/syft/syft/pkg.RpmDBEntry": "RpmDBEntry represents all captured data from a RPM DB package entry.", + "github.com/anchore/syft/syft/pkg.RpmDBEntry.Name": "Name is the RPM package name.", + "github.com/anchore/syft/syft/pkg.RpmDBEntry.Epoch": "Epoch is the version epoch.", + "github.com/anchore/syft/syft/pkg.RpmArchive.Name": "Name is the RPM package name.", + "github.com/anchore/syft/syft/pkg.RpmArchive.Epoch": "Epoch is the version epoch.", + }, + }, + { + name: "handles multiple aliases", + commentMap: map[string]string{ + "github.com/anchore/syft/syft/pkg.DpkgDBEntry": "DpkgDBEntry represents data from dpkg.", + "github.com/anchore/syft/syft/pkg.DpkgDBEntry.Package": "Package is the package name.", + "github.com/anchore/syft/syft/pkg.DpkgDBEntry.Architecture": "Architecture is the target arch.", + }, + aliases: map[string]string{ + "DpkgArchiveEntry": "DpkgDBEntry", + "DpkgSnapshot": "DpkgDBEntry", + }, + wantComments: map[string]string{ + "github.com/anchore/syft/syft/pkg.DpkgDBEntry": "DpkgDBEntry represents data from dpkg.", + "github.com/anchore/syft/syft/pkg.DpkgDBEntry.Package": "Package is the package name.", + "github.com/anchore/syft/syft/pkg.DpkgDBEntry.Architecture": "Architecture is the target arch.", + "github.com/anchore/syft/syft/pkg.DpkgArchiveEntry.Package": "Package is the package name.", + "github.com/anchore/syft/syft/pkg.DpkgArchiveEntry.Architecture": "Architecture is the target arch.", + "github.com/anchore/syft/syft/pkg.DpkgSnapshot.Package": "Package is the package name.", + "github.com/anchore/syft/syft/pkg.DpkgSnapshot.Architecture": "Architecture is the target arch.", + }, + }, + { + name: "does not copy non-field comments", + commentMap: map[string]string{ + "github.com/anchore/syft/syft/pkg.SomeType": "SomeType struct comment.", + "github.com/anchore/syft/syft/pkg.SomeType.Field": "Field comment.", + }, + aliases: map[string]string{ + "AliasType": "SomeType", + }, + wantComments: map[string]string{ + "github.com/anchore/syft/syft/pkg.SomeType": "SomeType struct comment.", + "github.com/anchore/syft/syft/pkg.SomeType.Field": "Field comment.", + "github.com/anchore/syft/syft/pkg.AliasType.Field": "Field comment.", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // create temp dir for testing + tmpDir := t.TempDir() + + // create a test go file with type aliases + testFile := filepath.Join(tmpDir, "test.go") + content := "package test\n\n" + for alias, source := range tt.aliases { + content += "type " + alias + " " + source + "\n" + } + err := os.WriteFile(testFile, []byte(content), 0644) + require.NoError(t, err) + + // make a copy of the comment map since the function modifies it + commentMap := make(map[string]string) + for k, v := range tt.commentMap { + commentMap[k] = v + } + + // run the function + copyAliasFieldComments(commentMap, tmpDir) + + // verify results + assert.Equal(t, tt.wantComments, commentMap) + }) + } +} + +func TestFindTypeAliases(t *testing.T) { + tests := []struct { + name string + fileContent string + wantAliases map[string]string + }{ + { + name: "finds simple type alias", + fileContent: `package test + +type RpmArchive RpmDBEntry +type DpkgArchiveEntry DpkgDBEntry +`, + wantAliases: map[string]string{ + "RpmArchive": "RpmDBEntry", + "DpkgArchiveEntry": "DpkgDBEntry", + }, + }, + { + name: "ignores struct definitions", + fileContent: `package test + +type MyStruct struct { + Field string +} + +type AliasType BaseType +`, + wantAliases: map[string]string{ + "AliasType": "BaseType", + }, + }, + { + name: "ignores interface definitions", + fileContent: `package test + +type MyInterface interface { + Method() +} + +type AliasType BaseType +`, + wantAliases: map[string]string{ + "AliasType": "BaseType", + }, + }, + { + name: "handles multiple files", + fileContent: `package test + +type Alias1 Base1 +type Alias2 Base2 +`, + wantAliases: map[string]string{ + "Alias1": "Base1", + "Alias2": "Base2", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // create temp dir + tmpDir := t.TempDir() + + // write test file + testFile := filepath.Join(tmpDir, "test.go") + err := os.WriteFile(testFile, []byte(tt.fileContent), 0644) + require.NoError(t, err) + + // run function + aliases := findTypeAliases(tmpDir) + + // verify + assert.Equal(t, tt.wantAliases, aliases) + }) + } +} + +func TestHasDescriptionInAlternatives(t *testing.T) { + tests := []struct { + name string + schema *jsonschema.Schema + want bool + }{ + { + name: "returns true when oneOf has description", + schema: &jsonschema.Schema{ + OneOf: []*jsonschema.Schema{ + {Description: "First alternative"}, + {Type: "null"}, + }, + }, + want: true, + }, + { + name: "returns true when anyOf has description", + schema: &jsonschema.Schema{ + AnyOf: []*jsonschema.Schema{ + {Description: "First alternative"}, + {Type: "null"}, + }, + }, + want: true, + }, + { + name: "returns false when no alternatives have descriptions", + schema: &jsonschema.Schema{ + OneOf: []*jsonschema.Schema{ + {Type: "integer"}, + {Type: "null"}, + }, + }, + want: false, + }, + { + name: "returns false when no oneOf or anyOf", + schema: &jsonschema.Schema{ + Type: "string", + }, + want: false, + }, + { + name: "returns true when any alternative in oneOf has description", + schema: &jsonschema.Schema{ + OneOf: []*jsonschema.Schema{ + {Type: "integer"}, + {Type: "string", Description: "Second alternative"}, + {Type: "null"}, + }, + }, + want: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := hasDescriptionInAlternatives(tt.schema) + assert.Equal(t, tt.want, got) + }) + } +} + +func TestWarnMissingDescriptions(t *testing.T) { + tests := []struct { + name string + schema *jsonschema.Schema + metadataNames []string + wantTypeWarnings int + wantFieldWarnings int + }{ + { + name: "no warnings when all types have descriptions", + schema: &jsonschema.Schema{ + Definitions: map[string]*jsonschema.Schema{ + "TypeA": { + Description: "Type A description", + Properties: newOrderedMap(map[string]*jsonschema.Schema{ + "field1": {Type: "string", Description: "Field 1"}, + }), + }, + }, + }, + metadataNames: []string{"TypeA"}, + wantTypeWarnings: 0, + wantFieldWarnings: 0, + }, + { + name: "warns about missing type description", + schema: &jsonschema.Schema{ + Definitions: map[string]*jsonschema.Schema{ + "TypeA": { + Properties: newOrderedMap(map[string]*jsonschema.Schema{ + "field1": {Type: "string", Description: "Field 1"}, + }), + }, + }, + }, + metadataNames: []string{"TypeA"}, + wantTypeWarnings: 1, + wantFieldWarnings: 0, + }, + { + name: "warns about missing field description", + schema: &jsonschema.Schema{ + Definitions: map[string]*jsonschema.Schema{ + "TypeA": { + Description: "Type A description", + Properties: newOrderedMap(map[string]*jsonschema.Schema{ + "field1": {Type: "string"}, + }), + }, + }, + }, + metadataNames: []string{"TypeA"}, + wantTypeWarnings: 0, + wantFieldWarnings: 1, + }, + { + name: "skips fields with references", + schema: &jsonschema.Schema{ + Definitions: map[string]*jsonschema.Schema{ + "TypeA": { + Description: "Type A description", + Properties: newOrderedMap(map[string]*jsonschema.Schema{ + "field1": {Ref: "#/$defs/OtherType"}, + }), + }, + }, + }, + metadataNames: []string{"TypeA"}, + wantTypeWarnings: 0, + wantFieldWarnings: 0, + }, + { + name: "skips fields with items that are references", + schema: &jsonschema.Schema{ + Definitions: map[string]*jsonschema.Schema{ + "TypeA": { + Description: "Type A description", + Properties: newOrderedMap(map[string]*jsonschema.Schema{ + "field1": { + Type: "array", + Items: &jsonschema.Schema{Ref: "#/$defs/OtherType"}, + }, + }), + }, + }, + }, + metadataNames: []string{"TypeA"}, + wantTypeWarnings: 0, + wantFieldWarnings: 0, + }, + { + name: "skips fields with oneOf containing descriptions", + schema: &jsonschema.Schema{ + Definitions: map[string]*jsonschema.Schema{ + "TypeA": { + Description: "Type A description", + Properties: newOrderedMap(map[string]*jsonschema.Schema{ + "field1": { + OneOf: []*jsonschema.Schema{ + {Type: "integer", Description: "Integer value"}, + {Type: "null"}, + }, + }, + }), + }, + }, + }, + metadataNames: []string{"TypeA"}, + wantTypeWarnings: 0, + wantFieldWarnings: 0, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // capture stderr output would require more complex testing + // for now, just verify the function runs without panicking + require.NotPanics(t, func() { + warnMissingDescriptions(tt.schema, tt.metadataNames) + }) + }) + } +} + +// helper to create an ordered map from a regular map +func newOrderedMap(m map[string]*jsonschema.Schema) *orderedmap.OrderedMap { + om := orderedmap.New() + for k, v := range m { + om.Set(k, v) + } + return om +} diff --git a/syft/internal/jsonschema/main.go b/internal/jsonschema/main.go similarity index 76% rename from syft/internal/jsonschema/main.go rename to internal/jsonschema/main.go index 731ffd9172d..9f3f19d3502 100644 --- a/syft/internal/jsonschema/main.go +++ b/internal/jsonschema/main.go @@ -15,8 +15,8 @@ import ( "github.com/invopop/jsonschema" "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/packagemetadata" syftJsonModel "github.com/anchore/syft/syft/format/syftjson/model" - "github.com/anchore/syft/syft/internal/packagemetadata" ) /* @@ -26,6 +26,17 @@ are not captured (empty interfaces). This means that pkg.Package.Metadata is not can be extended to include specific package metadata struct shapes in the future. */ +var repoRoot string + +func init() { + var err error + repoRoot, err = packagemetadata.RepoRoot() + if err != nil { + fmt.Println("unable to determine repo root") + os.Exit(1) + } +} + func main() { write(encode(build())) } @@ -60,7 +71,7 @@ func assembleTypeContainer(items []any) (any, map[string]string) { } if len(typesMissingNames) > 0 { - fmt.Println("the following types are missing JSON names (manually curated in ./syft/internal/packagemetadata/names.go):") + fmt.Println("the following types are missing JSON names (manually curated in ./internal/packagemetadata/names.go):") for _, t := range typesMissingNames { fmt.Println(" - ", t.Name()) } @@ -78,6 +89,38 @@ func build() *jsonschema.Schema { Namer: func(r reflect.Type) string { return strings.TrimPrefix(r.Name(), "JSON") }, + CommentMap: make(map[string]string), + } + + // extract comments from Go source files to enrich schema descriptions + // + // note: AddGoComments parses from the module root and creates keys like "syft/pkg.TypeName", + // but the reflector expects fully qualified paths like "github.com/anchore/syft/syft/pkg.TypeName". + // We fix up the keys after extraction to match the expected format. + if err := reflector.AddGoComments("github.com/anchore/syft", repoRoot); err != nil { + fmt.Fprintf(os.Stderr, "warning: failed to extract Go comments: %v\n", err) + } else { + // fix up comment map keys to use fully qualified import paths + // note: AddGoComments includes the absolute repo path WITHOUT the leading slash + repoRootNoSlash := strings.TrimPrefix(repoRoot, "/") + fixedMap := make(map[string]string) + for k, v := range reflector.CommentMap { + newKey := k + if !strings.HasPrefix(k, "github.com/") { + // key doesn't have module prefix, add it + newKey = "github.com/anchore/syft/" + k + } else if strings.Contains(k, repoRootNoSlash) { + // key has the absolute repo path embedded, strip it + // format: github.com/anchore/syft/Users/wagoodman/code/syft-manual/syft/pkg.Type + // should be: github.com/anchore/syft/syft/pkg.Type + newKey = strings.Replace(k, repoRootNoSlash+"/", "", 1) + } + fixedMap[newKey] = v + } + reflector.CommentMap = fixedMap + + // copy field comments for type aliases (e.g., type RpmArchive RpmDBEntry) + copyAliasFieldComments(reflector.CommentMap, repoRoot) } pkgMetadataContainer, pkgMetadataMapping := assembleTypeContainer(packagemetadata.AllTypes()) @@ -130,6 +173,9 @@ func build() *jsonschema.Schema { "anyOf": metadataTypes, }) + // warn about missing descriptions + warnMissingDescriptions(documentSchema, metadataNames) + return documentSchema } @@ -148,11 +194,6 @@ func encode(schema *jsonschema.Schema) []byte { } func write(schema []byte) { - repoRoot, err := packagemetadata.RepoRoot() - if err != nil { - fmt.Println("unable to determine repo root") - os.Exit(1) - } schemaPath := filepath.Join(repoRoot, "schema", "json", fmt.Sprintf("schema-%s.json", internal.JSONSchemaVersion)) latestSchemaPath := filepath.Join(repoRoot, "schema", "json", "schema-latest.json") diff --git a/internal/os/feature_detection.go b/internal/os/feature_detection.go new file mode 100644 index 00000000000..c23b8b67b25 --- /dev/null +++ b/internal/os/feature_detection.go @@ -0,0 +1,61 @@ +package os + +import ( + "context" + "fmt" + "regexp" + + "github.com/anchore/syft/internal" + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/sbomsync" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/linux" + "github.com/anchore/syft/syft/sbom" +) + +func DetectFeatures(_ context.Context, resolver file.Resolver, builder sbomsync.Builder) error { + builder.(sbomsync.Accessor).WriteToSBOM(func(s *sbom.SBOM) { + if s.Artifacts.LinuxDistribution == nil { + return + } + + err := findRhelFeatures(resolver, s.Artifacts.LinuxDistribution) + if err != nil { + log.WithFields("error", err, "release", s.Artifacts.LinuxDistribution).Trace("error searching for extended support") + } + }) + + return nil +} + +func findRhelFeatures(resolver file.Resolver, release *linux.Release) error { + if release == nil || release.ID != "rhel" { + return nil + } + contentManifestFiles, err := resolver.FilesByGlob("/root/buildinfo/content_manifests/*.json") + if err != nil { + return fmt.Errorf("unable to find content manifests: %w", err) + } + for _, contentManifestFile := range contentManifestFiles { + found, err := hasRhelExtendedSupportInContentManifest(resolver, contentManifestFile) + if err != nil { + return fmt.Errorf("unable to read content manifest from %s: %w", contentManifestFile.String(), err) + } + if found { + release.ExtendedSupport = true + break + } + } + return nil +} + +func hasRhelExtendedSupportInContentManifest(resolver file.Resolver, contentManifestFile file.Location) (bool, error) { + contents, err := resolver.FileContentsByLocation(contentManifestFile) + if err != nil { + return false, fmt.Errorf("unable to read content manifest from %s: %w", contentManifestFile.String(), err) + } + defer internal.CloseAndLogError(contents, "content-manifest") + + patterns := []*regexp.Regexp{regexp.MustCompile(`baseos-eus`), regexp.MustCompile(`baseos-eus|appstream-eus`)} + return internal.MatchAnyFromReader(contents, patterns...) +} diff --git a/internal/os/feature_detection_test.go b/internal/os/feature_detection_test.go new file mode 100644 index 00000000000..f7622e7ff6a --- /dev/null +++ b/internal/os/feature_detection_test.go @@ -0,0 +1,97 @@ +package os_test + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/anchore/stereoscope/pkg/imagetest" + "github.com/anchore/syft/internal/os" + "github.com/anchore/syft/internal/sbomsync" + "github.com/anchore/syft/internal/task" + "github.com/anchore/syft/syft" + "github.com/anchore/syft/syft/linux" + "github.com/anchore/syft/syft/sbom" + "github.com/anchore/syft/syft/source" +) + +func Test_EnvironmentTask(t *testing.T) { + tests := []struct { + name string + expected linux.Release + }{ + { + name: "not_rhel", + expected: linux.Release{ + PrettyName: "Red Hat Enterprise Linux 9.4 (Plow)", + Name: "Red Hat Enterprise Linux", + ID: "not-rhel", + IDLike: []string{ + "fedora", + }, + Version: "9.4 (Plow)", + VersionID: "9.4", + HomeURL: "https://www.redhat.com/", + BugReportURL: "https://issues.redhat.com/", + CPEName: "cpe:/o:redhat:enterprise_linux:9::baseos", + ExtendedSupport: false, // important + }, + }, + { + name: "rhel_content_manifests", + expected: linux.Release{ + PrettyName: "Red Hat Enterprise Linux 9.4 (Plow)", + Name: "Red Hat Enterprise Linux", + ID: "rhel", + IDLike: []string{ + "fedora", + }, + Version: "9.4 (Plow)", + VersionID: "9.4", + HomeURL: "https://www.redhat.com/", + BugReportURL: "https://issues.redhat.com/", + CPEName: "cpe:/o:redhat:enterprise_linux:9::baseos", + ExtendedSupport: true, // important + }, + }, + { + name: "rhel_no_manifests", + expected: linux.Release{ + PrettyName: "Red Hat Enterprise Linux 9.4 (Plow)", + Name: "Red Hat Enterprise Linux", + ID: "rhel", + IDLike: []string{ + "fedora", + }, + Version: "9.4 (Plow)", + VersionID: "9.4", + HomeURL: "https://www.redhat.com/", + BugReportURL: "https://issues.redhat.com/", + CPEName: "cpe:/o:redhat:enterprise_linux:9::baseos", + ExtendedSupport: false, // important + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + tarPath := imagetest.GetFixtureImageTarPath(t, test.name) + + // get the source + theSource, err := syft.GetSource(context.Background(), tarPath, syft.DefaultGetSourceConfig().WithSources("docker-archive")) + require.NoError(t, err) + resolver, err := theSource.FileResolver(source.SquashedScope) + require.NoError(t, err) + + s := sbom.SBOM{} + err = task.NewEnvironmentTask().Execute(context.Background(), resolver, sbomsync.NewBuilder(&s)) + require.NoError(t, err) + + err = os.DetectFeatures(context.Background(), resolver, sbomsync.NewBuilder(&s)) + require.NoError(t, err) + + require.Equal(t, &test.expected, s.Artifacts.LinuxDistribution) + }) + } +} diff --git a/internal/os/test-fixtures/not_rhel/Dockerfile b/internal/os/test-fixtures/not_rhel/Dockerfile new file mode 100644 index 00000000000..93ea4767673 --- /dev/null +++ b/internal/os/test-fixtures/not_rhel/Dockerfile @@ -0,0 +1,4 @@ +FROM scratch + +COPY etc/os-release /etc/ +COPY root/buildinfo/content_manifests/*.json /root/buildinfo/content_manifests/ diff --git a/internal/os/test-fixtures/not_rhel/etc/os-release b/internal/os/test-fixtures/not_rhel/etc/os-release new file mode 100644 index 00000000000..2f0289b0537 --- /dev/null +++ b/internal/os/test-fixtures/not_rhel/etc/os-release @@ -0,0 +1,18 @@ +NAME="Red Hat Enterprise Linux" +VERSION="9.4 (Plow)" +ID="not-rhel" +ID_LIKE="fedora" +VERSION_ID="9.4" +PLATFORM_ID="platform:el9" +PRETTY_NAME="Red Hat Enterprise Linux 9.4 (Plow)" +ANSI_COLOR="0;31" +LOGO="fedora-logo-icon" +CPE_NAME="cpe:/o:redhat:enterprise_linux:9::baseos" +HOME_URL="https://www.redhat.com/" +DOCUMENTATION_URL="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9" +BUG_REPORT_URL="https://issues.redhat.com/" + +REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 9" +REDHAT_BUGZILLA_PRODUCT_VERSION=9.4 +REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux" +REDHAT_SUPPORT_PRODUCT_VERSION="9.4" diff --git a/internal/os/test-fixtures/not_rhel/root/buildinfo/content_manifests/driver-toolkit-container-v4.16.0-202411210647.p0.g1d5732f.assembly.stream.el9.json b/internal/os/test-fixtures/not_rhel/root/buildinfo/content_manifests/driver-toolkit-container-v4.16.0-202411210647.p0.g1d5732f.assembly.stream.el9.json new file mode 100644 index 00000000000..0a0af786bae --- /dev/null +++ b/internal/os/test-fixtures/not_rhel/root/buildinfo/content_manifests/driver-toolkit-container-v4.16.0-202411210647.p0.g1d5732f.assembly.stream.el9.json @@ -0,0 +1,14 @@ +{ + "image_contents": [], + "metadata": { + "icm_spec": "https://raw.githubusercontent.com/containerbuildsystem/atomic-reactor/f4abcfdaf8247a6b074f94fa84f3846f82d781c6/atomic_reactor/schemas/content_manifest.json", + "icm_version": 1, + "image_layer_index": 3 + }, + "content_sets": [ + "rhel-9-for-x86_64-appstream-eus-rpms__9_DOT_4", + "rhel-9-for-x86_64-baseos-eus-rpms__9_DOT_4", + "rhel-9-for-x86_64-rt-rpms__9_DOT_4", + "rhocp-4.16-for-rhel-9-x86_64-rpms" + ] +} \ No newline at end of file diff --git a/internal/os/test-fixtures/rhel_content_manifests/Dockerfile b/internal/os/test-fixtures/rhel_content_manifests/Dockerfile new file mode 100644 index 00000000000..93ea4767673 --- /dev/null +++ b/internal/os/test-fixtures/rhel_content_manifests/Dockerfile @@ -0,0 +1,4 @@ +FROM scratch + +COPY etc/os-release /etc/ +COPY root/buildinfo/content_manifests/*.json /root/buildinfo/content_manifests/ diff --git a/internal/os/test-fixtures/rhel_content_manifests/etc/os-release b/internal/os/test-fixtures/rhel_content_manifests/etc/os-release new file mode 100644 index 00000000000..66458c5674e --- /dev/null +++ b/internal/os/test-fixtures/rhel_content_manifests/etc/os-release @@ -0,0 +1,18 @@ +NAME="Red Hat Enterprise Linux" +VERSION="9.4 (Plow)" +ID="rhel" +ID_LIKE="fedora" +VERSION_ID="9.4" +PLATFORM_ID="platform:el9" +PRETTY_NAME="Red Hat Enterprise Linux 9.4 (Plow)" +ANSI_COLOR="0;31" +LOGO="fedora-logo-icon" +CPE_NAME="cpe:/o:redhat:enterprise_linux:9::baseos" +HOME_URL="https://www.redhat.com/" +DOCUMENTATION_URL="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9" +BUG_REPORT_URL="https://issues.redhat.com/" + +REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 9" +REDHAT_BUGZILLA_PRODUCT_VERSION=9.4 +REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux" +REDHAT_SUPPORT_PRODUCT_VERSION="9.4" diff --git a/internal/os/test-fixtures/rhel_content_manifests/root/buildinfo/content_manifests/driver-toolkit-container-v4.16.0-202411210647.p0.g1d5732f.assembly.stream.el9.json b/internal/os/test-fixtures/rhel_content_manifests/root/buildinfo/content_manifests/driver-toolkit-container-v4.16.0-202411210647.p0.g1d5732f.assembly.stream.el9.json new file mode 100644 index 00000000000..0a0af786bae --- /dev/null +++ b/internal/os/test-fixtures/rhel_content_manifests/root/buildinfo/content_manifests/driver-toolkit-container-v4.16.0-202411210647.p0.g1d5732f.assembly.stream.el9.json @@ -0,0 +1,14 @@ +{ + "image_contents": [], + "metadata": { + "icm_spec": "https://raw.githubusercontent.com/containerbuildsystem/atomic-reactor/f4abcfdaf8247a6b074f94fa84f3846f82d781c6/atomic_reactor/schemas/content_manifest.json", + "icm_version": 1, + "image_layer_index": 3 + }, + "content_sets": [ + "rhel-9-for-x86_64-appstream-eus-rpms__9_DOT_4", + "rhel-9-for-x86_64-baseos-eus-rpms__9_DOT_4", + "rhel-9-for-x86_64-rt-rpms__9_DOT_4", + "rhocp-4.16-for-rhel-9-x86_64-rpms" + ] +} \ No newline at end of file diff --git a/internal/os/test-fixtures/rhel_content_manifests/root/buildinfo/content_manifests/openshift-base-rhel9-container-v4.16.0-202411190033.p0.gb45ea65.assembly.stream.el9.json b/internal/os/test-fixtures/rhel_content_manifests/root/buildinfo/content_manifests/openshift-base-rhel9-container-v4.16.0-202411190033.p0.gb45ea65.assembly.stream.el9.json new file mode 100644 index 00000000000..ca8f4f90790 --- /dev/null +++ b/internal/os/test-fixtures/rhel_content_manifests/root/buildinfo/content_manifests/openshift-base-rhel9-container-v4.16.0-202411190033.p0.gb45ea65.assembly.stream.el9.json @@ -0,0 +1,13 @@ +{ + "image_contents": [], + "metadata": { + "icm_spec": "https://raw.githubusercontent.com/containerbuildsystem/atomic-reactor/f4abcfdaf8247a6b074f94fa84f3846f82d781c6/atomic_reactor/schemas/content_manifest.json", + "icm_version": 1, + "image_layer_index": 1 + }, + "content_sets": [ + "rhel-9-for-x86_64-appstream-eus-rpms__9_DOT_4", + "rhel-9-for-x86_64-baseos-eus-rpms__9_DOT_4", + "rhocp-4.16-for-rhel-9-x86_64-rpms" + ] +} \ No newline at end of file diff --git a/internal/os/test-fixtures/rhel_no_manifests/Dockerfile b/internal/os/test-fixtures/rhel_no_manifests/Dockerfile new file mode 100644 index 00000000000..96d504b03af --- /dev/null +++ b/internal/os/test-fixtures/rhel_no_manifests/Dockerfile @@ -0,0 +1,3 @@ +FROM scratch + +COPY ./etc/os-release /etc/ diff --git a/internal/os/test-fixtures/rhel_no_manifests/etc/os-release b/internal/os/test-fixtures/rhel_no_manifests/etc/os-release new file mode 100644 index 00000000000..66458c5674e --- /dev/null +++ b/internal/os/test-fixtures/rhel_no_manifests/etc/os-release @@ -0,0 +1,18 @@ +NAME="Red Hat Enterprise Linux" +VERSION="9.4 (Plow)" +ID="rhel" +ID_LIKE="fedora" +VERSION_ID="9.4" +PLATFORM_ID="platform:el9" +PRETTY_NAME="Red Hat Enterprise Linux 9.4 (Plow)" +ANSI_COLOR="0;31" +LOGO="fedora-logo-icon" +CPE_NAME="cpe:/o:redhat:enterprise_linux:9::baseos" +HOME_URL="https://www.redhat.com/" +DOCUMENTATION_URL="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9" +BUG_REPORT_URL="https://issues.redhat.com/" + +REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 9" +REDHAT_BUGZILLA_PRODUCT_VERSION=9.4 +REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux" +REDHAT_SUPPORT_PRODUCT_VERSION="9.4" diff --git a/syft/internal/packagemetadata/completion_tester.go b/internal/packagemetadata/completion_tester.go similarity index 73% rename from syft/internal/packagemetadata/completion_tester.go rename to internal/packagemetadata/completion_tester.go index 08a285bcf67..b677222ab25 100644 --- a/syft/internal/packagemetadata/completion_tester.go +++ b/internal/packagemetadata/completion_tester.go @@ -12,6 +12,7 @@ type CompletionTester struct { } func NewCompletionTester(t testing.TB, ignore ...any) *CompletionTester { + t.Helper() tester := &CompletionTester{ valid: AllTypes(), ignore: ignore, @@ -23,6 +24,14 @@ func NewCompletionTester(t testing.TB, ignore ...any) *CompletionTester { return tester } +func (tr *CompletionTester) Ignore(is ...any) { + tr.ignore = append(tr.ignore, keepNonNil(is...)...) +} + +func (tr *CompletionTester) Expect(is ...any) { + tr.valid = append(tr.valid, keepNonNil(is...)...) +} + func (tr *CompletionTester) Tested(t testing.TB, m any) { t.Helper() @@ -33,6 +42,13 @@ func (tr *CompletionTester) Tested(t testing.TB, m any) { t.Fatal("no valid metadata types to test against") } ty := reflect.TypeOf(m) + + for _, v := range tr.ignore { + if reflect.TypeOf(v) == ty { + return + } + } + for _, v := range tr.valid { if reflect.TypeOf(v) == ty { tr.saw = append(tr.saw, m) @@ -67,3 +83,13 @@ validations: } } } + +func keepNonNil(is ...any) []any { + var result []any + for _, i := range is { + if i != nil { + result = append(result, i) + } + } + return result +} diff --git a/syft/internal/packagemetadata/discover_type_names.go b/internal/packagemetadata/discover_type_names.go similarity index 98% rename from syft/internal/packagemetadata/discover_type_names.go rename to internal/packagemetadata/discover_type_names.go index 647753eb038..f9783db104f 100644 --- a/syft/internal/packagemetadata/discover_type_names.go +++ b/internal/packagemetadata/discover_type_names.go @@ -24,7 +24,7 @@ var knownNonMetadataTypeNames = strset.New( // these are names that would be removed due to common convention (e.g. used within another metadata type) but are // known to be metadata types themselves. Adding to this list will prevent the removal of the type from the schema. -var knownMetadaTypeNames = strset.New( +var knownMetadataTypeNames = strset.New( "DotnetPortableExecutableEntry", ) @@ -72,7 +72,7 @@ func findMetadataDefinitionNames(paths ...string) ([]string, error) { } // any definition that is used within another struct should not be considered a top-level metadata definition - removeNames := strset.Difference(usedNames, knownMetadaTypeNames) + removeNames := strset.Difference(usedNames, knownMetadataTypeNames) names.Remove(removeNames.List()...) // remove known exceptions, that is, types exported in the pkg Package that are not used diff --git a/syft/internal/packagemetadata/discover_type_names_test.go b/internal/packagemetadata/discover_type_names_test.go similarity index 100% rename from syft/internal/packagemetadata/discover_type_names_test.go rename to internal/packagemetadata/discover_type_names_test.go diff --git a/syft/internal/packagemetadata/generate/main.go b/internal/packagemetadata/generate/main.go similarity index 91% rename from syft/internal/packagemetadata/generate/main.go rename to internal/packagemetadata/generate/main.go index e9dc1791c04..88339abff6c 100644 --- a/syft/internal/packagemetadata/generate/main.go +++ b/internal/packagemetadata/generate/main.go @@ -5,9 +5,8 @@ import ( "os" "strings" + "github.com/anchore/syft/internal/packagemetadata" "github.com/dave/jennifer/jen" - - "github.com/anchore/syft/syft/internal/packagemetadata" ) // This program is invoked from syft/internal and generates packagemetadata/generated.go @@ -31,7 +30,7 @@ func main() { fmt.Printf("updating package metadata type list with %+v types\n", len(typeNames)) f := jen.NewFile("packagemetadata") - f.HeaderComment("DO NOT EDIT: generated by syft/internal/packagemetadata/generate/main.go") + f.HeaderComment("DO NOT EDIT: generated by internal/packagemetadata/generate/main.go") f.ImportName(pkgImport, "pkg") f.Comment("AllTypes returns a list of all pkg metadata types that syft supports (that are represented in the pkg.Package.Metadata field).") diff --git a/syft/internal/packagemetadata/generated.go b/internal/packagemetadata/generated.go similarity index 91% rename from syft/internal/packagemetadata/generated.go rename to internal/packagemetadata/generated.go index e11f4c025f8..2315352dc65 100644 --- a/syft/internal/packagemetadata/generated.go +++ b/internal/packagemetadata/generated.go @@ -1,4 +1,4 @@ -// DO NOT EDIT: generated by syft/internal/packagemetadata/generate/main.go +// DO NOT EDIT: generated by internal/packagemetadata/generate/main.go package packagemetadata @@ -16,6 +16,7 @@ func AllTypes() []any { pkg.ConanV2LockEntry{}, pkg.ConanfileEntry{}, pkg.ConaninfoEntry{}, + pkg.CondaMetaPackage{}, pkg.DartPubspec{}, pkg.DartPubspecLockEntry{}, pkg.DotnetDepsEntry{}, @@ -29,6 +30,7 @@ func AllTypes() []any { pkg.GitHubActionsUseStatement{}, pkg.GolangBinaryBuildinfoEntry{}, pkg.GolangModuleEntry{}, + pkg.GolangSourceEntry{}, pkg.HackageStackYamlEntry{}, pkg.HackageStackYamlLockEntry{}, pkg.HomebrewFormula{}, @@ -52,12 +54,14 @@ func AllTypes() []any { pkg.PythonPipfileLockEntry{}, pkg.PythonPoetryLockEntry{}, pkg.PythonRequirementsEntry{}, + pkg.PythonUvLockEntry{}, pkg.RDescription{}, pkg.RpmArchive{}, pkg.RpmDBEntry{}, pkg.RubyGemspec{}, pkg.RustBinaryAuditEntry{}, pkg.RustCargoLockEntry{}, + pkg.SnapEntry{}, pkg.SwiftPackageManagerResolvedEntry{}, pkg.SwiplPackEntry{}, pkg.TerraformLockProviderEntry{}, diff --git a/syft/internal/packagemetadata/names.go b/internal/packagemetadata/names.go similarity index 96% rename from syft/internal/packagemetadata/names.go rename to internal/packagemetadata/names.go index e4e266d1c67..79eed0d4fdd 100644 --- a/syft/internal/packagemetadata/names.go +++ b/internal/packagemetadata/names.go @@ -82,6 +82,7 @@ var jsonTypes = makeJSONTypes( jsonNames(pkg.GitHubActionsUseStatement{}, "github-actions-use-statement"), jsonNames(pkg.GolangBinaryBuildinfoEntry{}, "go-module-buildinfo-entry", "GolangBinMetadata", "GolangMetadata"), jsonNames(pkg.GolangModuleEntry{}, "go-module-entry", "GolangModMetadata"), + jsonNames(pkg.GolangSourceEntry{}, "go-source-entry"), jsonNames(pkg.HackageStackYamlLockEntry{}, "haskell-hackage-stack-lock-entry", "HackageMetadataType"), jsonNamesWithoutLookup(pkg.HackageStackYamlEntry{}, "haskell-hackage-stack-entry", "HackageMetadataType"), // the legacy value is split into two types, where the other is preferred jsonNames(pkg.JavaArchive{}, "java-archive", "JavaMetadata"), @@ -104,6 +105,7 @@ var jsonTypes = makeJSONTypes( jsonNames(pkg.PythonPipfileLockEntry{}, "python-pipfile-lock-entry", "PythonPipfileLockMetadata"), jsonNames(pkg.PythonPoetryLockEntry{}, "python-poetry-lock-entry", "PythonPoetryLockMetadata"), jsonNames(pkg.PythonRequirementsEntry{}, "python-pip-requirements-entry", "PythonRequirementsMetadata"), + jsonNames(pkg.PythonUvLockEntry{}, "python-uv-lock-entry"), jsonNames(pkg.ErlangRebarLockEntry{}, "erlang-rebar-lock-entry", "RebarLockMetadataType"), jsonNames(pkg.RDescription{}, "r-description", "RDescriptionFileMetadataType"), jsonNames(pkg.RpmDBEntry{}, "rpm-db-entry", "RpmMetadata", "RpmdbMetadata"), @@ -113,11 +115,13 @@ var jsonTypes = makeJSONTypes( jsonNames(pkg.OpamPackage{}, "opam-package"), jsonNames(pkg.RustCargoLockEntry{}, "rust-cargo-lock-entry", "RustCargoPackageMetadata"), jsonNamesWithoutLookup(pkg.RustBinaryAuditEntry{}, "rust-cargo-audit-entry", "RustCargoPackageMetadata"), // the legacy value is split into two types, where the other is preferred + jsonNames(pkg.SnapEntry{}, "snap-entry"), jsonNames(pkg.WordpressPluginEntry{}, "wordpress-plugin-entry", "WordpressMetadata"), jsonNames(pkg.HomebrewFormula{}, "homebrew-formula"), jsonNames(pkg.LuaRocksPackage{}, "luarocks-package"), jsonNames(pkg.TerraformLockProviderEntry{}, "terraform-lock-provider-entry"), jsonNames(pkg.DotnetPackagesLockEntry{}, "dotnet-packages-lock-entry"), + jsonNames(pkg.CondaMetaPackage{}, "conda-metadata-entry", "CondaPackageMetadata"), ) func expandLegacyNameVariants(names ...string) []string { diff --git a/syft/internal/packagemetadata/names_test.go b/internal/packagemetadata/names_test.go similarity index 98% rename from syft/internal/packagemetadata/names_test.go rename to internal/packagemetadata/names_test.go index ee73d843740..74d43602665 100644 --- a/syft/internal/packagemetadata/names_test.go +++ b/internal/packagemetadata/names_test.go @@ -347,6 +347,12 @@ func Test_JSONName_JSONLegacyName(t *testing.T) { expectedJSONName: "go-module-entry", expectedLegacyName: "GolangModMetadata", }, + { + name: "GolangSourceMetadata", + metadata: pkg.GolangSourceEntry{}, + expectedJSONName: "go-source-entry", + expectedLegacyName: "go-source-entry", + }, { name: "HackageStackYamlLockMetadata", metadata: pkg.HackageStackYamlLockEntry{}, diff --git a/internal/regex_helpers.go b/internal/regex_helpers.go index 78a024c4ba4..dce1d349616 100644 --- a/internal/regex_helpers.go +++ b/internal/regex_helpers.go @@ -41,11 +41,11 @@ func MatchNamedCaptureGroups(regEx *regexp.Regexp, content string) map[string]st // 1.5x the reader chunk size (1MB * 1.5). func MatchNamedCaptureGroupsFromReader(re *regexp.Regexp, r io.Reader) (map[string]string, error) { results := make(map[string]string) - _, err := processReaderInChunks(r, readerChunkSize, matchNamedCaptureGroupsHandler(re, results)) + matches, err := processReaderInChunks(r, readerChunkSize, matchNamedCaptureGroupsHandler(re, results)) if err != nil { return nil, err } - if len(results) == 0 { + if !matches { return nil, nil } return results, nil diff --git a/syft/internal/sourcemetadata/completion_tester.go b/internal/sourcemetadata/completion_tester.go similarity index 73% rename from syft/internal/sourcemetadata/completion_tester.go rename to internal/sourcemetadata/completion_tester.go index 8dc9ce0c444..0e6bbea1a5b 100644 --- a/syft/internal/sourcemetadata/completion_tester.go +++ b/internal/sourcemetadata/completion_tester.go @@ -12,6 +12,7 @@ type CompletionTester struct { } func NewCompletionTester(t testing.TB, ignore ...any) *CompletionTester { + t.Helper() tester := &CompletionTester{ valid: AllTypes(), ignore: ignore, @@ -23,6 +24,14 @@ func NewCompletionTester(t testing.TB, ignore ...any) *CompletionTester { return tester } +func (tr *CompletionTester) Ignore(is ...any) { + tr.ignore = append(tr.ignore, keepNonNil(is...)...) +} + +func (tr *CompletionTester) Expect(is ...any) { + tr.valid = append(tr.valid, keepNonNil(is...)...) +} + func (tr *CompletionTester) Tested(t testing.TB, m any) { t.Helper() @@ -33,6 +42,13 @@ func (tr *CompletionTester) Tested(t testing.TB, m any) { t.Fatal("no valid metadata types to test against") } ty := reflect.TypeOf(m) + + for _, v := range tr.ignore { + if reflect.TypeOf(v) == ty { + return + } + } + for _, v := range tr.valid { if reflect.TypeOf(v) == ty { tr.saw = append(tr.saw, m) @@ -67,3 +83,13 @@ validations: } } } + +func keepNonNil(is ...any) []any { + var result []any + for _, i := range is { + if i != nil { + result = append(result, i) + } + } + return result +} diff --git a/syft/internal/sourcemetadata/discover_type_names.go b/internal/sourcemetadata/discover_type_names.go similarity index 100% rename from syft/internal/sourcemetadata/discover_type_names.go rename to internal/sourcemetadata/discover_type_names.go diff --git a/syft/internal/sourcemetadata/generate/main.go b/internal/sourcemetadata/generate/main.go similarity index 90% rename from syft/internal/sourcemetadata/generate/main.go rename to internal/sourcemetadata/generate/main.go index ea40960a073..a56bfc832d8 100644 --- a/syft/internal/sourcemetadata/generate/main.go +++ b/internal/sourcemetadata/generate/main.go @@ -4,9 +4,8 @@ import ( "fmt" "os" + "github.com/anchore/syft/internal/sourcemetadata" "github.com/dave/jennifer/jen" - - "github.com/anchore/syft/syft/internal/sourcemetadata" ) // This program is invoked from syft/internal and generates sourcemetadata/generated.go @@ -25,7 +24,7 @@ func main() { fmt.Printf("updating source metadata type list with %+v types\n", len(typeNames)) f := jen.NewFile("sourcemetadata") - f.HeaderComment("DO NOT EDIT: generated by syft/internal/sourcemetadata/generate/main.go") + f.HeaderComment("DO NOT EDIT: generated by internal/sourcemetadata/generate/main.go") f.ImportName(srcImport, "source") f.Comment("AllTypes returns a list of all source metadata types that syft supports (that are represented in the source.Description.Metadata field).") diff --git a/syft/internal/sourcemetadata/generated.go b/internal/sourcemetadata/generated.go similarity index 82% rename from syft/internal/sourcemetadata/generated.go rename to internal/sourcemetadata/generated.go index ffcd9c88202..2cfbb6e87e7 100644 --- a/syft/internal/sourcemetadata/generated.go +++ b/internal/sourcemetadata/generated.go @@ -1,4 +1,4 @@ -// DO NOT EDIT: generated by syft/internal/sourcemetadata/generate/main.go +// DO NOT EDIT: generated by internal/sourcemetadata/generate/main.go package sourcemetadata diff --git a/syft/internal/sourcemetadata/names.go b/internal/sourcemetadata/names.go similarity index 100% rename from syft/internal/sourcemetadata/names.go rename to internal/sourcemetadata/names.go diff --git a/syft/internal/sourcemetadata/names_test.go b/internal/sourcemetadata/names_test.go similarity index 100% rename from syft/internal/sourcemetadata/names_test.go rename to internal/sourcemetadata/names_test.go diff --git a/internal/spdxlicense/generate/generate_license_list.go b/internal/spdxlicense/generate/generate_license_list.go index 5c5bf26b760..642df106657 100644 --- a/internal/spdxlicense/generate/generate_license_list.go +++ b/internal/spdxlicense/generate/generate_license_list.go @@ -31,6 +31,13 @@ var licenseIDs = map[string]string{ {{ printf "%q" $k }}: {{ printf "%q" $v }}, {{- end }} } + +// urlToLicense maps license URLs from the seeAlso field to license IDs +var urlToLicense = map[string]string{ +{{- range $url, $id := .URLToLicense }} + {{ printf "%q" $url }}: {{ printf "%q" $id }}, +{{- end }} +} `)) var versionMatch = regexp.MustCompile(`([0-9]+)\.?([0-9]+)?\.?([0-9]+)?\.?`) @@ -68,17 +75,20 @@ func run() error { }() licenseIDs := processSPDXLicense(result) + urlToLicense := buildURLToLicenseMap(result) err = tmp.Execute(f, struct { - Timestamp time.Time - URL string - Version string - LicenseIDs map[string]string + Timestamp time.Time + URL string + Version string + LicenseIDs map[string]string + URLToLicense map[string]string }{ - Timestamp: time.Now(), - URL: url, - Version: result.Version, - LicenseIDs: licenseIDs, + Timestamp: time.Now(), + URL: url, + Version: result.Version, + LicenseIDs: licenseIDs, + URLToLicense: urlToLicense, }) if err != nil { @@ -156,3 +166,30 @@ func cleanLicenseID(id string) string { cleanID := strings.ToLower(id) return strings.ReplaceAll(cleanID, "-", "") } + +// buildURLToLicenseMap creates a mapping from license URLs (from seeAlso fields) to license IDs +func buildURLToLicenseMap(result LicenseList) map[string]string { + urlMap := make(map[string]string) + + for _, l := range result.Licenses { + // Skip deprecated licenses + if l.Deprecated { + // Find replacement license if available + replacement := result.findReplacementLicense(l) + if replacement != nil { + // Map deprecated license URLs to the replacement license + for _, url := range l.SeeAlso { + urlMap[url] = replacement.ID + } + } + continue + } + + // Add URLs from non-deprecated licenses + for _, url := range l.SeeAlso { + urlMap[url] = l.ID + } + } + + return urlMap +} diff --git a/internal/spdxlicense/license.go b/internal/spdxlicense/license.go index d57f9ebe5e8..3678da8457f 100644 --- a/internal/spdxlicense/license.go +++ b/internal/spdxlicense/license.go @@ -35,3 +35,20 @@ func cleanLicenseID(id string) string { id = strings.ToLower(id) return strings.ReplaceAll(id, "-", "") } + +// LicenseInfo contains license ID and name +type LicenseInfo struct { + ID string +} + +// LicenseByURL returns the license ID and name for a given URL from the SPDX license list +// The URL should match one of the URLs in the seeAlso field of an SPDX license +func LicenseByURL(url string) (LicenseInfo, bool) { + url = strings.TrimSpace(url) + if id, exists := urlToLicense[url]; exists { + return LicenseInfo{ + ID: id, + }, true + } + return LicenseInfo{}, false +} diff --git a/internal/spdxlicense/license_list.go b/internal/spdxlicense/license_list.go index 5bd4100e6ec..0eba01eee61 100644 --- a/internal/spdxlicense/license_list.go +++ b/internal/spdxlicense/license_list.go @@ -1,9 +1,9 @@ // Code generated by go generate; DO NOT EDIT. -// This file was generated by robots at 2024-11-29 09:22:05.594787 +0100 CET m=+2.414400043 +// This file was generated by robots at 2025-08-12 14:01:18.565303 -0400 EDT m=+0.306214043 // using data from https://spdx.org/licenses/licenses.json package spdxlicense -const Version = "3.25.0" +const Version = "3.27.0" var licenseIDs = map[string]string{ "0bsd": "0BSD", @@ -67,6 +67,7 @@ var licenseIDs = map[string]string{ "antlrpd": "ANTLR-PD", "antlrpdfallback": "ANTLR-PD-fallback", "anyosi": "any-OSI", + "anyosiperlmodules": "any-OSI-perl-modules", "apache1": "Apache-1.0", "apache1.0": "Apache-1.0", "apache1.0.0": "Apache-1.0", @@ -107,6 +108,7 @@ var licenseIDs = map[string]string{ "artistic2": "Artistic-2.0", "artistic2.0": "Artistic-2.0", "artistic2.0.0": "Artistic-2.0", + "aspellru": "Aspell-RU", "aswfdigitalassets1": "ASWF-Digital-Assets-1.0", "aswfdigitalassets1.0": "ASWF-Digital-Assets-1.0", "aswfdigitalassets1.0.0": "ASWF-Digital-Assets-1.0", @@ -129,6 +131,7 @@ var licenseIDs = map[string]string{ "blueoak1.0": "BlueOak-1.0.0", "blueoak1.0.0": "BlueOak-1.0.0", "boehmgc": "Boehm-GC", + "boehmgcwithoutfee": "Boehm-GC-without-fee", "borceux": "Borceux", "briangladman2.0.0clause": "Brian-Gladman-2-Clause", "briangladman2.0clause": "Brian-Gladman-2-Clause", @@ -145,6 +148,7 @@ var licenseIDs = map[string]string{ "bsd2.0.0clausefreebsd": "BSD-2-Clause-Views", "bsd2.0.0clausenetbsd": "BSD-2-Clause", "bsd2.0.0clausepatent": "BSD-2-Clause-Patent", + "bsd2.0.0clausepkgconfdisclaimer": "BSD-2-Clause-pkgconf-disclaimer", "bsd2.0.0clauseviews": "BSD-2-Clause-Views", "bsd2.0clause": "BSD-2-Clause", "bsd2.0clausedarwin": "BSD-2-Clause-Darwin", @@ -152,6 +156,7 @@ var licenseIDs = map[string]string{ "bsd2.0clausefreebsd": "BSD-2-Clause-Views", "bsd2.0clausenetbsd": "BSD-2-Clause", "bsd2.0clausepatent": "BSD-2-Clause-Patent", + "bsd2.0clausepkgconfdisclaimer": "BSD-2-Clause-pkgconf-disclaimer", "bsd2.0clauseviews": "BSD-2-Clause-Views", "bsd2clause": "BSD-2-Clause", "bsd2clausedarwin": "BSD-2-Clause-Darwin", @@ -159,6 +164,7 @@ var licenseIDs = map[string]string{ "bsd2clausefreebsd": "BSD-2-Clause-Views", "bsd2clausenetbsd": "BSD-2-Clause", "bsd2clausepatent": "BSD-2-Clause-Patent", + "bsd2clausepkgconfdisclaimer": "BSD-2-Clause-pkgconf-disclaimer", "bsd2clauseviews": "BSD-2-Clause-Views", "bsd3.0.0clause": "BSD-3-Clause", "bsd3.0.0clauseacpica": "BSD-3-Clause-acpica", @@ -400,6 +406,12 @@ var licenseIDs = map[string]string{ "ccbysa4.0": "CC-BY-SA-4.0", "ccbysa4.0.0": "CC-BY-SA-4.0", "ccpddc": "CC-PDDC", + "ccpdm1": "CC-PDM-1.0", + "ccpdm1.0": "CC-PDM-1.0", + "ccpdm1.0.0": "CC-PDM-1.0", + "ccsa1": "CC-SA-1.0", + "ccsa1.0": "CC-SA-1.0", + "ccsa1.0.0": "CC-SA-1.0", "cddl1": "CDDL-1.0", "cddl1.0": "CDDL-1.0", "cddl1.0.0": "CDDL-1.0", @@ -477,6 +489,7 @@ var licenseIDs = map[string]string{ "cpol1.02.0": "CPOL-1.02", "cronyx": "Cronyx", "crossword": "Crossword", + "cryptoswift": "CryptoSwift", "crystalstacker": "CrystalStacker", "cuaopl1": "CUA-OPL-1.0", "cuaopl1.0": "CUA-OPL-1.0", @@ -501,7 +514,9 @@ var licenseIDs = map[string]string{ "dldezero2.0": "DL-DE-ZERO-2.0", "dldezero2.0.0": "DL-DE-ZERO-2.0", "doc": "DOC", + "docbookdtd": "DocBook-DTD", "docbookschema": "DocBook-Schema", + "docbookstylesheet": "DocBook-Stylesheet", "docbookxml": "DocBook-XML", "dotseqn": "Dotseqn", "drl1": "DRL-1.0", @@ -567,12 +582,21 @@ var licenseIDs = map[string]string{ "fsfapnowarrantydisclaimer": "FSFAP-no-warranty-disclaimer", "fsful": "FSFUL", "fsfullr": "FSFULLR", + "fsfullrsd": "FSFULLRSD", "fsfullrwd": "FSFULLRWD", + "fsl1.1.0alv2": "FSL-1.1-ALv2", + "fsl1.1.0mit": "FSL-1.1-MIT", + "fsl1.1alv2": "FSL-1.1-ALv2", + "fsl1.1mit": "FSL-1.1-MIT", + "fsl1alv2": "FSL-1.1-ALv2", + "fsl1mit": "FSL-1.1-MIT", "ftl": "FTL", "furuseth": "Furuseth", "fwlw": "fwlw", + "gameprogramminggems": "Game-Programming-Gems", "gcrdocs": "GCR-docs", "gd": "GD", + "genericxts": "generic-xts", "gfdl1": "GFDL-1.1-only", "gfdl1+": "GFDL-1.1-or-later", "gfdl1+invariants": "GFDL-1.1-invariants-or-later", @@ -715,6 +739,9 @@ var licenseIDs = map[string]string{ "gtkbook": "gtkbook", "gutmann": "Gutmann", "haskellreport": "HaskellReport", + "hdf5": "HDF5", + "hdf5.0": "HDF5", + "hdf5.0.0": "HDF5", "hdparm": "hdparm", "hidapi": "HIDAPI", "hippocratic2": "Hippocratic-2.1", @@ -767,6 +794,7 @@ var licenseIDs = map[string]string{ "innernet2": "Inner-Net-2.0", "innernet2.0": "Inner-Net-2.0", "innernet2.0.0": "Inner-Net-2.0", + "innosetup": "InnoSetup", "intel": "Intel", "intelacpi": "Intel-ACPI", "interbase1": "Interbase-1.0", @@ -782,6 +810,7 @@ var licenseIDs = map[string]string{ "jasper2": "JasPer-2.0", "jasper2.0": "JasPer-2.0", "jasper2.0.0": "JasPer-2.0", + "jove": "jove", "jplimage": "JPL-image", "jpnic": "JPNIC", "json": "JSON", @@ -834,6 +863,9 @@ var licenseIDs = map[string]string{ "lgpl3orlater": "LGPL-3.0-or-later", "lgpllr": "LGPLLR", "libpng": "Libpng", + "libpng1": "libpng-1.6.35", + "libpng1.6": "libpng-1.6.35", + "libpng1.6.35": "libpng-1.6.35", "libpng2": "libpng-2.0", "libpng2.0": "libpng-2.0", "libpng2.0.0": "libpng-2.0", @@ -897,14 +929,19 @@ var licenseIDs = map[string]string{ "magaz": "magaz", "mailprio": "mailprio", "makeindex": "MakeIndex", + "man2.0.0html": "man2html", + "man2.0html": "man2html", + "man2html": "man2html", "martinbirgmeier": "Martin-Birgmeier", "mcpheeslideshow": "McPhee-slideshow", "metamail": "metamail", "minpack": "Minpack", + "mips": "MIPS", "miros": "MirOS", "mit": "MIT", "mit0": "MIT-0", "mitadvertising": "MIT-advertising", + "mitclick": "MIT-Click", "mitcmu": "MIT-CMU", "mitenna": "MIT-enna", "mitfeh": "MIT-feh", @@ -966,6 +1003,7 @@ var licenseIDs = map[string]string{ "netsnmp": "Net-SNMP", "newsletr": "Newsletr", "ngpl": "NGPL", + "ngrep": "ngrep", "nicta1": "NICTA-1.0", "nicta1.0": "NICTA-1.0", "nicta1.0.0": "NICTA-1.0", @@ -991,6 +1029,7 @@ var licenseIDs = map[string]string{ "nposl3.0": "NPOSL-3.0", "nposl3.0.0": "NPOSL-3.0", "nrl": "NRL", + "ntiapd": "NTIA-PD", "ntp": "NTP", "ntp0": "NTP-0", "nunit": "Nunit", @@ -1181,6 +1220,9 @@ var licenseIDs = map[string]string{ "sendmail8": "Sendmail-8.23", "sendmail8.23": "Sendmail-8.23", "sendmail8.23.0": "Sendmail-8.23", + "sendmailopensource1": "Sendmail-Open-Source-1.1", + "sendmailopensource1.1": "Sendmail-Open-Source-1.1", + "sendmailopensource1.1.0": "Sendmail-Open-Source-1.1", "sgib1": "SGI-B-1.0", "sgib1.0": "SGI-B-1.0", "sgib1.0.0": "SGI-B-1.0", @@ -1206,10 +1248,12 @@ var licenseIDs = map[string]string{ "sissl1.2.0": "SISSL-1.2", "sl": "SL", "sleepycat": "Sleepycat", + "smailgpl": "SMAIL-GPL", "smlnj": "SMLNJ", "smppl": "SMPPL", "snia": "SNIA", "snprintf": "snprintf", + "sofa": "SOFA", "softsurfer": "softSurfer", "soundex": "Soundex", "spencer86": "Spencer-86", @@ -1235,6 +1279,9 @@ var licenseIDs = map[string]string{ "sugarcrm1": "SugarCRM-1.1.3", "sugarcrm1.1": "SugarCRM-1.1.3", "sugarcrm1.1.3": "SugarCRM-1.1.3", + "sul1": "SUL-1.0", + "sul1.0": "SUL-1.0", + "sul1.0.0": "SUL-1.0", "sunppp": "Sun-PPP", "sunppp2000": "Sun-PPP-2000", "sunppp2000.0": "Sun-PPP-2000", @@ -1252,6 +1299,7 @@ var licenseIDs = map[string]string{ "tgppl1": "TGPPL-1.0", "tgppl1.0": "TGPPL-1.0", "tgppl1.0.0": "TGPPL-1.0", + "thirdeye": "ThirdEye", "threeparttable": "threeparttable", "tmate": "TMate", "torque1": "TORQUE-1.1", @@ -1262,6 +1310,7 @@ var licenseIDs = map[string]string{ "tpl1": "TPL-1.0", "tpl1.0": "TPL-1.0", "tpl1.0.0": "TPL-1.0", + "trustedqsl": "TrustedQSL", "ttwl": "TTWL", "ttyp0": "TTYP0", "tuberlin1": "TU-Berlin-1.0", @@ -1291,6 +1340,8 @@ var licenseIDs = map[string]string{ "unicodetou": "Unicode-TOU", "unixcrypt": "UnixCrypt", "unlicense": "Unlicense", + "unlicenselibtelnet": "Unlicense-libtelnet", + "unlicenselibwhirlpool": "Unlicense-libwhirlpool", "upl1": "UPL-1.0", "upl1.0": "UPL-1.0", "upl1.0.0": "UPL-1.0", @@ -1318,6 +1369,7 @@ var licenseIDs = map[string]string{ "widgetworkshop": "Widget-Workshop", "wsuipa": "Wsuipa", "wtfpl": "WTFPL", + "wwl": "wwl", "wxwindows": "wxWindows", "x11": "X11", "x11.0": "X11", @@ -1369,3 +1421,836 @@ var licenseIDs = map[string]string{ "zpl2.1": "ZPL-2.1", "zpl2.1.0": "ZPL-2.1", } + +// urlToLicense maps license URLs from the seeAlso field to license IDs +var urlToLicense = map[string]string{ + "ftp://ftp.tin.org/pub/news/utils/newsx/newsx-1.6.tar.gz": "Zeeff", + "http://apache.org/licenses/LICENSE-1.1": "Apache-1.1", + "http://artlibre.org/licence/lal/licence-art-libre-12/": "LAL-1.2", + "http://bits.netizen.com.au/licenses/NOSL/nosl.txt": "NOSL", + "http://bzip.org/1.0.5/bzip2-manual-1.0.5.html": "bzip2-1.0.6", + "http://cryptographicautonomylicense.com/license-text.html": "CAL-1.0-Combined-Work-Exception", + "http://cvs.savannah.gnu.org/viewvc/cvs/ccvs/contrib/check_cvs.in?revision=1.1.4.3&view=markup&pathrev=cvs1-11-23#l2": "check-cvs", + "http://data.norge.no/nlod/en/1.0": "NLOD-1.0", + "http://data.norge.no/nlod/en/2.0": "NLOD-2.0", + "http://dev.perl.org/licenses/artistic.html": "Artistic-1.0-Perl", + "http://dev.w3.org/cvsweb/Amaya/libjpeg/Attic/README?rev=1.2": "IJG", + "http://directory.fsf.org/wiki/License:BSD_4Clause": "BSD-4-Clause", + "http://directory.fsf.org/wiki/License:BitTorrentOSL1.1": "BitTorrent-1.1", + "http://doc.qt.nokia.com/3.3/license.html": "QPL-1.0", + "http://download.oracle.com/otn-pub/java/licenses/bsd.txt": "BSD-3-Clause-No-Nuclear-License", + "http://ec.europa.eu/idabc/en/document/7330.html": "EUPL-1.0", + "http://ec.europa.eu/idabc/servlets/Doc027f.pdf?id=31096": "EUPL-1.0", + "http://ecos.sourceware.org/old-license.html": "RHeCos-1.1", + "http://eu-datagrid.web.cern.ch/eu-datagrid/license.html": "EUDatagrid", + "http://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32017D0863": "EUPL-1.2", + "http://freeimage.sourceforge.net/freeimage-license.txt": "FreeImage", + "http://freetype.fis.uniroma2.it/FTL.TXT": "FTL", + "http://ftp.gnu.org/gnu/non-gnu/chinese-fonts-truetype/LICENSE": "Arphic-1999", + "http://gianluca.dellavedova.org/2011/01/03/clarified-artistic-license/": "ClArtistic", + "http://git.denx.de/?p=u-boot.git;a=blob;f=arch/powerpc/cpu/ppc4xx/miiphy.c;h=297155fdafa064b955e53e9832de93bfb0cfb85b;hb=9fab4bf4cc077c21e43941866f3f2c196f28670d": "IBM-pibs", + "http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT": "FTL", + "http://git.savannah.gnu.org/cgit/gcl.git/tree/gcl/lsp/gcl_loop.lsp?h=Version_2_6_13pre": "LOOP", + "http://git.savannah.gnu.org/cgit/kazlib.git/tree/except.c?id=0062df360c2d17d57f6af19b0e444c51feb99036": "Kazlib", + "http://gitlab.freedesktop.org/freetype/freetype/-/raw/master/docs/FTL.TXT": "FTL", + "http://glassfish.java.net/public/CDDL+GPL_1_1.html": "CDDL-1.1", + "http://gridscheduler.sourceforge.net/Gridengine_SISSL_license.html": "SISSL-1.2", + "http://labs.metacarta.com/license-explanation.html#license": "BSD-3-Clause-Clear", + "http://landley.net/toybox/license.html": "0BSD", + "http://legacy.imatix.com/html/sfl/sfl4.htm#license": "iMatix", + "http://liballeg.org/license.html#allegro-4-the-giftware-license": "Giftware", + "http://lists.opensource.org/pipermail/license-discuss_lists.opensource.org/2002-November/006304.html": "HPND", + "http://old.koalateam.com/jackaroo/OPL_1_0.TXT": "OPL-1.0", + "http://old.zope.org/Resources/License/ZPL-1.1": "ZPL-1.1", + "http://old.zope.org/Resources/License/ZPL-2.0": "ZPL-2.0", + "http://old.zope.org/Resources/ZPL/": "ZPL-2.1", + "http://opencontent.org/openpub/": "OPUBL-1.0", + "http://opendatacommons.org/licenses/pddl/1.0/": "PDDL-1.0", + "http://opensource.linux-mirror.org/licenses/afl-1.1.txt": "AFL-1.1", + "http://opensource.linux-mirror.org/licenses/afl-1.2.txt": "AFL-1.2", + "http://opensource.linux-mirror.org/licenses/afl-2.1.txt": "AFL-2.1", + "http://opensource.org/licenses/LiLiQ-P-1.1": "LiLiQ-P-1.1", + "http://opensource.org/licenses/LiLiQ-R-1.1": "LiLiQ-R-1.1", + "http://opensource.org/licenses/LiLiQ-Rplus-1.1": "LiLiQ-Rplus-1.1", + "http://opensource.org/licenses/MIT": "MIT", + "http://oss.sgi.com/projects/FreeB/": "SGI-B-1.1", + "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.1.0.html": "SGI-B-1.0", + "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.2.0.pdf": "SGI-B-2.0", + "http://otm.illinois.edu/uiuc_openSource": "NCSA", + "http://pages.cs.wisc.edu/~ghost/doc/AFPL/6.01/Public.htm": "Aladdin", + "http://plan9.bell-labs.com/plan9/license.html": "LPL-1.02", + "http://primates.ximian.com/~flucifredi/man/man-1.6g.tar.gz": "man2html", + "http://rc.quest.com/topics/openssh/license.php#tcpwrappers": "TCP-wrappers", + "http://research.cs.wisc.edu/condor/license.html#condor": "Condor-1.1", + "http://research.scea.com/scea_shared_source_license.html": "SCEA", + "http://sam.zoy.org/wtfpl/COPYING": "WTFPL", + "http://scripts.sil.org/cms/scripts/page.php?item_id=OFL10_web": "OFL-1.0-no-RFN", + "http://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web": "OFL-1.1-no-RFN", + "http://source.icu-project.org/repos/icu/icu/trunk/license.html": "ICU", + "http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/licenses/BitTorrent?r1=1.1&r2=1.1.1.1&diff_format=s": "BitTorrent-1.0", + "http://svnkit.com/license.html": "TMate", + "http://ti.arc.nasa.gov/opensource/nosa/": "NASA-1.3", + "http://trac.enlightenment.org/e/browser/trunk/imlib2/COPYING": "Imlib2", + "http://vimdoc.sourceforge.net/htmldoc/uganda.html": "Vim", + "http://wayback.archive.org/web/20021004124254/http://www.opensource.org/licenses/academic.php": "AFL-1.1", + "http://wayback.archive.org/web/20021204204652/http://www.opensource.org/licenses/academic.php": "AFL-1.2", + "http://wayback.archive.org/web/20060715140826/http://www.risource.org/RPL/RPL-1.0A.shtml": "RSCPL", + "http://wayback.archive.org/web/20060924134533/http://www.opensource.org/licenses/afl-2.0.txt": "AFL-2.0", + "http://web.archive.org/web/20041020171434/http://www.rosenlaw.com/osl2.0.html": "OSL-2.0", + "http://web.archive.org/web/20050212003940/http://www.rosenlaw.com/osl21.htm": "OSL-2.1", + "http://web.archive.org/web/20100302225219/http://www.zimbra.com/license/zimbra-public-license-1-3.html": "Zimbra-1.3", + "http://web.archive.org/web/20111123062036/http://research.cs.wisc.edu/condor/license.html#condor": "Condor-1.1", + "http://web.archive.org/web/20140704074106/http://www.unicode.org/copyright.html": "Unicode-TOU", + "http://web.archive.org/web/20160823201924/http://www.unicode.org/copyright.html#License": "Unicode-DFS-2016", + "http://web.mit.edu/freebsd/head/lib/libutil/login_ok.3": "libutil-David-Nugent", + "http://web.mit.edu/kolya/.f/root/athena.mit.edu/sipb.mit.edu/project/openssh/OldFiles/src/openssh-2.9.9p2/ssh-add.1": "SSH-short", + "http://web.mit.edu/network/isakmp/nrllicense.html": "NRL", + "http://www-igm.univ-mlv.fr/~unitex/lgpllr.html": "LGPLLR", + "http://www.affero.org/oagpl.html": "AGPL-1.0-or-later", + "http://www.antlr2.org/license.html": "ANTLR-PD-fallback", + "http://www.apache.org/licenses/LICENSE-1.0": "Apache-1.0", + "http://www.boost.org/LICENSE_1_0.txt": "BSL-1.0", + "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html": "CECILL-B", + "http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html": "CECILL-C", + "http://www.cecill.info/licences/Licence_CeCILL_V1-fr.html": "CECILL-1.0", + "http://www.cecill.info/licences/Licence_CeCILL_V1.1-US.html": "CECILL-1.1", + "http://www.cecill.info/licences/Licence_CeCILL_V2-en.html": "CECILL-2.0", + "http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.html": "CECILL-2.1", + "http://www.codeproject.com/info/cpol10.aspx": "CPOL-1.02", + "http://www.cs.fsu.edu/~engelen/license.html": "gSOAP-1.3b", + "http://www.cs.wustl.edu/~schmidt/ACE-copying.html": "DOC", + "http://www.db.net/downloads/wwl+db-1.3.tgz": "wwl", + "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/de/D-FSL-1_0_de.txt": "D-FSL-1.0", + "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/en/D-FSL-1_0_en.txt": "D-FSL-1.0", + "http://www.dipp.nrw.de/d-fsl/lizenzen/": "D-FSL-1.0", + "http://www.docbook.org/xml/5.0/docbook-5.0.zip": "DocBook-Stylesheet", + "http://www.docbook.org/xml/simple/1.1/docbook-simple-1.1.zip": "DocBook-DTD", + "http://www.ece.uvic.ca/~mdadams/jasper/LICENSE": "JasPer-2.0", + "http://www.eclipse.org/legal/epl-v10.html": "EPL-1.0", + "http://www.egenix.com/products/eGenix.com-Public-License-1.1.0.pdf": "eGenix", + "http://www.eiffel-nice.org/license/eiffel-forum-license-2.html": "EFL-2.0", + "http://www.eiffel-nice.org/license/forum.txt": "EFL-1.0", + "http://www.erlang.org/EPLICENSE": "ErlPL-1.1", + "http://www.faqs.org/rfcs/rfc1321.html": "RSA-MD", + "http://www.freebsd.org/copyright/freebsd-license.html": "BSD-2-Clause-Views", + "http://www.freebsd.org/copyright/license.html": "BSD-4-Clause-UC", + "http://www.geuz.org/gl2ps/COPYING.GL2PS": "GL2PS", + "http://www.iausofa.org/tandc.html": "SOFA", + "http://www.imagemagick.org/script/license.php": "ImageMagick", + "http://www.info-zip.org/license.html": "Info-ZIP", + "http://www.json.org/license.html": "JSON", + "http://www.jython.org/license.html": "CNRI-Jython", + "http://www.latex-project.org/lppl/lppl-1-0.txt": "LPPL-1.0", + "http://www.latex-project.org/lppl/lppl-1-1.txt": "LPPL-1.1", + "http://www.latex-project.org/lppl/lppl-1-2.txt": "LPPL-1.2", + "http://www.latex-project.org/lppl/lppl-1-3a.txt": "LPPL-1.3a", + "http://www.latex-project.org/lppl/lppl-1-3c.txt": "LPPL-1.3c", + "http://www.lemis.com/grog/UNIX/ancient-source-all.pdf": "Caldera", + "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt": "libpng-2.0", + "http://www.microsoft.com/opensource/licenses.mspx": "MS-RL", + "http://www.mozilla.org/MPL/MPL-1.0.html": "MPL-1.0", + "http://www.mozilla.org/MPL/MPL-1.1.html": "MPL-1.1", + "http://www.mozilla.org/MPL/NPL/1.0/": "NPL-1.0", + "http://www.mozilla.org/MPL/NPL/1.1/": "NPL-1.1", + "http://www.nationalarchives.gov.uk/doc/non-commercial-government-licence/version/2/": "NCGL-UK-2.0", + "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/1/": "OGL-UK-1.0", + "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/2/": "OGL-UK-2.0", + "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/": "OGL-UK-3.0", + "http://www.ncftp.com/ncftp/doc/LICENSE.txt": "ClArtistic", + "http://www.netbsd.org/about/redistribution.html#default": "BSD-2-Clause", + "http://www.netlib.org/lapack/LICENSE.txt": "BSD-3-Clause-Open-MPI", + "http://www.netlib.org/minpack/disclaimer": "Minpack", + "http://www.networkcultures.org/_uploads/%233notebook_telekommunist.pdf": "PPL", + "http://www.oclc.org/research/activities/software/license/v2final.htm": "OCLC-2.0", + "http://www.opencascade.com/content/occt-public-license": "OCCT-PL", + "http://www.opendatacommons.org/licenses/odbl/1.0/": "ODbL-1.0", + "http://www.opengroup.org/testing/downloads/The_Open_Group_TSL.txt": "OGTSL", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=1cae062821881f41b73012ba816434897abf4205": "OLDAP-2.6", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=37b4b3f6cc4bf34e1d3dec61e69914b9819d8894": "NBPL-1.0", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=42b0383c50c299977b5893ee695cf4e486fb0dc7": "OLDAP-1.2", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=470b0c18ec67621c85881b2733057fecf4a1acc3": "OLDAP-2.2", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=47c2415c1df81556eeb39be6cad458ef87c534a2": "OLDAP-2.7", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=4bc786f34b50aa301be6f5600f58a980070f481e": "OLDAP-2.2.1", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=6852b9d90022e8593c98205413380536b1b5a7cf": "OLDAP-2.5", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=806557a5ad59804ef3a44d5abfbe91d706b0791f": "OLDAP-1.1", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=b0d176738e96a0d3b9f85cb51e140a86f21be715": "OLDAP-2.1", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=b6d68acd14e51ca3aab4428bf26522aa74873f0e": "OLDAP-2.0.1", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=c9f95c2f3f2ffb5e0ae55fe7388af75547660941": "OLDAP-1.4", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=cbf50f4e1185a21abd4c0a54d3f4341fe28f36ea": "OLDAP-2.0", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=cd1284c4a91a8a380d904eee68d1583f989ed386": "OLDAP-2.4", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=d32cf54a32d581ab475d23c810b0a7fbaf8d63c3": "OLDAP-2.3", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=df2cc1e21eb7c160695f5b7cffd6296c151ba188": "OLDAP-2.2.2", + "http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=LICENSE;hb=e5f8117f0ce088d0bd7a8e18ddf37eaa40eb09b1": "OLDAP-1.3", + "http://www.openldap.org/software/release/license.html": "OLDAP-2.8", + "http://www.openoffice.org/licenses/sissl_license.html": "SISSL", + "http://www.opensource.apple.com/cdl/": "CDL-1.0", + "http://www.opensource.apple.com/license/apsl/": "APSL-2.0", + "http://www.opensource.apple.com/source/IOSerialFamily/IOSerialFamily-7/APPLE_LICENSE": "APSL-1.1", + "http://www.opensource.apple.com/source/tcl/tcl-5/tcl/generic/regfronts.c": "Spencer-99", + "http://www.openssl.org/source/license.html": "OpenSSL", + "http://www.osetfoundation.org/public-license": "OSET-PL-2.1", + "http://www.perlfoundation.org/artistic_license_2_0": "Artistic-2.0", + "http://www.php.net/license/3_0.txt": "PHP-3.0", + "http://www.php.net/license/3_01.txt": "PHP-3.01", + "http://www.postgresql.org/about/licence": "PostgreSQL", + "http://www.python.org/download/releases/1.6.1/download_win/": "CNRI-Python-GPL-Compatible", + "http://www.rosenlaw.com/AFL3.0.htm": "AFL-3.0", + "http://www.samurajdata.se/opensource/mirror/licenses/apsl.php": "APSL-1.2", + "http://www.saxproject.org/copying.html": "SAX-PD-2.0", + "http://www.sendmail.com/pdfs/open_source/sendmail_license.pdf": "Sendmail", + "http://www.sugarcrm.com/crm/SPL": "SugarCRM-1.1.3", + "http://www.tcl.tk/software/tcltk/license.html": "TCL", + "http://www.unicode.org/copyright.html": "Unicode-TOU", + "http://www.unidata.ucar.edu/software/netcdf/copyright.html": "NetCDF", + "http://www.users.on.net/~triforce/glidexp/COPYING.txt": "Glide", + "http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html": "W3C", + "http://www.w3.org/Consortium/Legal/copyright-software-19980720.html": "W3C-19980720", + "http://www.wtfpl.net/about/": "WTFPL", + "http://www.xfree86.org/3.3.6/COPYRIGHT2.html#3": "X11", + "http://www.xfree86.org/current/LICENSE4.html": "XFree86-1.1", + "http://www.zimbra.com/legal/zimbra-public-license-1-4": "Zimbra-1.4", + "http://www.zimbra.com/license/yahoo_public_license_1.0.html": "YPL-1.0", + "http://www.zimbra.com/license/yahoo_public_license_1.1.html": "YPL-1.1", + "http://www.zlib.net/zlib_license.html": "Zlib", + "https://android.googlesource.com/platform/external/dng_sdk/+/refs/heads/master/source/dng_lossless_jpeg.cpp#16": "Cornell-Lossless-JPEG", + "https://archive.eclipse.org/jetty/8.0.1.v20110908/xref/org/eclipse/jetty/http/security/UnixCrypt.html": "UnixCrypt", + "https://artlibre.org/": "LAL-1.3", + "https://assets.ubuntu.com/v1/81e5605d-ubuntu-font-licence-1.0.txt": "Ubuntu-font-1.0", + "https://blueoakcouncil.org/license/1.0.0": "BlueOak-1.0.0", + "https://cdla.dev/computational-use-of-data-agreement-v1-0/": "C-UDA-1.0", + "https://cdla.dev/open-use-of-data-agreement-v1-0/": "O-UDA-1.0", + "https://cdla.dev/permissive-2-0": "CDLA-Permissive-2.0", + "https://cdla.io/permissive-1-0": "CDLA-Permissive-1.0", + "https://cdla.io/sharing-1-0": "CDLA-Sharing-1.0", + "https://celestrak.org/publications/AIAA/2006-6753/faq.php": "SGP4", + "https://cgit.freedesktop.org/libbsd/tree/man/setproctitle.3bsd": "libutil-David-Nugent", + "https://coil.apotheon.org/plaintext/01.0.txt": "COIL-1.0", + "https://core.tcl-lang.org/tk/file?name=compat/unistd.h": "HPND-UC", + "https://creativecommons.org/licenses/by-nc-nd/2.0/legalcode": "CC-BY-NC-ND-2.0", + "https://creativecommons.org/licenses/by-nc-nd/2.5/legalcode": "CC-BY-NC-ND-2.5", + "https://creativecommons.org/licenses/by-nc-nd/3.0/de/legalcode": "CC-BY-NC-ND-3.0-DE", + "https://creativecommons.org/licenses/by-nc-nd/3.0/igo/legalcode": "CC-BY-NC-ND-3.0-IGO", + "https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode": "CC-BY-NC-ND-3.0", + "https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode": "CC-BY-NC-ND-4.0", + "https://creativecommons.org/licenses/by-nc-sa/1.0/legalcode": "CC-BY-NC-SA-1.0", + "https://creativecommons.org/licenses/by-nc-sa/2.0/de/legalcode": "CC-BY-NC-SA-2.0-DE", + "https://creativecommons.org/licenses/by-nc-sa/2.0/fr/legalcode": "CC-BY-NC-SA-2.0-FR", + "https://creativecommons.org/licenses/by-nc-sa/2.0/legalcode": "CC-BY-NC-SA-2.0", + "https://creativecommons.org/licenses/by-nc-sa/2.0/uk/legalcode": "CC-BY-NC-SA-2.0-UK", + "https://creativecommons.org/licenses/by-nc-sa/2.5/legalcode": "CC-BY-NC-SA-2.5", + "https://creativecommons.org/licenses/by-nc-sa/3.0/de/legalcode": "CC-BY-NC-SA-3.0-DE", + "https://creativecommons.org/licenses/by-nc-sa/3.0/igo/legalcode": "CC-BY-NC-SA-3.0-IGO", + "https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode": "CC-BY-NC-SA-3.0", + "https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode": "CC-BY-NC-SA-4.0", + "https://creativecommons.org/licenses/by-nc/1.0/legalcode": "CC-BY-NC-1.0", + "https://creativecommons.org/licenses/by-nc/2.0/legalcode": "CC-BY-NC-2.0", + "https://creativecommons.org/licenses/by-nc/2.5/legalcode": "CC-BY-NC-2.5", + "https://creativecommons.org/licenses/by-nc/3.0/de/legalcode": "CC-BY-NC-3.0-DE", + "https://creativecommons.org/licenses/by-nc/3.0/legalcode": "CC-BY-NC-3.0", + "https://creativecommons.org/licenses/by-nc/4.0/legalcode": "CC-BY-NC-4.0", + "https://creativecommons.org/licenses/by-nd-nc/1.0/legalcode": "CC-BY-NC-ND-1.0", + "https://creativecommons.org/licenses/by-nd/1.0/legalcode": "CC-BY-ND-1.0", + "https://creativecommons.org/licenses/by-nd/2.0/legalcode": "CC-BY-ND-2.0", + "https://creativecommons.org/licenses/by-nd/2.5/legalcode": "CC-BY-ND-2.5", + "https://creativecommons.org/licenses/by-nd/3.0/de/legalcode": "CC-BY-ND-3.0-DE", + "https://creativecommons.org/licenses/by-nd/3.0/legalcode": "CC-BY-ND-3.0", + "https://creativecommons.org/licenses/by-nd/4.0/legalcode": "CC-BY-ND-4.0", + "https://creativecommons.org/licenses/by-sa/1.0/legalcode": "CC-BY-SA-1.0", + "https://creativecommons.org/licenses/by-sa/2.0/legalcode": "CC-BY-SA-2.0", + "https://creativecommons.org/licenses/by-sa/2.0/uk/legalcode": "CC-BY-SA-2.0-UK", + "https://creativecommons.org/licenses/by-sa/2.1/jp/legalcode": "CC-BY-SA-2.1-JP", + "https://creativecommons.org/licenses/by-sa/2.5/legalcode": "CC-BY-SA-2.5", + "https://creativecommons.org/licenses/by-sa/3.0/at/legalcode": "CC-BY-SA-3.0-AT", + "https://creativecommons.org/licenses/by-sa/3.0/de/legalcode": "CC-BY-SA-3.0-DE", + "https://creativecommons.org/licenses/by-sa/3.0/igo/legalcode": "CC-BY-SA-3.0-IGO", + "https://creativecommons.org/licenses/by-sa/3.0/legalcode": "CC-BY-SA-3.0", + "https://creativecommons.org/licenses/by-sa/4.0/legalcode": "CC-BY-SA-4.0", + "https://creativecommons.org/licenses/by/1.0/legalcode": "CC-BY-1.0", + "https://creativecommons.org/licenses/by/2.0/legalcode": "CC-BY-2.0", + "https://creativecommons.org/licenses/by/2.5/au/legalcode": "CC-BY-2.5-AU", + "https://creativecommons.org/licenses/by/2.5/legalcode": "CC-BY-2.5", + "https://creativecommons.org/licenses/by/3.0/at/legalcode": "CC-BY-3.0-AT", + "https://creativecommons.org/licenses/by/3.0/au/legalcode": "CC-BY-3.0-AU", + "https://creativecommons.org/licenses/by/3.0/de/legalcode": "CC-BY-3.0-DE", + "https://creativecommons.org/licenses/by/3.0/igo/legalcode": "CC-BY-3.0-IGO", + "https://creativecommons.org/licenses/by/3.0/legalcode": "CC-BY-3.0", + "https://creativecommons.org/licenses/by/3.0/nl/legalcode": "CC-BY-3.0-NL", + "https://creativecommons.org/licenses/by/3.0/us/legalcode": "CC-BY-3.0-US", + "https://creativecommons.org/licenses/by/4.0/legalcode": "CC-BY-4.0", + "https://creativecommons.org/licenses/publicdomain/": "CC-PDDC", + "https://creativecommons.org/licenses/sa/1.0/legalcode": "CC-SA-1.0", + "https://creativecommons.org/publicdomain/mark/1.0/": "CC-PDM-1.0", + "https://creativecommons.org/publicdomain/zero/1.0/legalcode": "CC0-1.0", + "https://creativecommons.org/share-your-work/cclicenses/": "CC-PDM-1.0", + "https://ctan.math.utah.edu/ctan/tex-archive/macros/generic/kastrup/binhex.dtx": "Kastrup", + "https://ctan.math.utah.edu/ctan/tex-archive/macros/generic/misc/swrule.sty": "swrule", + "https://ctan.org/license/knuth": "Knuth-CTAN", + "https://data.gov.tw/license": "OGDL-Taiwan-1.0", + "https://directory.fsf.org/wiki/License:Fdk": "FDK-AAC", + "https://doc.qt.io/archives/3.3/license.html": "QPL-1.0", + "https://docs.omniverse.nvidia.com/install-guide/latest/common/licenses.html": "AML-glslang", + "https://docs.oracle.com/cd/E81115_01/html/E81116/licenses.html": "man2html", + "https://docs.python.org/3/license.html": "Python-2.0.1", + "https://docubrain.com/sites/default/files/licenses/bitstream-vera.html": "Bitstream-Vera", + "https://en.wikipedia.org/wiki/Shared_Source_Initiative#Microsoft_Limited_Public_License_(Ms-LPL)": "MS-LPL", + "https://enterprise.dejacode.com/licenses/public/naist-2003/#license-text": "NAIST-2003", + "https://epics.anl.gov/license/open.php": "EPICS", + "https://fedoraproject.org/wiki/Licensing/AMD_plpa_map_License": "AMDPLPA", + "https://fedoraproject.org/wiki/Licensing/Abstyles": "Abstyles", + "https://fedoraproject.org/wiki/Licensing/AdobeLicense": "Adobe-2006", + "https://fedoraproject.org/wiki/Licensing/AdobePostscriptAFM": "APAFML", + "https://fedoraproject.org/wiki/Licensing/Afmparse": "Afmparse", + "https://fedoraproject.org/wiki/Licensing/AmazonDigitalServicesLicense": "ADSL", + "https://fedoraproject.org/wiki/Licensing/App-s2p": "App-s2p", + "https://fedoraproject.org/wiki/Licensing/Apple_MIT_License": "AML", + "https://fedoraproject.org/wiki/Licensing/Apple_Public_Source_License_1.0": "APSL-1.0", + "https://fedoraproject.org/wiki/Licensing/BSD#AMPASBSD": "AMPAS", + "https://fedoraproject.org/wiki/Licensing/BSD_Protection_License": "BSD-Protection", + "https://fedoraproject.org/wiki/Licensing/BSD_with_Attribution": "BSD-3-Clause-Attribution", + "https://fedoraproject.org/wiki/Licensing/Bahyph": "Bahyph", + "https://fedoraproject.org/wiki/Licensing/Barr": "Barr", + "https://fedoraproject.org/wiki/Licensing/Beerware": "Beerware", + "https://fedoraproject.org/wiki/Licensing/Borceux": "Borceux", + "https://fedoraproject.org/wiki/Licensing/Charter#License_Text": "Bitstream-Charter", + "https://fedoraproject.org/wiki/Licensing/Common_Documentation_License": "CDL-1.0", + "https://fedoraproject.org/wiki/Licensing/Crossword": "Crossword", + "https://fedoraproject.org/wiki/Licensing/Cube": "Cube", + "https://fedoraproject.org/wiki/Licensing/DSDP": "DSDP", + "https://fedoraproject.org/wiki/Licensing/Dotseqn": "Dotseqn", + "https://fedoraproject.org/wiki/Licensing/Eurosym": "Eurosym", + "https://fedoraproject.org/wiki/Licensing/FDK-AAC": "FDK-AAC", + "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License": "FSFUL", + "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License#License_Retention_Variant": "FSFULLR", + "https://fedoraproject.org/wiki/Licensing/Glulxe": "Glulxe", + "https://fedoraproject.org/wiki/Licensing/Gnuplot": "gnuplot", + "https://fedoraproject.org/wiki/Licensing/Haskell_Language_Report_License": "HaskellReport", + "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License": "Spencer-94", + "https://fedoraproject.org/wiki/Licensing/Inner_Net_License": "Inner-Net-2.0", + "https://fedoraproject.org/wiki/Licensing/Intel_ACPI_Software_License_Agreement": "Intel-ACPI", + "https://fedoraproject.org/wiki/Licensing/LBNLBSD": "BSD-3-Clause-LBNL", + "https://fedoraproject.org/wiki/Licensing/Latex2e": "Latex2e", + "https://fedoraproject.org/wiki/Licensing/Leptonica": "Leptonica", + "https://fedoraproject.org/wiki/Licensing/MIT": "mpich2", + "https://fedoraproject.org/wiki/Licensing/MIT#AdobeGlyph": "Adobe-Glyph", + "https://fedoraproject.org/wiki/Licensing/MIT#enna": "MIT-enna", + "https://fedoraproject.org/wiki/Licensing/MIT#feh": "MIT-feh", + "https://fedoraproject.org/wiki/Licensing/MITNFA": "MITNFA", + "https://fedoraproject.org/wiki/Licensing/MIT_With_Advertising": "MIT-advertising", + "https://fedoraproject.org/wiki/Licensing/MakeIndex": "MakeIndex", + "https://fedoraproject.org/wiki/Licensing/Matrix_Template_Library_License": "MTLL", + "https://fedoraproject.org/wiki/Licensing/Mup": "Mup", + "https://fedoraproject.org/wiki/Licensing/NLPL": "NLPL", + "https://fedoraproject.org/wiki/Licensing/Newsletr": "Newsletr", + "https://fedoraproject.org/wiki/Licensing/Noweb": "Noweb", + "https://fedoraproject.org/wiki/Licensing/OSL1.1": "OSL-1.1", + "https://fedoraproject.org/wiki/Licensing/Open_Market_License": "OML", + "https://fedoraproject.org/wiki/Licensing/Open_Public_License": "OPL-1.0", + "https://fedoraproject.org/wiki/Licensing/Plexus_Classworlds_License": "Plexus", + "https://fedoraproject.org/wiki/Licensing/Qhull": "Qhull", + "https://fedoraproject.org/wiki/Licensing/Rdisc_License": "Rdisc", + "https://fedoraproject.org/wiki/Licensing/SNIA_Public_License": "SNIA", + "https://fedoraproject.org/wiki/Licensing/SWL": "SWL", + "https://fedoraproject.org/wiki/Licensing/Saxpath_License": "Saxpath", + "https://fedoraproject.org/wiki/Licensing/TCL": "TCL", + "https://fedoraproject.org/wiki/Licensing/TGPPL": "TGPPL-1.0", + "https://fedoraproject.org/wiki/Licensing/TORQUEv1.1": "TORQUE-1.1", + "https://fedoraproject.org/wiki/Licensing/TOSL": "TOSL", + "https://fedoraproject.org/wiki/Licensing/TTWL": "TTWL", + "https://fedoraproject.org/wiki/Licensing/Threeparttable": "threeparttable", + "https://fedoraproject.org/wiki/Licensing/VOSTROM": "VOSTROM", + "https://fedoraproject.org/wiki/Licensing/Wsuipa": "Wsuipa", + "https://fedoraproject.org/wiki/Licensing/XSkat_License": "XSkat", + "https://fedoraproject.org/wiki/Licensing/Xerox": "Xerox", + "https://fedoraproject.org/wiki/Licensing/Xinetd_License": "xinetd", + "https://fedoraproject.org/wiki/Licensing/Zed": "Zed", + "https://fedoraproject.org/wiki/Licensing/ZlibWithAcknowledgement": "zlib-acknowledgement", + "https://fedoraproject.org/wiki/Licensing/diffmark": "diffmark", + "https://fedoraproject.org/wiki/Licensing/dvipdfm": "dvipdfm", + "https://fedoraproject.org/wiki/Licensing/eGenix.com_Public_License_1.1.0": "eGenix", + "https://fedoraproject.org/wiki/Licensing/libtiff": "libtiff", + "https://fedoraproject.org/wiki/Licensing/psfrag": "psfrag", + "https://fedoraproject.org/wiki/Licensing/psutils": "psutils", + "https://fedoraproject.org/wiki/Licensing/softSurfer": "softSurfer", + "https://fedoraproject.org/wiki/Licensing/xpp": "xpp", + "https://fedoraproject.org/wiki/Licensing:BSD#Modification_Variant": "BSD-3-Clause-Modification", + "https://fedoraproject.org/wiki/Licensing:Baekmuk?rd=Licensing/Baekmuk": "Baekmuk", + "https://fedoraproject.org/wiki/Licensing:CrystalStacker?rd=Licensing/CrystalStacker": "CrystalStacker", + "https://fedoraproject.org/wiki/Licensing:MIT#Another_Minimal_variant_(found_in_libatomic_ops)": "Boehm-GC", + "https://fedoraproject.org/wiki/Licensing:MIT#Modern_Variants": "MIT-Modern-Variant", + "https://fedoraproject.org/wiki/Licensing:MIT#OpenVision_Variant": "OpenVision", + "https://fedoraproject.org/wiki/Licensing:MIT#Xfig_Variant": "Xfig", + "https://fedoraproject.org/wiki/Licensing:MIT?rd=Licensing/MIT#CMU_Style": "MIT-CMU", + "https://fedoraproject.org/wiki/Licensing:Mplus?rd=Licensing/mplus": "mplus", + "https://fedoraproject.org/wiki/Licensing:ThorPublicLicense": "TPL-1.0", + "https://firstdonoharm.dev/version/2/1/license.html": "Hippocratic-2.1", + "https://forge.gouv.qc.ca/licence/fr/liliq-v1-1/": "LiLiQ-P-1.1", + "https://foss.heptapod.net/python-libs/passlib/-/blob/branch/stable/LICENSE#L70": "UnixCrypt", + "https://fossies.org/linux/sendmail/contrib/mailprio": "mailprio", + "https://fossies.org/linux/tiff/contrib/ras/ras2tif.c": "xlock", + "https://fsl.software/FSL-1.1-ALv2.template.md": "FSL-1.1-ALv2", + "https://fsl.software/FSL-1.1-MIT.template.md": "FSL-1.1-MIT", + "https://ftp.gnu.org/gnu/aspell/dict/ru/aspell6-ru-0.99f7-1.tar.bz2": "Aspell-RU", + "https://git.enlightenment.org/legacy/imlib2.git/tree/COPYING": "Imlib2", + "https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man2/getcpu.2#n4": "Linux-man-pages-1-para", + "https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man2/migrate_pages.2#n8": "Linux-man-pages-copyleft-2-para", + "https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man2/move_pages.2#n5": "Linux-man-pages-copyleft-2-para", + "https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man2/set_mempolicy.2#n5": "Linux-man-pages-copyleft-var", + "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/infiniband/core/sa.h": "Linux-OpenIB", + "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/sunrpc/auth_gss/gss_generic_token.c?h=v4.19": "HPND-sell-variant", + "https://git.openldap.org/openldap/openldap/-/blob/master/COPYRIGHT#L55-63": "BSD-4.3RENO", + "https://git.openldap.org/openldap/openldap/-/blob/master/COPYRIGHT?ref_type=heads#L39-51": "Furuseth", + "https://git.openldap.org/openldap/openldap/-/blob/master/libraries/libldap/os-local.c?ref_type=heads#L19-23": "PADL", + "https://git.savannah.gnu.org/cgit/gnulib.git/tree/modules/COPYING?id=7b08932179d0d6b017f7df01a2ddf6e096b038e3": "FSFULLRSD", + "https://git.savannah.gnu.org/cgit/indent.git/tree/doc/indent.texi?id=a74c6b4ee49397cf330b333da1042bffa60ed14f#n1788": "BSD-4.3TAHOE", + "https://git.savannah.gnu.org/cgit/indent.git/tree/doc/indent.texi?id=a74c6b4ee49397cf330b333da1042bffa60ed14f#n74": "Latex2e-translated-notice", + "https://git.savannah.gnu.org/cgit/wget.git/tree/util/trunc.c?h=v1.21.3&id=40747a11e44ced5a8ac628a41f879ced3e2ebce9#n6": "FSFAP-no-warranty-disclaimer", + "https://github.com/389ds/389-ds-base/blob/main/ldap/include/sysexits-compat.h#L15": "BSD-4.3TAHOE", + "https://github.com/AcademySoftwareFoundation/foundation/blob/main/digital_assets/aswf_digital_assets_license_v1.0.txt": "ASWF-Digital-Assets-1.0", + "https://github.com/AcademySoftwareFoundation/foundation/blob/main/digital_assets/aswf_digital_assets_license_v1.1.txt": "ASWF-Digital-Assets-1.1", + "https://github.com/AdaCore/gnatcoll-core/blob/master/docs/index.rst": "AdaCore-doc", + "https://github.com/AdaCore/gnatcoll-db/blob/master/docs/index.rst": "AdaCore-doc", + "https://github.com/AdaCore/xmlada/blob/master/docs/index.rst": "AdaCore-doc", + "https://github.com/CommunitySpecification/1.0/blob/master/1._Community_Specification_License-v1.md": "Community-Spec-1.0", + "https://github.com/CorsixTH/deps/blob/fd339a9f526d1d9c9f01ccf39e438a015da50035/licences/libgsm.txt": "TU-Berlin-2.0", + "https://github.com/Cyan4973/xxHash/blob/dev/doc/xxhash_spec.md": "LPD-document", + "https://github.com/DISIC/politique-de-contribution-open-source/blob/master/LICENSE.pdf": "etalab-2.0", + "https://github.com/Distrotech/hdparm/blob/4517550db29a91420fb2b020349523b1b4512df2/LICENSE.TXT": "hdparm", + "https://github.com/Distrotech/transfig/blob/master/transfig/transfig.c": "Xfig", + "https://github.com/DrItanium/maya/blob/master/LICENSE.CLIPS": "Clips", + "https://github.com/Dual-Life/mime-base64/blob/master/Base64.xs#L12": "metamail", + "https://github.com/EthicalSource/hippocratic-license/blob/58c0e646d64ff6fbee275bfe2b9492f914e3ab2a/LICENSE.txt": "Hippocratic-2.1", + "https://github.com/FreeRADIUS/freeradius-client/blob/master/COPYRIGHT#L32": "HPND-Fenneberg-Livingston", + "https://github.com/GNOME/gcr/blob/master/docs/COPYING": "GCR-docs", + "https://github.com/GNOME/libxml2/blob/master/dict.c": "ISC-Veillard", + "https://github.com/HDFGroup/hdf5/?tab=License-1-ov-file#readme": "HDF5", + "https://github.com/KhronosGroup/SPIRV-Cross/blob/main/LICENSES/LicenseRef-KhronosFreeUse.txt": "MIT-Khronos-old", + "https://github.com/KhronosGroup/glslang/blob/main/LICENSE.txt#L949": "AML-glslang", + "https://github.com/MariaDB/server/blob/11.6/libmysqld/lib_sql.cc": "Boehm-GC-without-fee", + "https://github.com/Neo23x0/sigma/blob/master/LICENSE.Detection.Rules.md": "DRL-1.0", + "https://github.com/OGRECave/ogre/blob/master/OgreMain/include/OgreSingleton.h#L28C3-L35C46": "Game-Programming-Gems", + "https://github.com/Perl/perl5/blob/blead/util.c#L6136": "Martin-Birgmeier", + "https://github.com/PixarAnimationStudios/OpenSubdiv/blob/v3_5_0/opensubdiv/version.cpp#L2-L22": "Pixar", + "https://github.com/PixarAnimationStudios/OpenSubdiv/raw/v3_5_0/LICENSE.txt": "Pixar", + "https://github.com/RTimothyEdwards/magic/blob/master/LICENSE": "HPND-UC-export-US", + "https://github.com/SELinuxProject/selinux/blob/master/libselinux/LICENSE": "libselinux-1.0", + "https://github.com/SWI-Prolog/packages-clib/blob/master/sha1/brg_endian.h": "Brian-Gladman-3-Clause", + "https://github.com/SWI-Prolog/packages-xpce/blob/161a40cd82004f731ba48024f9d30af388a7edf5/src/img/gifwrite.c#L21-L26": "FBM", + "https://github.com/SWI-Prolog/swipl-devel/blob/master/src/os/dtoa.c": "dtoa", + "https://github.com/SigmaHQ/Detection-Rule-License/blob/6ec7fbde6101d101b5b5d1fcb8f9b69fbc76c04a/LICENSE.Detection.Rules.md": "DRL-1.1", + "https://github.com/Slicer/Slicer/blob/main/License.txt": "3D-Slicer-1.0", + "https://github.com/Unidata/UDUNITS-2/blob/master/COPYRIGHT": "UCAR", + "https://github.com/acpica/acpica/blob/master/source/common/acfileio.c#L119": "BSD-3-Clause-acpica", + "https://github.com/adaptivecomputing/torque/blob/master/PBS_License.txt": "OpenPBS-2.3", + "https://github.com/ap/Text-Tabs/blob/master/lib.modern/Text/Tabs.pm#L148": "TTWL", + "https://github.com/apache/apr/blob/trunk/LICENSE#L298C6-L298C29": "Caldera-no-preamble", + "https://github.com/audacious-media-player/audacious/blob/master/COPYING": "BSD-2-Clause-pkgconf-disclaimer", + "https://github.com/audacious-media-player/audacious/blob/master/src/audacious/main.cc": "BSD-2-Clause-pkgconf-disclaimer", + "https://github.com/aws/mit-0": "MIT-0", + "https://github.com/awsdocs/aws-cloud9-user-guide/blob/master/LICENSE-SAMPLECODE": "MIT-0", + "https://github.com/bagder/curl/blob/master/COPYING": "curl", + "https://github.com/bcrypt-ruby/bcrypt-ruby/blob/master/ext/mri/crypt_blowfish.c": "bcrypt-Solar-Designer", + "https://github.com/blakemcbride/eclipse-lisp/blob/master/lisp/loop.lisp": "LOOP", + "https://github.com/bleargh45/Data-UUID/blob/master/LICENSE": "HP-1989", + "https://github.com/chromium/octane/blob/master/crypto.js": "MIT-Wu", + "https://github.com/cl-adams/adams/blob/master/LICENSE.md": "LOOP", + "https://github.com/copyleft-next/copyleft-next/blob/master/Releases/copyleft-next-0.3.0": "copyleft-next-0.3.0", + "https://github.com/copyleft-next/copyleft-next/blob/master/Releases/copyleft-next-0.3.1": "copyleft-next-0.3.1", + "https://github.com/cyrusimap/cyrus-sasl/blob/master/COPYING": "BSD-Attribution-HPND-disclaimer", + "https://github.com/dcblake/SMP/blob/master/Documentation/License.txt": "SMPPL", + "https://github.com/dfateyev/libwhirlpool/blob/master/README#L27": "Unlicense-libwhirlpool", + "https://github.com/docbook/xslt10-stylesheets/blob/efd62655c11cc8773708df7a843613fa1e932bf8/xsl/COPYING#L27": "DocBook-XML", + "https://github.com/docbook/xslt10-stylesheets/blob/efd62655c11cc8773708df7a843613fa1e932bf8/xsl/assembly/schema/docbook51b7.rnc": "DocBook-Schema", + "https://github.com/dotnet/runtime/blob/55e1ac7c07df62c4108d4acedf78f77574470ce5/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/AttRegexTests.cs#L12-L28": "MIT-testregex", + "https://github.com/elastic/elasticsearch/blob/master/licenses/ELASTIC-LICENSE-2.0.txt": "Elastic-2.0", + "https://github.com/erich666/GraphicsGems/blob/master/LICENSE.md": "Graphics-Gems", + "https://github.com/fedeinthemix/chez-srfi/blob/master/srfi/LICENSE": "X11-swapped", + "https://github.com/festvox/flite/blob/master/COPYING": "MIT-Festival", + "https://github.com/festvox/speech_tools/blob/master/COPYING": "MIT-Festival", + "https://github.com/file/file/blob/master/COPYING": "BSD-2-Clause-Darwin", + "https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/e_acosh.c": "SunPro", + "https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/e_lgammal.c": "SunPro", + "https://github.com/gabegundy/atlserver/blob/master/License.txt": "MS-LPL", + "https://github.com/greymass/swift-eosio/blob/master/LICENSE": "BSD-3-Clause-No-Military-License", + "https://github.com/hamano/man2html/blob/master/man2html.c": "man2html", + "https://github.com/htacg/tidy-html5/blob/next/README/LICENSE.md": "HTMLTIDY", + "https://github.com/ivmai/libatomic_ops/blob/master/LICENSE": "Boehm-GC", + "https://github.com/jonathanstowe/TermReadKey/blob/master/README#L9-L10": "TermReadKey", + "https://github.com/jonmacs/jove/blob/4_17/LICENSE": "jove", + "https://github.com/jpr5/ngrep/blob/master/LICENSE": "ngrep", + "https://github.com/jrsoftware/issrc/blob/HEAD/license.txt": "InnoSetup", + "https://github.com/kfish/xsel/blob/master/COPYING": "HPND-sell-variant", + "https://github.com/kohler/t1utils/blob/master/LICENSE": "MIT-Click", + "https://github.com/krb5/krb5/blob/krb5-1.21.2-final/NOTICE#L111-L133": "HPND-export2-US", + "https://github.com/krb5/krb5/blob/krb5-1.21.2-final/NOTICE#L1157-L1182": "HPND-export-US-modify", + "https://github.com/krb5/krb5/blob/krb5-1.21.2-final/NOTICE#L140-L156": "Brian-Gladman-2-Clause", + "https://github.com/krb5/krb5/blob/krb5-1.21.2-final/NOTICE#L66-L98": "OpenVision", + "https://github.com/krb5/krb5/blob/krb5-1.21.2-final/NOTICE#L664-L690": "BSD-2-Clause-first-lines", + "https://github.com/krb5/krb5/blob/krb5-1.21.2-final/NOTICE#L718-L728": "CMU-Mach-nodoc", + "https://github.com/krb5/krb5/blob/krb5-1.21.2-final/NOTICE#L831-L852": "HPND-export-US-acknowledgement", + "https://github.com/krzyzanowskim/CryptoSwift/blob/main/LICENSE": "CryptoSwift", + "https://github.com/lattera/freebsd/blob/master/sys/cam/cam.c#L4": "BSD-Source-beginning-file", + "https://github.com/libcheck/check/blob/master/checkmk/checkmk.in": "checkmk", + "https://github.com/lsof-org/lsof/blob/master/COPYING": "lsof", + "https://github.com/maranget/hevea/blob/master/LICENSE": "QPL-1.0-INRIA-2004", + "https://github.com/me-shaon/GLWTPL/commit/da5f6bc734095efbacb442c0b31e33a65b9d6e85": "GLWTPL", + "https://github.com/mhogomchungu/zuluCrypt/blob/master/external_libraries/tcplay/generic_xts.c": "generic-xts", + "https://github.com/microsoft/Computational-Use-of-Data-Agreement/blob/master/C-UDA-1.0.md": "C-UDA-1.0", + "https://github.com/microsoft/Open-Use-of-Data-Agreement/blob/v1.0/O-UDA-1.0.md": "O-UDA-1.0", + "https://github.com/mirror/ncurses/blob/master/COPYING": "X11-distribute-modifications-variant", + "https://github.com/mm2/Little-CMS/blob/master/src/cmssm.c#L207": "softSurfer", + "https://github.com/mruby/mruby/blob/83d12f8d52522cdb7c8cc46fad34821359f453e6/mrbgems/mruby-dir/src/Win/dirent.c#L127-L140": "HPND-Kevlin-Henney", + "https://github.com/mtoyoda/sl/blob/master/LICENSE": "SL", + "https://github.com/n8n-io/n8n/blob/master/LICENSE.md": "SUL-1.0", + "https://github.com/ncbi/datasets/blob/0ea4cd16b61e5b799d9cc55aecfa016d6c9bd2bf/LICENSE.md": "NCBI-PD", + "https://github.com/ncbi/datasets/blob/master/LICENSE.md": "NCBI-PD", + "https://github.com/ncbi/egapx/blob/08930b9dec0c69b2d1a05e5153c7b95ef0a3eb0f/LICENSE": "NCBI-PD", + "https://github.com/ncbi/gprobe/blob/de64d30fee8b4c4013094d7d3139ea89b5dd1ace/LICENSE": "NCBI-PD", + "https://github.com/ncbi/sra-tools/blob/e8e5b6af4edc460156ad9ce5902d0779cffbf685/LICENSE": "NCBI-PD", + "https://github.com/nodejs/node/blob/4a19cc8947b1bba2b2d27816ec3d0edf9b28e503/LICENSE#L343": "NAIST-2003", + "https://github.com/novnc/noVNC/blob/master/core/crypto/des.js#L24": "Widget-Workshop", + "https://github.com/oetiker/rrdtool-1.x/blob/master/src/plbasename.c#L8-L11": "gtkbook", + "https://github.com/open-quantum-safe/liboqs/blob/40b01fdbb270f8614fde30e65d30e9da18c02393/src/common/rand/rand_nist.c#L1-L15": "NIST-Software", + "https://github.com/openjdk/jdk/blob/6162e2c5213c5dd7c1127fd9616b543efa898962/LICENSE": "GPL-2.0-or-later", + "https://github.com/openssh/openssh-portable/blob/1b11ea7c58cd5c59838b5fa574cd456d6047b2d4/LICENCE#L10": "SSH-OpenSSH", + "https://github.com/openssh/openssh-portable/blob/1b11ea7c58cd5c59838b5fa574cd456d6047b2d4/pathnames.h": "SSH-short", + "https://github.com/openssh/openssh-portable/blob/master/LICENCE#L82": "ssh-keyscan", + "https://github.com/openssh/openssh-portable/blob/master/openbsd-compat/bsd-snprintf.c#L2": "snprintf", + "https://github.com/pkgconf/pkgconf/blob/master/cli/main.c#L8": "pkgconf", + "https://github.com/ppp-project/ppp/blob/master/modules/ppp_ahdlc.c#L7-L19": "Sun-PPP-2000", + "https://github.com/ppp-project/ppp/blob/master/pppd/auth.c#L6-L28": "Mackerras-3-Clause-acknowledgment", + "https://github.com/ppp-project/ppp/blob/master/pppd/chap_ms.c#L6-L28": "Mackerras-3-Clause", + "https://github.com/ppp-project/ppp/blob/master/pppd/eap.c#L7-L16": "Sun-PPP", + "https://github.com/ppp-project/ppp/blob/master/pppd/ipv6cp.c#L75-L83": "HPND-INRIA-IMAG", + "https://github.com/protegeproject/protege/blob/master/license.txt": "BSD-2-Clause-Views", + "https://github.com/python-excel/xlrd/blob/master/LICENSE#L33": "BSD-Advertising-Acknowledgement", + "https://github.com/python-ldap/python-ldap/blob/main/LICENCE": "python-ldap", + "https://github.com/python-pillow/Pillow/blob/fffb426092c8db24a5f4b6df243a8a3c01fb63cd/LICENSE": "MIT-CMU", + "https://github.com/python/cpython/blob/main/LICENSE": "Python-2.0.1", + "https://github.com/pythongssapi/k5test/blob/v0.10.3/K5TEST-LICENSE.txt": "HPND-export-US-modify", + "https://github.com/radcli/radcli/blob/master/COPYRIGHT#L34": "HPND-Fenneberg-Livingston", + "https://github.com/radcli/radcli/blob/master/COPYRIGHT#L64": "UMich-Merit", + "https://github.com/radvd-project/radvd/blob/master/COPYRIGHT": "radvd", + "https://github.com/robbiehanson/CocoaHTTPServer/blob/master/LICENSE.txt": "BSD-Source-Code", + "https://github.com/ruby/ruby/blob/9f6deaa6888a423720b4b127b5314f0ad26cc2e6/ext/pty/pty.c#L775-L786": "Ruby-pty", + "https://github.com/ruby/ruby/commit/0a64817fb80016030c03518fb9459f63c11605ea#diff-ef5fa30838d6d0cecad9e675cc50b24628cfe2cb277c346053fafcc36c91c204": "Ruby-pty", + "https://github.com/ruby/ruby/commit/0a64817fb80016030c03518fb9459f63c11605ea#diff-fedf217c1ce44bda01f0a678d3ff8b198bed478754d699c527a698ad933979a0": "Ruby-pty", + "https://github.com/scummvm/scummvm/blob/v2.8.0/LICENSES/CatharonLicense.txt": "Catharon", + "https://github.com/seanmiddleditch/libtelnet/blob/develop/COPYING": "Unlicense-libtelnet", + "https://github.com/sigmavirus24/x11-ssh-askpass/blob/master/README": "HPND-sell-variant-MIT-disclaimer", + "https://github.com/sigmavirus24/x11-ssh-askpass/blob/master/dynlist.c": "HPND-sell-variant-MIT-disclaimer-rev", + "https://github.com/signal11/hidapi/blob/master/LICENSE-orig.txt": "HIDAPI", + "https://github.com/slogan621/gtkbook": "gtkbook", + "https://github.com/swh/ladspa/blob/7bf6f3799fdba70fda297c2d8fd9f526803d9680/gsm/COPYRIGHT": "TU-Berlin-1.0", + "https://github.com/tats/w3m/blob/master/COPYING": "w3m", + "https://github.com/tcheneau/Routing/blob/f09f46fcfe636107f22f2c98348188a65a135d98/README.md": "NIST-PD", + "https://github.com/tcheneau/simpleRPL/blob/e645e69e38dd4e3ccfeceb2db8cba05b7c2e0cd3/LICENSE.txt": "NIST-PD", + "https://github.com/trusteddomainproject/OpenDMARC/blob/master/LICENSE.Sendmail": "Sendmail-Open-Source-1.1", + "https://github.com/tytso/e2fsprogs/blob/master/lib/et/et_name.c": "NTP-0", + "https://github.com/uim/libgcroots/blob/master/COPYING": "Boehm-GC", + "https://github.com/usnistgov/fipy/blob/86aaa5c2ba2c6f1be19593c5986071cf6568cc34/LICENSE.rst": "NIST-PD-fallback", + "https://github.com/usnistgov/jsip/blob/59700e6926cbe96c5cdae897d9a7d2656b42abe3/LICENSE": "NIST-PD-fallback", + "https://github.com/wernerd/ZRTPCPP/blob/6b3cd8e6783642292bad0c21e3e5e5ce45ff3e03/cryptcommon/twofish.c#L113C3-L127": "Ferguson-Twofish", + "https://github.com/westes/flex/blob/master/COPYING": "BSD-3-Clause-flex", + "https://github.com/xdebug/xdebug/blob/master/LICENSE": "Xdebug-1.03", + "https://github.com/xmlark/msv/blob/b9316e2f2270bc1606952ea4939ec87fbba157f3/xsdlib/src/main/java/com/sun/msv/datatype/regexp/InternalImpl.java": "BSD-3-Clause-Sun", + "https://github.com/yuwenlong/longphp/blob/25dfb70cc2a466dc4bb55ba30901cbce08d164b5/LICENSE": "MulanPSL-1.0", + "https://github.com/zdohnal/hplip/blob/master/COPYING#L939": "BSD-3-Clause-HP", + "https://gitlab.com/bacula-org/bacula/-/blob/Branch-11.0/bacula/LICENSE-FOSS?ref_type=heads#L245": "HPND-sell-regexpr", + "https://gitlab.com/embeddable-common-lisp/ecl/-/blob/develop/src/lsp/loop.lsp": "LOOP", + "https://gitlab.com/libeigen/eigen/-/blob/master/COPYING.MINPACK": "Minpack", + "https://gitlab.common-lisp.net/cmucl/cmucl/-/blob/master/src/code/loop.lisp": "LOOP", + "https://gitlab.freedesktop.org/libopenraw/libopenraw/blob/master/lib/ljpegdecompressor.cpp#L32": "Cornell-Lossless-JPEG", + "https://gitlab.freedesktop.org/mesa/glw/-/blob/master/README?ref_type=heads": "SGI-OpenGL", + "https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/master/src/modules/module-filter-chain/pffft.c?ref_type=heads#L1-52": "NCL", + "https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/blob/master/COPYING?ref_type=heads#L178": "xkeyboard-config-Zinoviev", + "https://gitlab.freedesktop.org/xorg/app/iceauth/-/blob/master/COPYING": "MIT-open-group", + "https://gitlab.freedesktop.org/xorg/app/xauth/-/blob/master/COPYING": "MIT-open-group", + "https://gitlab.freedesktop.org/xorg/app/xkbcomp/-/blob/master/COPYING?ref_type=heads#L69": "HPND-DEC", + "https://gitlab.freedesktop.org/xorg/app/xsetroot/-/blob/master/COPYING": "MIT-open-group", + "https://gitlab.freedesktop.org/xorg/font/adobe-utopia-100dpi/-/blob/master/COPYING?ref_type=heads": "Adobe-Utopia", + "https://gitlab.freedesktop.org/xorg/font/alias/-/blob/master/COPYING": "Cronyx", + "https://gitlab.freedesktop.org/xorg/font/bh-100dpi/-/blob/master/COPYING?ref_type=heads": "Lucida-Bitmap-Fonts", + "https://gitlab.freedesktop.org/xorg/font/cronyx-cyrillic/-/blob/master/COPYING": "Cronyx", + "https://gitlab.freedesktop.org/xorg/font/misc-cyrillic/-/blob/master/COPYING": "Cronyx", + "https://gitlab.freedesktop.org/xorg/font/screen-cyrillic/-/blob/master/COPYING": "Cronyx", + "https://gitlab.freedesktop.org/xorg/lib/libxext/-/blob/master/COPYING?ref_type=heads#L153-162": "HPND-doc-sell", + "https://gitlab.freedesktop.org/xorg/lib/libxext/-/blob/master/COPYING?ref_type=heads#L185-197": "HPND-doc", + "https://gitlab.freedesktop.org/xorg/lib/libxtst/-/blob/master/COPYING?ref_type=heads#L108-117": "HPND-doc-sell", + "https://gitlab.freedesktop.org/xorg/lib/libxtst/-/blob/master/COPYING?ref_type=heads#L70-77": "HPND-doc", + "https://gitlab.freedesktop.org/xorg/xserver/-/blob/master/COPYING?ref_type=heads#L1781": "HPND-sell-MIT-disclaimer-xserver", + "https://gitlab.freedesktop.org/xorg/xserver/-/blob/master/COPYING?ref_type=heads#L239": "DEC-3-Clause", + "https://gitlab.freedesktop.org/xorg/xserver/-/blob/master/COPYING?ref_type=heads#L752": "Adobe-Display-PostScript", + "https://gitlab.isc.org/isc-projects/bind9/blob/master/COPYRIGHT#L366": "JPNIC", + "https://gitlab.lrz.de/mmix/mmixware/-/blob/master/boilerplate.w": "MMIXware", + "https://gitlab.syncad.com/hive/dhive/-/blob/master/LICENSE": "BSD-3-Clause-No-Military-License", + "https://graphics.pixar.com/opensubdiv/docs/license.html": "Pixar", + "https://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/f_user/node9.html": "CFITSIO", + "https://heasarc.gsfc.nasa.gov/docs/software/ftools/fv/doc/license.html": "CFITSIO", + "https://helixcommunity.org/content/rpsl": "RPSL-1.0", + "https://hstechdocs.helpsystems.com/manuals/globalscape/archive/cuteftp6/open_ssl_license_agreement.htm": "OpenSSL-standalone", + "https://java.net/projects/javaeetutorial/pages/BerkeleyLicense": "BSD-3-Clause-No-Nuclear-License-2014", + "https://javaee.github.io/glassfish/LICENSE": "CDDL-1.1", + "https://jogamp.org/git/?p=gluegen.git;a=blob_plain;f=LICENSE.txt": "BSD-3-Clause-No-Nuclear-Warranty", + "https://joinup.ec.europa.eu/page/eupl-text-11-12": "EUPL-1.2", + "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/2020-03/EUPL-1.2%20EN.txt": "EUPL-1.2", + "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl1.1.-licence-en_0.pdf": "EUPL-1.1", + "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl_v1.2_en.pdf": "EUPL-1.2", + "https://joinup.ec.europa.eu/sites/default/files/inline-files/EUPL%20v1_2%20EN(1).txt": "EUPL-1.2", + "https://joinup.ec.europa.eu/software/page/eupl/licence-eupl": "EUPL-1.1", + "https://joinup.ec.europa.eu/svn/lesoll/trunk/italc/lib/src/dsa_key.cpp": "SSH-short", + "https://libgd.github.io/manuals/2.3.0/files/license-txt.html": "GD", + "https://library.netapp.com/ecm/ecm_download_file/ECMP1196395": "OpenSSL-standalone", + "https://license.coscl.org.cn/MulanPSL/": "MulanPSL-1.0", + "https://license.coscl.org.cn/MulanPSL2": "MulanPSL-2.0", + "https://lists.gnu.org/archive/html/autoconf/2012-04/msg00061.html": "FSFULLRWD", + "https://mariadb.com/bsl11/": "BUSL-1.1", + "https://matplotlib.org/stable/project/license.html": "PSF-2.0", + "https://metacpan.org/pod/Exporter::Tidy#LICENSE": "any-OSI", + "https://metacpan.org/pod/Net::MQTT::Simple#LICENSE": "any-OSI-perl-modules", + "https://metacpan.org/pod/Qmail::Deliverable::Client#LICENSE": "any-OSI-perl-modules", + "https://metacpan.org/pod/Time::ParseDate#LICENSE": "TPDL", + "https://metacpan.org/release/DPARIS/Crypt-Blowfish-2.14/source/COPYRIGHT#L7": "BSD-Systemics-W3Works", + "https://metacpan.org/release/DPARIS/Crypt-DES-2.07/source/COPYRIGHT": "BSD-Systemics", + "https://metacpan.org/release/JUERD/Exporter-Tidy-0.09/view/Tidy.pm#LICENSE": "any-OSI-perl-modules", + "https://metacpan.org/release/KNOK/File-MMagic-1.30/source/COPYING#L28": "Spencer-94", + "https://metacpan.org/release/NLNETLABS/Net-DNS-SEC-1.22/source/LICENSE": "HPND-MIT-disclaimer", + "https://metacpan.org/release/RJBS/Text-Soundex-3.05/source/Soundex.pm#L3-11": "Soundex", + "https://metadata.ftp-master.debian.org/changelogs//main/a/arpwatch/arpwatch_2.1a15-7_copyright": "BSD-4-Clause-Shortened", + "https://metadata.ftp-master.debian.org/changelogs//main/x/xzoom/xzoom_0.3-27_copyright": "xzoom", + "https://mirror.las.iastate.edu/tex-archive/graphics/metapost/contrib/macros/slideshow/slideshow.mp": "McPhee-slideshow", + "https://mirrors.ctan.org/macros/latex/contrib/ulem/README": "ulem", + "https://mirrors.ctan.org/macros/latex/contrib/version/version.sty": "magaz", + "https://mirrors.nic.cz/tex-archive/macros/latex/contrib/fwlw/README": "fwlw", + "https://mirrors.nic.cz/tex-archive/macros/latex/contrib/magaz/magaz.tex": "magaz", + "https://open.canada.ca/en/open-government-licence-canada": "OGL-Canada-2.0", + "https://opendatacommons.org/licenses/by/1.0/": "ODC-By-1.0", + "https://opendatacommons.org/licenses/odbl/1-0/": "ODbL-1.0", + "https://opendatacommons.org/licenses/pddl/": "PDDL-1.0", + "https://openlogisticsfoundation.org/licenses/": "OLFL-1.3", + "https://opensource.apple.com/source/JBoss/JBoss-737/jboss-all/jetty/src/main/org/mortbay/util/UnixCrypt.java.auto.html": "UnixCrypt", + "https://opensource.apple.com/source/mDNSResponder/mDNSResponder-320.10/mDNSPosix/nss_ReadMe.txt": "NICTA-1.0", + "https://opensource.org/license/apache-2-0": "Apache-2.0", + "https://opensource.org/license/mit/": "MIT", + "https://opensource.org/license/olfl-1-3/": "OLFL-1.3", + "https://opensource.org/licenses/0BSD": "0BSD", + "https://opensource.org/licenses/AGPL-3.0": "AGPL-3.0-or-later", + "https://opensource.org/licenses/APL-1.0": "APL-1.0", + "https://opensource.org/licenses/Apache-1.1": "Apache-1.1", + "https://opensource.org/licenses/Apache-2.0": "Apache-2.0", + "https://opensource.org/licenses/Artistic-1.0": "Artistic-1.0-cl8", + "https://opensource.org/licenses/BSD-2-Clause": "BSD-2-Clause", + "https://opensource.org/licenses/BSD-3-Clause": "BSD-3-Clause", + "https://opensource.org/licenses/BSDplusPatent": "BSD-2-Clause-Patent", + "https://opensource.org/licenses/BSL-1.0": "BSL-1.0", + "https://opensource.org/licenses/CAL-1.0": "CAL-1.0-Combined-Work-Exception", + "https://opensource.org/licenses/CATOSL-1.1": "CATOSL-1.1", + "https://opensource.org/licenses/CNRI-Python": "CNRI-Python", + "https://opensource.org/licenses/CPAL-1.0": "CPAL-1.0", + "https://opensource.org/licenses/CPL-1.0": "CPL-1.0", + "https://opensource.org/licenses/CUA-OPL-1.0": "CUA-OPL-1.0", + "https://opensource.org/licenses/ECL-1.0": "ECL-1.0", + "https://opensource.org/licenses/ECL-2.0": "ECL-2.0", + "https://opensource.org/licenses/EFL-1.0": "EFL-1.0", + "https://opensource.org/licenses/EFL-2.0": "EFL-2.0", + "https://opensource.org/licenses/EPL-1.0": "EPL-1.0", + "https://opensource.org/licenses/EUDatagrid": "EUDatagrid", + "https://opensource.org/licenses/EUPL-1.1": "EUPL-1.1", + "https://opensource.org/licenses/EUPL-1.2": "EUPL-1.2", + "https://opensource.org/licenses/Entessa": "Entessa", + "https://opensource.org/licenses/Fair": "Fair", + "https://opensource.org/licenses/Frameworx-1.0": "Frameworx-1.0", + "https://opensource.org/licenses/GPL-2.0": "GPL-2.0-or-later", + "https://opensource.org/licenses/GPL-3.0": "GPL-3.0-or-later", + "https://opensource.org/licenses/HPND": "HPND", + "https://opensource.org/licenses/IPA": "IPA", + "https://opensource.org/licenses/IPL-1.0": "IPL-1.0", + "https://opensource.org/licenses/ISC": "ISC", + "https://opensource.org/licenses/Intel": "Intel", + "https://opensource.org/licenses/LGPL-2.1": "LGPL-2.1-or-later", + "https://opensource.org/licenses/LGPL-3.0": "LGPL-3.0-or-later", + "https://opensource.org/licenses/LPL-1.0": "LPL-1.0", + "https://opensource.org/licenses/LPL-1.02": "LPL-1.02", + "https://opensource.org/licenses/LPPL-1.3c": "LPPL-1.3c", + "https://opensource.org/licenses/MPL-1.0": "MPL-1.0", + "https://opensource.org/licenses/MPL-1.1": "MPL-1.1", + "https://opensource.org/licenses/MPL-2.0": "MPL-2.0-no-copyleft-exception", + "https://opensource.org/licenses/MS-PL": "MS-PL", + "https://opensource.org/licenses/MS-RL": "MS-RL", + "https://opensource.org/licenses/MirOS": "MirOS", + "https://opensource.org/licenses/Motosoto": "Motosoto", + "https://opensource.org/licenses/Multics": "Multics", + "https://opensource.org/licenses/NASA-1.3": "NASA-1.3", + "https://opensource.org/licenses/NCSA": "NCSA", + "https://opensource.org/licenses/NGPL": "NGPL", + "https://opensource.org/licenses/NOSL3.0": "NPOSL-3.0", + "https://opensource.org/licenses/NTP": "NTP", + "https://opensource.org/licenses/Naumen": "Naumen", + "https://opensource.org/licenses/OCLC-2.0": "OCLC-2.0", + "https://opensource.org/licenses/OFL-1.1": "OFL-1.1-no-RFN", + "https://opensource.org/licenses/OGTSL": "OGTSL", + "https://opensource.org/licenses/OPL-2.1": "OSET-PL-2.1", + "https://opensource.org/licenses/OSL-1.0": "OSL-1.0", + "https://opensource.org/licenses/OSL-2.1": "OSL-2.1", + "https://opensource.org/licenses/OSL-3.0": "OSL-3.0", + "https://opensource.org/licenses/PHP-3.0": "PHP-3.0", + "https://opensource.org/licenses/PostgreSQL": "PostgreSQL", + "https://opensource.org/licenses/Python-2.0": "Python-2.0", + "https://opensource.org/licenses/QPL-1.0": "QPL-1.0", + "https://opensource.org/licenses/RPL-1.1": "RPL-1.1", + "https://opensource.org/licenses/RPL-1.5": "RPL-1.5", + "https://opensource.org/licenses/RPSL-1.0": "RPSL-1.0", + "https://opensource.org/licenses/RSCPL": "RSCPL", + "https://opensource.org/licenses/SISSL": "SISSL", + "https://opensource.org/licenses/SPL-1.0": "SPL-1.0", + "https://opensource.org/licenses/SimPL-2.0": "SimPL-2.0", + "https://opensource.org/licenses/Sleepycat": "Sleepycat", + "https://opensource.org/licenses/UCL-1.0": "UCL-1.0", + "https://opensource.org/licenses/UPL": "UPL-1.0", + "https://opensource.org/licenses/VSL-1.0": "VSL-1.0", + "https://opensource.org/licenses/W3C": "W3C", + "https://opensource.org/licenses/Watcom-1.0": "Watcom-1.0", + "https://opensource.org/licenses/Xnet": "Xnet", + "https://opensource.org/licenses/ZPL-2.0": "ZPL-2.0", + "https://opensource.org/licenses/Zlib": "Zlib", + "https://opensource.org/licenses/afl-3.0": "AFL-3.0", + "https://opensource.org/licenses/artistic-license-2.0": "Artistic-2.0", + "https://opensource.org/licenses/attribution": "AAL", + "https://opensource.org/licenses/cddl1": "CDDL-1.0", + "https://opensource.org/licenses/nokia": "Nokia", + "https://paritylicense.com/versions/6.0.0.html": "Parity-6.0.0", + "https://paritylicense.com/versions/7.0.0.html": "Parity-7.0.0", + "https://people.freebsd.org/~ivoras/wine/patch-wine-nvidia.sh": "BSD-2-Clause-Views", + "https://people.freebsd.org/~phk/": "Beerware", + "https://people.mpi-inf.mpg.de/~uwe/misc/uw-ttyp0/": "TTYP0", + "https://pirlwww.lpl.arizona.edu/resources/guide/software/PerlTk/Tixlic.html": "MIT-Modern-Variant", + "https://polyformproject.org/licenses/noncommercial/1.0.0": "PolyForm-Noncommercial-1.0.0", + "https://polyformproject.org/licenses/small-business/1.0.0": "PolyForm-Small-Business-1.0.0", + "https://projects.eclipse.org/license/epl-2.0": "EPL-2.0", + "https://ptolemy.berkeley.edu/copyright.htm": "MIT-Modern-Variant", + "https://raw.githubusercontent.com/DISIC/politique-de-contribution-open-source/master/LICENSE": "etalab-2.0", + "https://raw.githubusercontent.com/GNOME/libxml2/4c2e7c651f6c2f0d1a74f350cbda95f7df3e7017/hash.c": "ISC-Veillard", + "https://raw.githubusercontent.com/NTIA/itm/refs/heads/master/LICENSE.md": "NTIA-PD", + "https://raw.githubusercontent.com/NTIA/scos-sensor/refs/heads/master/LICENSE.md": "NTIA-PD", + "https://raw.githubusercontent.com/blackhole89/notekit/master/data/fonts/Charter%20license.txt": "Bitstream-Charter", + "https://romanrm.net/mit-zero": "MIT-0", + "https://slicer.org/LICENSE": "3D-Slicer-1.0", + "https://solderpad.org/licenses/SHL-0.5/": "SHL-0.5", + "https://solderpad.org/licenses/SHL-0.51/": "SHL-0.51", + "https://sourceforge.net/p/ctrio/git/ci/master/tree/README": "ISC-Veillard", + "https://sourceforge.net/p/mcj/xfig/ci/master/tree/src/Makefile.am": "Xfig", + "https://sourceforge.net/p/netpbm/code/HEAD/tree/super_stable/converter/other/pnmtorle.c": "URT-RLE", + "https://sourceforge.net/p/netpbm/code/HEAD/tree/super_stable/converter/other/rletopnm.c": "URT-RLE", + "https://sourceforge.net/p/netpbm/code/HEAD/tree/super_stable/converter/ppm/ppmtompeg/jrevdct.c#l1189": "MPEG-SSG", + "https://sourceforge.net/p/netpbm/code/HEAD/tree/super_stable/editor/pnmstitch.c#l2": "pnmstitch", + "https://sourceforge.net/p/netpbm/code/HEAD/tree/super_stable/netpbm.c#l8": "HPND-Pbmplus", + "https://sourceforge.net/p/sbcl/sbcl/ci/master/tree/src/code/loop.lisp": "LOOP", + "https://sourceforge.net/p/trustedqsl/tqsl/ci/master/tree/LICENSE.txt": "TrustedQSL", + "https://sourceforge.net/p/xmedcon/code/ci/master/tree/libs/dicom/README": "OFFIS", + "https://sourceforge.net/p/xmedcon/code/ci/master/tree/libs/ljpg/": "IJG-short", + "https://sourceforge.net/projects/sevenzip/files/LZMA%20SDK/": "LZMA-SDK-9.22", + "https://sources.debian.org/copyright/license/debianutils/4.11.2/": "SMAIL-GPL", + "https://sources.debian.org/src/openmpi/4.1.0-10/ompi/debuggers/msgq_interface.h/?hl=19#L19": "mpi-permissive", + "https://sourceware.org/bzip2/1.0.5/bzip2-manual-1.0.5.html": "bzip2-1.0.6", + "https://sourceware.org/cgit/binutils-gdb/tree/include/coff/sym.h#n11": "MIPS", + "https://sourceware.org/cgit/binutils-gdb/tree/include/coff/symconst.h#n11": "ThirdEye", + "https://sourceware.org/cgit/valgrind/tree/mpi/libmpiwrap.c": "bzip2-1.0.6", + "https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=libiberty/strcasecmp.c;h=131d81c2ce7881fa48c363dc5bf5fb302c61ce0b;hb=HEAD": "BSD-4.3RENO", + "https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=readline/readline/support/wcwidth.c;h=0f5ec995796f4813abbcf4972aec0378ab74722a;hb=HEAD#l55": "HPND-Markus-Kuhn", + "https://sourceware.org/git/?p=bzip2.git;a=blob;f=LICENSE;hb=bzip2-1.0.6": "bzip2-1.0.6", + "https://sourceware.org/git/?p=glibc.git;a=blob;f=LICENSES;h=530893b1dc9ea00755603c68fb36bd4fc38a7be8;hb=HEAD#l207": "Inner-Net-2.0", + "https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=newlib/libc/machine/hppa/memchr.S;h=1cca3e5e8867aa4bffef1f75a5c1bba25c0c441e;hb=HEAD#l2": "HP-1986", + "https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=newlib/libc/machine/i960/memcpy.S;hb=HEAD": "HPND-Intel", + "https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=newlib/libc/misc/fini.c;hb=HEAD": "HPND-merchantability-variant", + "https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=newlib/libc/stdlib/mprec.h;hb=HEAD": "dtoa", + "https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=newlib/libc/string/strsignal.c;hb=HEAD#l35": "OAR", + "https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=newlib/libc/sys/a29khif/_close.S;h=04f52ae00de1dafbd9055ad8d73c5c697a3aae7f;hb=HEAD": "AMD-newlib", + "https://sqlite.org/src/artifact/df5091916dbb40e6": "blessing", + "https://svnweb.freebsd.org/base/head/include/ifaddrs.h?revision=326823": "BSD-1-Clause", + "https://tahoe-lafs.org/trac/tahoe-lafs/browser/trunk/COPYING.TGPPL.rst": "TGPPL-1.0", + "https://ubuntu.com/legal/font-licence": "Ubuntu-font-1.0", + "https://unlicense.org/": "Unlicense", + "https://web.archive.org/web/20060319014854/http://info.borland.com/devsupport/interbase/opensource/IPL.html": "Interbase-1.0", + "https://web.archive.org/web/20080207013128/http://www.gnome.org/fonts/": "Bitstream-Vera", + "https://web.archive.org/web/20120101081418/http://rosenlaw.com:80/OSL3.0.htm": "OSL-3.0", + "https://web.archive.org/web/20130517195954/http://www.zend.com/license/2_00.txt": "Zend-2.0", + "https://web.archive.org/web/20150926120323/http://fairlicense.org/": "Fair", + "https://web.archive.org/web/20151224134844/http://unicode.org/copyright.html": "Unicode-DFS-2015", + "https://web.archive.org/web/20160322142305/https://www.sendmail.com/pdfs/open_source/sendmail_license.pdf": "Sendmail", + "https://web.archive.org/web/20160330173339/https://swarm.workshop.perforce.com/files/guest/perforce_software/jam/src/README": "Jam", + "https://web.archive.org/web/20181003101040/https://www.proofpoint.com/sites/default/files/sendmail-license.pdf": "Sendmail-8.23", + "https://web.mit.edu/kerberos/krb5-1.21/doc/mitK5license.html": "OpenVision", + "https://wiki.p2pfoundation.net/Peer_Production_License": "PPL", + "https://www.7-zip.org/sdk.html": "LZMA-SDK-9.22", + "https://www.apache.org/licenses/LICENSE-2.0": "Apache-2.0", + "https://www.boost.org/doc/libs/1_35_0/doc/html/jam.html": "Jam", + "https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c": "HPND-Markus-Kuhn", + "https://www.cs.auckland.ac.nz/~pgut001/dumpasn1.c": "Gutmann", + "https://www.cs.cmu.edu/~410/licenses.html": "CMU-Mach", + "https://www.ctan.org/license/opl": "OPUBL-1.0", + "https://www.cve.org/Legal/TermsOfUse": "cve-tou", + "https://www.debian.org/opl": "OPUBL-1.0", + "https://www.dre.vanderbilt.edu/~schmidt/ACE-copying.html": "DOC", + "https://www.eclipse.org/legal/epl-2.0": "EPL-2.0", + "https://www.eclipse.org/legal/epl-v20.html": "EPL-2.0", + "https://www.eclipse.org/org/documents/edl-v10.php": "BSD-3-Clause", + "https://www.elastic.co/licensing/elastic-license": "Elastic-2.0", + "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-forte-liliq-r-v1-1/": "LiLiQ-Rplus-1.1", + "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-liliq-r-v1-1/": "LiLiQ-R-1.1", + "https://www.freebsd.org/copyright/freebsd-doc-license/": "FreeBSD-DOC", + "https://www.gnu.org/licenses/agpl.txt": "AGPL-3.0-or-later", + "https://www.gnu.org/licenses/fdl-1.3.txt": "GFDL-1.3-or-later", + "https://www.gnu.org/licenses/gpl-3.0-standalone.html": "GPL-3.0-or-later", + "https://www.gnu.org/licenses/lgpl+gpl-3.0.txt": "LGPL-3.0-or-later", + "https://www.gnu.org/licenses/lgpl-3.0-standalone.html": "LGPL-3.0-or-later", + "https://www.gnu.org/licenses/license-list.html#ACDL": "CDL-1.0", + "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt": "GFDL-1.1-or-later", + "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt": "GFDL-1.2-or-later", + "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html": "GPL-1.0-or-later", + "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html": "GPL-2.0-or-later", + "https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt": "GPL-2.0-only", + "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html": "LGPL-2.0-or-later", + "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html": "LGPL-2.1-or-later", + "https://www.gnu.org/prep/maintain/html_node/License-Notices-for-Other-Files.html": "FSFAP", + "https://www.govdata.de/dl-de/by-2-0": "DL-DE-BY-2.0", + "https://www.govdata.de/dl-de/zero-2-0": "DL-DE-ZERO-2.0", + "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl": "D-FSL-1.0", + "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_de.txt/at_download/file": "D-FSL-1.0", + "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_en.txt/at_download/file": "D-FSL-1.0", + "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/deutsche-freie-software-lizenz": "D-FSL-1.0", + "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/german-free-software-license": "D-FSL-1.0", + "https://www.iec.ch/CCv1": "IEC-Code-Components-EULA", + "https://www.iec.ch/copyright": "IEC-Code-Components-EULA", + "https://www.iec.ch/webstore/custserv/pdf/CC-EULA.pdf": "IEC-Code-Components-EULA", + "https://www.ietf.org/rfc/rfc1952.txt": "LPD-document", + "https://www.inet.no/dante/LICENSE": "BSD-Inferno-Nettverk", + "https://www.isc.org/downloads/software-support-policy/isc-license/": "ISC", + "https://www.isc.org/licenses/": "ISC", + "https://www.jpl.nasa.gov/jpl-image-use-policy": "JPL-image", + "https://www.kermitproject.org/ck90.html#source": "HPND-export-US", + "https://www.kernel.org/doc/man-pages/licenses.html": "Linux-man-pages-copyleft", + "https://www.mail-archive.com/debian-bugs-rc@lists.debian.org/msg11494.html": "Symlinks", + "https://www.mcs.anl.gov/research/projects/openpbs/PBS_License.txt": "OpenPBS-2.3", + "https://www.mongodb.com/licensing/server-side-public-license": "SSPL-1.0", + "https://www.mozilla.org/MPL/2.0/": "MPL-2.0-no-copyleft-exception", + "https://www.mssl.ucl.ac.uk/~mcrw/src/20050920/proto.h": "Cornell-Lossless-JPEG", + "https://www.ogc.org/ogc/software/1.0": "OGC-1.0", + "https://www.ohwr.org/project/cernohl/wikis/Documents/CERN-OHL-version-2": "CERN-OHL-W-2.0", + "https://www.ohwr.org/project/licenses/wikis/cern-ohl-v1.1": "CERN-OHL-1.1", + "https://www.ohwr.org/project/licenses/wikis/cern-ohl-v1.2": "CERN-OHL-1.2", + "https://www.open-mpi.org/community/license.php": "BSD-3-Clause-Open-MPI", + "https://www.openhub.net/licenses/mslpl": "MS-LPL", + "https://www.opensource.org/licenses/EPL-2.0": "EPL-2.0", + "https://www.parliament.uk/site-information/copyright-parliament/open-parliament-licence/": "OPL-UK-3.0", + "https://www.perlfoundation.org/artistic-license-20.html": "Artistic-2.0", + "https://www.proofpoint.com/sites/default/files/sendmail-license.pdf": "Sendmail-8.23", + "https://www.python.org/download/releases/2.0.1/license/": "Python-2.0.1", + "https://www.ruby-lang.org/en/about/license.txt": "Ruby", + "https://www.smlnj.org/license.html": "SMLNJ", + "https://www.sqlite.org/src/artifact/e33a4df7e32d742a?ln=4-9": "blessing", + "https://www.tapr.org/OHL": "TAPR-OHL-1.0", + "https://www.tq-group.com/filedownloads/files/software-license-conditions/OriginalSSLeay/OriginalSSLeay.pdf": "SSLeay-standalone", + "https://www.unicode.org/license.txt": "Unicode-DFS-2016", + "https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document": "W3C-20150513", + "https://www.w3.org/copyright/software-license-2015/": "W3C-20150513", + "https://www.w3.org/copyright/software-license-2023/": "W3C-20150513", +} diff --git a/internal/spdxlicense/license_url_test.go b/internal/spdxlicense/license_url_test.go new file mode 100644 index 00000000000..be84e88f38b --- /dev/null +++ b/internal/spdxlicense/license_url_test.go @@ -0,0 +1,97 @@ +package spdxlicense + +import ( + "testing" +) + +func TestLicenseByURL(t *testing.T) { + tests := []struct { + name string + url string + wantID string + wantFound bool + }{ + { + name: "MIT license URL (https)", + url: "https://opensource.org/license/mit/", + wantID: "MIT", + wantFound: true, + }, + { + name: "MIT license URL (http)", + url: "http://opensource.org/licenses/MIT", + wantID: "MIT", + wantFound: true, + }, + { + name: "Apache 2.0 license URL", + url: "https://www.apache.org/licenses/LICENSE-2.0", + wantID: "Apache-2.0", + wantFound: true, + }, + { + name: "GPL 3.0 or later URL", + url: "https://www.gnu.org/licenses/gpl-3.0-standalone.html", + wantID: "GPL-3.0-or-later", + wantFound: true, + }, + { + name: "BSD 3-Clause URL", + url: "https://opensource.org/licenses/BSD-3-Clause", + wantID: "BSD-3-Clause", + wantFound: true, + }, + { + name: "URL with trailing whitespace", + url: " http://opensource.org/licenses/MIT ", + wantID: "MIT", + wantFound: true, + }, + { + name: "Unknown URL", + url: "https://example.com/unknown-license", + wantID: "", + wantFound: false, + }, + { + name: "Empty URL", + url: "", + wantID: "", + wantFound: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + info, found := LicenseByURL(tt.url) + if found != tt.wantFound { + t.Errorf("LicenseByURL() found = %v, want %v", found, tt.wantFound) + } + if found { + if info.ID != tt.wantID { + t.Errorf("LicenseByURL() ID = %v, want %v", info.ID, tt.wantID) + } + } + }) + } +} + +func TestLicenseByURL_DeprecatedLicenses(t *testing.T) { + // Test that deprecated license URLs map to their replacement licenses + // For example, GPL-2.0+ should map to GPL-2.0-or-later + + // This test needs actual URLs from deprecated licenses + // We can verify by checking if a deprecated license URL maps to a non-deprecated ID + url := "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html" + info, found := LicenseByURL(url) + + if found { + // Check that we got a valid non-deprecated license ID + if info.ID == "" { + t.Error("Got empty license ID for deprecated license URL") + } + // The ID should be the replacement (GPL-2.0-only or GPL-2.0-or-later) + // depending on the URL + t.Logf("Deprecated license URL mapped to: ID=%s", info.ID) + } +} diff --git a/internal/task/feature_detection.go b/internal/task/feature_detection.go new file mode 100644 index 00000000000..563165582ec --- /dev/null +++ b/internal/task/feature_detection.go @@ -0,0 +1,7 @@ +package task + +import "github.com/anchore/syft/internal/os" + +func NewOSFeatureDetectionTask() Task { + return NewTask("os-feature-detection", os.DetectFeatures) +} diff --git a/internal/task/package_tasks.go b/internal/task/package_tasks.go index e350e912cbc..bd7e4bce591 100644 --- a/internal/task/package_tasks.go +++ b/internal/task/package_tasks.go @@ -7,6 +7,7 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/arch" "github.com/anchore/syft/syft/pkg/cataloger/binary" bitnamiSbomCataloger "github.com/anchore/syft/syft/pkg/cataloger/bitnami" + "github.com/anchore/syft/syft/pkg/cataloger/conda" "github.com/anchore/syft/syft/pkg/cataloger/cpp" "github.com/anchore/syft/syft/pkg/cataloger/dart" "github.com/anchore/syft/syft/pkg/cataloger/debian" @@ -31,6 +32,7 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/ruby" "github.com/anchore/syft/syft/pkg/cataloger/rust" sbomCataloger "github.com/anchore/syft/syft/pkg/cataloger/sbom" + "github.com/anchore/syft/syft/pkg/cataloger/snap" "github.com/anchore/syft/syft/pkg/cataloger/swift" "github.com/anchore/syft/syft/pkg/cataloger/swipl" "github.com/anchore/syft/syft/pkg/cataloger/terraform" @@ -171,6 +173,8 @@ func DefaultPackageTaskFactories() Factories { newSimplePackageTaskFactory(wordpress.NewWordpressPluginCataloger, pkgcataloging.DirectoryTag, pkgcataloging.ImageTag, "wordpress"), newSimplePackageTaskFactory(terraform.NewLockCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, "terraform"), newSimplePackageTaskFactory(homebrew.NewCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "homebrew"), + newSimplePackageTaskFactory(conda.NewCondaMetaCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.PackageTag, "conda"), + newSimplePackageTaskFactory(snap.NewCataloger, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "snap"), // deprecated catalogers //////////////////////////////////////// // these are catalogers that should not be selectable other than specific inclusion via name or "deprecated" tag (to remain backwards compatible) diff --git a/schema/cyclonedx/README.md b/schema/cyclonedx/README.md index 08f16ad52cd..a5f212b39a5 100644 --- a/schema/cyclonedx/README.md +++ b/schema/cyclonedx/README.md @@ -13,6 +13,6 @@ prior spec version (e.g. if updating to 1.7, compare the files in this directory equivalents). One can also update the schemas and observe the errors in order to make the necessary updates. -At the time of writing, the cyclonedx.xsd needed modifications to link to the local spdx.xsd, -and also to changes the minOccurs for a license tag to 0. (The json schema does not require +At the time of writing, the cyclonedx.xsd needed modifications to link to the local spdx.xsd, +and also to change the minOccurs for a license tag to 0. (The json schema does not require modification for the generated file to lint properly, but can simply be copy/pasted). diff --git a/schema/cyclonedx/spdx.xsd b/schema/cyclonedx/spdx.xsd index a339a085759..6e90a9e432c 100644 --- a/schema/cyclonedx/spdx.xsd +++ b/schema/cyclonedx/spdx.xsd @@ -2,7 +2,7 @@ + version="1.0-3.26.0"> @@ -162,6 +162,11 @@ Any OSI License + + + Any OSI License - Perl Modules + + Apache License 1.0 @@ -307,6 +312,11 @@ Boehm-Demers-Weiser GC License + + + Boehm-Demers-Weiser GC License (without fee) + + Borceux license @@ -812,6 +822,16 @@ Creative Commons Public Domain Dedication and Certification + + + Creative Commons Public Domain Mark 1.0 Universal + + + + + Creative Commons Share Alike 1.0 Generic + + Creative Commons Zero v1.0 Universal @@ -1062,6 +1082,21 @@ DOC License + + + DocBook Schema License + + + + + DocBook Stylesheet License + + + + + DocBook XML License + + Dotseqn License @@ -1267,6 +1302,11 @@ GD License + + + Generic XTS License + + GNU Free Documentation License v1.1 @@ -1527,6 +1567,11 @@ hdparm License + + + HIDAPI License + + Hippocratic License 2.1 @@ -1617,6 +1662,11 @@ Historical Permission Notice and Disclaimer with MIT disclaimer + + + Historical Permission Notice and Disclaimer - Netrek variant + + Historical Permission Notice and Disclaimer - Pbmplus variant @@ -1712,6 +1762,11 @@ Inner Net License v2.0 + + + Inno Setup License + + Intel Open Source License @@ -2052,6 +2107,11 @@ Minpack License + + + MIPS License + + The MirOS Licence @@ -2072,6 +2132,11 @@ Enlightenment License (e16) + + + MIT Click License + + CMU License @@ -2772,6 +2837,11 @@ Ruby License + + + Ruby pty extension license + + Sax Public Domain Notice @@ -2807,6 +2877,11 @@ Sendmail License 8.23 + + + Sendmail Open Source License v1.1 + + SGI Free Software License B v1.0 @@ -2867,6 +2942,11 @@ Sleepycat License + + + SMAIL General Public License + + Standard ML of New Jersey License @@ -3007,6 +3087,11 @@ Transitive Grace Period Public Licence 1.0 + + + ThirdEye License + + threeparttable License @@ -3037,6 +3122,11 @@ THOR Public License 1.0 + + + TrustedQSL License + + Text-Tabs+Wrap License @@ -3057,6 +3147,11 @@ Technische Universitaet Berlin License 2.0 + + + Ubuntu Font Licence v1.0 + + UCAR License @@ -3172,6 +3267,11 @@ Do What The F*ck You Want To Public License + + + WWL License + + wxWindows Library License @@ -3187,6 +3287,11 @@ X11 License Distribution Modification Variant + + + X11 swapped final paragraphs + + Xdebug License v 1.03 @@ -3358,6 +3463,11 @@ Bootloader Distribution Exception + + + CGAL Linking Exception + + Classpath exception 2.0 @@ -3383,6 +3493,11 @@ eCos exception 2.0 + + + Erlang/OTP Linking Exception + + Fawkes Runtime Exception @@ -3425,7 +3540,7 @@ - Gmsh exception> + Gmsh exception @@ -3448,6 +3563,11 @@ GNU JavaMail exception + + + GPL-3.0 389 DS Base Exception + + GPL-3.0 Interface Exception @@ -3478,11 +3598,21 @@ GStreamer Exception (2008) + + + harbour exception + + i2p GPL+Java Exception + + + Independent Module Linking exception + + KiCad Libraries Exception @@ -3528,6 +3658,11 @@ Macros and Inline Functions Exception + + + mxml Exception + + Nokia Qt LGPL exception 1.1 @@ -3583,6 +3718,11 @@ Qwt exception 1.0 + + + Romic Exception + + RRDtool FLOSS exception 2.0 diff --git a/schema/json/schema-16.0.35.json b/schema/json/schema-16.0.35.json new file mode 100644 index 00000000000..a6832043869 --- /dev/null +++ b/schema/json/schema-16.0.35.json @@ -0,0 +1,3104 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "anchore.io/schema/syft/json/16.0.35/document", + "$ref": "#/$defs/Document", + "$defs": { + "AlpmDbEntry": { + "properties": { + "basepackage": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "packager": { + "type": "string" + }, + "url": { + "type": "string" + }, + "validation": { + "type": "string" + }, + "reason": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "backup": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "basepackage", + "package", + "version", + "description", + "architecture", + "size", + "packager", + "url", + "validation", + "reason", + "files", + "backup" + ] + }, + "AlpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "type": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "gid": { + "type": "string" + }, + "time": { + "type": "string", + "format": "date-time" + }, + "size": { + "type": "string" + }, + "link": { + "type": "string" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object" + }, + "ApkDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "originPackage": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "version": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "installedSize": { + "type": "integer" + }, + "pullDependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "pullChecksum": { + "type": "string" + }, + "gitCommitOfApkPort": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/ApkFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "originPackage", + "maintainer", + "version", + "architecture", + "url", + "description", + "size", + "installedSize", + "pullDependencies", + "provides", + "pullChecksum", + "gitCommitOfApkPort", + "files" + ] + }, + "ApkFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "ownerUid": { + "type": "string" + }, + "ownerGid": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "BinarySignature": { + "properties": { + "matches": { + "items": { + "$ref": "#/$defs/ClassifierMatch" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "matches" + ] + }, + "BitnamiSbomEntry": { + "properties": { + "name": { + "type": "string" + }, + "arch": { + "type": "string" + }, + "distro": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "arch", + "distro", + "revision", + "version", + "path", + "files" + ] + }, + "CConanFileEntry": { + "properties": { + "ref": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanInfoEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "build_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "py_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "options": { + "$ref": "#/$defs/KeyValues" + }, + "path": { + "type": "string" + }, + "context": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockV2Entry": { + "properties": { + "ref": { + "type": "string" + }, + "packageID": { + "type": "string" + }, + "username": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "recipeRevision": { + "type": "string" + }, + "packageRevision": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CPE": { + "properties": { + "cpe": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "cpe" + ] + }, + "ClassifierMatch": { + "properties": { + "classifier": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Location" + } + }, + "type": "object", + "required": [ + "classifier", + "location" + ] + }, + "CocoaPodfileLockEntry": { + "properties": { + "checksum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "checksum" + ] + }, + "Coordinates": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "DartPubspec": { + "properties": { + "homepage": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "documentation": { + "type": "string" + }, + "publish_to": { + "type": "string" + }, + "environment": { + "$ref": "#/$defs/DartPubspecEnvironment" + }, + "platforms": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ignored_advisories": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "DartPubspecEnvironment": { + "properties": { + "sdk": { + "type": "string" + }, + "flutter": { + "type": "string" + } + }, + "type": "object" + }, + "DartPubspecLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hosted_url": { + "type": "string" + }, + "vcs_url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Descriptor": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "configuration": true + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Digest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "Document": { + "properties": { + "artifacts": { + "items": { + "$ref": "#/$defs/Package" + }, + "type": "array" + }, + "artifactRelationships": { + "items": { + "$ref": "#/$defs/Relationship" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/File" + }, + "type": "array" + }, + "source": { + "$ref": "#/$defs/Source" + }, + "distro": { + "$ref": "#/$defs/LinuxRelease" + }, + "descriptor": { + "$ref": "#/$defs/Descriptor" + }, + "schema": { + "$ref": "#/$defs/Schema" + } + }, + "type": "object", + "required": [ + "artifacts", + "artifactRelationships", + "source", + "distro", + "descriptor", + "schema" + ] + }, + "DotnetDepsEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "sha512": { + "type": "string" + }, + "hashPath": { + "type": "string" + }, + "executables": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "path", + "sha512", + "hashPath" + ] + }, + "DotnetPackagesLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "contentHash": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "contentHash", + "type" + ] + }, + "DotnetPortableExecutableEntry": { + "properties": { + "assemblyVersion": { + "type": "string" + }, + "legalCopyright": { + "type": "string" + }, + "comments": { + "type": "string" + }, + "internalName": { + "type": "string" + }, + "companyName": { + "type": "string" + }, + "productName": { + "type": "string" + }, + "productVersion": { + "type": "string" + } + }, + "type": "object", + "required": [ + "assemblyVersion", + "legalCopyright", + "companyName", + "productName", + "productVersion" + ] + }, + "DpkgArchiveEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "isConfigFile": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "path", + "isConfigFile" + ] + }, + "ELFSecurityFeatures": { + "properties": { + "symbolTableStripped": { + "type": "boolean" + }, + "stackCanary": { + "type": "boolean" + }, + "nx": { + "type": "boolean" + }, + "relRO": { + "type": "string" + }, + "pie": { + "type": "boolean" + }, + "dso": { + "type": "boolean" + }, + "safeStack": { + "type": "boolean" + }, + "cfi": { + "type": "boolean" + }, + "fortify": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "symbolTableStripped", + "nx", + "relRO", + "pie", + "dso" + ] + }, + "ElfBinaryPackageNoteJsonPayload": { + "properties": { + "type": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "osCPE": { + "type": "string" + }, + "os": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "system": { + "type": "string" + }, + "vendor": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "commit": { + "type": "string" + } + }, + "type": "object" + }, + "ElixirMixLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "ErlangRebarLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "Executable": { + "properties": { + "format": { + "type": "string" + }, + "hasExports": { + "type": "boolean" + }, + "hasEntrypoint": { + "type": "boolean" + }, + "importedLibraries": { + "items": { + "type": "string" + }, + "type": "array" + }, + "elfSecurityFeatures": { + "$ref": "#/$defs/ELFSecurityFeatures" + } + }, + "type": "object", + "required": [ + "format", + "hasExports", + "hasEntrypoint", + "importedLibraries" + ] + }, + "File": { + "properties": { + "id": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Coordinates" + }, + "metadata": { + "$ref": "#/$defs/FileMetadataEntry" + }, + "contents": { + "type": "string" + }, + "digests": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/FileLicense" + }, + "type": "array" + }, + "executable": { + "$ref": "#/$defs/Executable" + }, + "unknowns": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "id", + "location" + ] + }, + "FileLicense": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "evidence": { + "$ref": "#/$defs/FileLicenseEvidence" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type" + ] + }, + "FileLicenseEvidence": { + "properties": { + "confidence": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "extent": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "confidence", + "offset", + "extent" + ] + }, + "FileMetadataEntry": { + "properties": { + "mode": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "userID": { + "type": "integer" + }, + "groupID": { + "type": "integer" + }, + "mimeType": { + "type": "string" + }, + "size": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "mode", + "type", + "userID", + "groupID", + "mimeType", + "size" + ] + }, + "GithubActionsUseStatement": { + "properties": { + "value": { + "type": "string" + }, + "comment": { + "type": "string" + } + }, + "type": "object", + "required": [ + "value" + ] + }, + "GoModuleBuildinfoEntry": { + "properties": { + "goBuildSettings": { + "$ref": "#/$defs/KeyValues" + }, + "goCompiledVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "h1Digest": { + "type": "string" + }, + "mainModule": { + "type": "string" + }, + "goCryptoSettings": { + "items": { + "type": "string" + }, + "type": "array" + }, + "goExperiments": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "goCompiledVersion", + "architecture" + ] + }, + "GoModuleEntry": { + "properties": { + "h1Digest": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackEntry": { + "properties": { + "pkgHash": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackLockEntry": { + "properties": { + "pkgHash": { + "type": "string" + }, + "snapshotURL": { + "type": "string" + } + }, + "type": "object" + }, + "HomebrewFormula": { + "properties": { + "tap": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "IDLikes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "JavaArchive": { + "properties": { + "virtualPath": { + "type": "string" + }, + "manifest": { + "$ref": "#/$defs/JavaManifest" + }, + "pomProperties": { + "$ref": "#/$defs/JavaPomProperties" + }, + "pomProject": { + "$ref": "#/$defs/JavaPomProject" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "virtualPath" + ] + }, + "JavaJvmInstallation": { + "properties": { + "release": { + "$ref": "#/$defs/JavaVMRelease" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "release", + "files" + ] + }, + "JavaManifest": { + "properties": { + "main": { + "$ref": "#/$defs/KeyValues" + }, + "sections": { + "items": { + "$ref": "#/$defs/KeyValues" + }, + "type": "array" + } + }, + "type": "object" + }, + "JavaPomParent": { + "properties": { + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object", + "required": [ + "groupId", + "artifactId", + "version" + ] + }, + "JavaPomProject": { + "properties": { + "path": { + "type": "string" + }, + "parent": { + "$ref": "#/$defs/JavaPomParent" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "groupId", + "artifactId", + "version", + "name" + ] + }, + "JavaPomProperties": { + "properties": { + "path": { + "type": "string" + }, + "name": { + "type": "string" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "extraFields": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "name", + "groupId", + "artifactId", + "version" + ] + }, + "JavaVMRelease": { + "properties": { + "implementor": { + "type": "string" + }, + "implementorVersion": { + "type": "string" + }, + "javaRuntimeVersion": { + "type": "string" + }, + "javaVersion": { + "type": "string" + }, + "javaVersionDate": { + "type": "string" + }, + "libc": { + "type": "string" + }, + "modules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "osArch": { + "type": "string" + }, + "osName": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "source": { + "type": "string" + }, + "buildSource": { + "type": "string" + }, + "buildSourceRepo": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "fullVersion": { + "type": "string" + }, + "semanticVersion": { + "type": "string" + }, + "buildInfo": { + "type": "string" + }, + "jvmVariant": { + "type": "string" + }, + "jvmVersion": { + "type": "string" + }, + "imageType": { + "type": "string" + }, + "buildType": { + "type": "string" + } + }, + "type": "object" + }, + "JavascriptNpmPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "private": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "homepage", + "description", + "url", + "private" + ] + }, + "JavascriptNpmPackageLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "JavascriptYarnLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "KeyValue": { + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "key", + "value" + ] + }, + "KeyValues": { + "items": { + "$ref": "#/$defs/KeyValue" + }, + "type": "array" + }, + "License": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "urls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "contents": { + "type": "string" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type", + "urls", + "locations" + ] + }, + "LinuxKernelArchive": { + "properties": { + "name": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "version": { + "type": "string" + }, + "extendedVersion": { + "type": "string" + }, + "buildTime": { + "type": "string" + }, + "author": { + "type": "string" + }, + "format": { + "type": "string" + }, + "rwRootFS": { + "type": "boolean" + }, + "swapDevice": { + "type": "integer" + }, + "rootDevice": { + "type": "integer" + }, + "videoMode": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "architecture", + "version" + ] + }, + "LinuxKernelModule": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "path": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "license": { + "type": "string" + }, + "kernelVersion": { + "type": "string" + }, + "versionMagic": { + "type": "string" + }, + "parameters": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/LinuxKernelModuleParameter" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "LinuxKernelModuleParameter": { + "properties": { + "type": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "LinuxRelease": { + "properties": { + "prettyName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idLike": { + "$ref": "#/$defs/IDLikes" + }, + "version": { + "type": "string" + }, + "versionID": { + "type": "string" + }, + "versionCodename": { + "type": "string" + }, + "buildID": { + "type": "string" + }, + "imageID": { + "type": "string" + }, + "imageVersion": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "variantID": { + "type": "string" + }, + "homeURL": { + "type": "string" + }, + "supportURL": { + "type": "string" + }, + "bugReportURL": { + "type": "string" + }, + "privacyPolicyURL": { + "type": "string" + }, + "cpeName": { + "type": "string" + }, + "supportEnd": { + "type": "string" + }, + "extendedSupport": { + "type": "boolean" + } + }, + "type": "object" + }, + "Location": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + }, + "accessPath": { + "type": "string" + }, + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "accessPath" + ] + }, + "LuarocksPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "dependencies": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "license", + "homepage", + "description", + "url", + "dependencies" + ] + }, + "MicrosoftKbPatch": { + "properties": { + "product_id": { + "type": "string" + }, + "kb": { + "type": "string" + } + }, + "type": "object", + "required": [ + "product_id", + "kb" + ] + }, + "NixDerivation": { + "properties": { + "path": { + "type": "string" + }, + "system": { + "type": "string" + }, + "inputDerivations": { + "items": { + "$ref": "#/$defs/NixDerivationReference" + }, + "type": "array" + }, + "inputSources": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "NixDerivationReference": { + "properties": { + "path": { + "type": "string" + }, + "outputs": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "NixStoreEntry": { + "properties": { + "path": { + "type": "string" + }, + "output": { + "type": "string" + }, + "outputHash": { + "type": "string" + }, + "derivation": { + "$ref": "#/$defs/NixDerivation" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "outputHash" + ] + }, + "OpamPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "url": { + "type": "string" + }, + "checksum": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "licenses", + "url", + "checksum", + "homepage", + "dependencies" + ] + }, + "Package": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "foundBy": { + "type": "string" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "licenses": { + "$ref": "#/$defs/licenses" + }, + "language": { + "type": "string" + }, + "cpes": { + "$ref": "#/$defs/cpes" + }, + "purl": { + "type": "string" + }, + "metadataType": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/AlpmDbEntry" + }, + { + "$ref": "#/$defs/ApkDbEntry" + }, + { + "$ref": "#/$defs/BinarySignature" + }, + { + "$ref": "#/$defs/BitnamiSbomEntry" + }, + { + "$ref": "#/$defs/CConanFileEntry" + }, + { + "$ref": "#/$defs/CConanInfoEntry" + }, + { + "$ref": "#/$defs/CConanLockEntry" + }, + { + "$ref": "#/$defs/CConanLockV2Entry" + }, + { + "$ref": "#/$defs/CocoaPodfileLockEntry" + }, + { + "$ref": "#/$defs/DartPubspec" + }, + { + "$ref": "#/$defs/DartPubspecLockEntry" + }, + { + "$ref": "#/$defs/DotnetDepsEntry" + }, + { + "$ref": "#/$defs/DotnetPackagesLockEntry" + }, + { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + }, + { + "$ref": "#/$defs/DpkgArchiveEntry" + }, + { + "$ref": "#/$defs/DpkgDbEntry" + }, + { + "$ref": "#/$defs/ElfBinaryPackageNoteJsonPayload" + }, + { + "$ref": "#/$defs/ElixirMixLockEntry" + }, + { + "$ref": "#/$defs/ErlangRebarLockEntry" + }, + { + "$ref": "#/$defs/GithubActionsUseStatement" + }, + { + "$ref": "#/$defs/GoModuleBuildinfoEntry" + }, + { + "$ref": "#/$defs/GoModuleEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackLockEntry" + }, + { + "$ref": "#/$defs/HomebrewFormula" + }, + { + "$ref": "#/$defs/JavaArchive" + }, + { + "$ref": "#/$defs/JavaJvmInstallation" + }, + { + "$ref": "#/$defs/JavascriptNpmPackage" + }, + { + "$ref": "#/$defs/JavascriptNpmPackageLockEntry" + }, + { + "$ref": "#/$defs/JavascriptYarnLockEntry" + }, + { + "$ref": "#/$defs/LinuxKernelArchive" + }, + { + "$ref": "#/$defs/LinuxKernelModule" + }, + { + "$ref": "#/$defs/LuarocksPackage" + }, + { + "$ref": "#/$defs/MicrosoftKbPatch" + }, + { + "$ref": "#/$defs/NixStoreEntry" + }, + { + "$ref": "#/$defs/OpamPackage" + }, + { + "$ref": "#/$defs/PeBinary" + }, + { + "$ref": "#/$defs/PhpComposerInstalledEntry" + }, + { + "$ref": "#/$defs/PhpComposerLockEntry" + }, + { + "$ref": "#/$defs/PhpPearEntry" + }, + { + "$ref": "#/$defs/PhpPeclEntry" + }, + { + "$ref": "#/$defs/PortageDbEntry" + }, + { + "$ref": "#/$defs/PythonPackage" + }, + { + "$ref": "#/$defs/PythonPipRequirementsEntry" + }, + { + "$ref": "#/$defs/PythonPipfileLockEntry" + }, + { + "$ref": "#/$defs/PythonPoetryLockEntry" + }, + { + "$ref": "#/$defs/RDescription" + }, + { + "$ref": "#/$defs/RpmArchive" + }, + { + "$ref": "#/$defs/RpmDbEntry" + }, + { + "$ref": "#/$defs/RubyGemspec" + }, + { + "$ref": "#/$defs/RustCargoAuditEntry" + }, + { + "$ref": "#/$defs/RustCargoLockEntry" + }, + { + "$ref": "#/$defs/SwiftPackageManagerLockEntry" + }, + { + "$ref": "#/$defs/SwiplpackPackage" + }, + { + "$ref": "#/$defs/TerraformLockProviderEntry" + }, + { + "$ref": "#/$defs/WordpressPluginEntry" + } + ] + } + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "foundBy", + "locations", + "licenses", + "language", + "cpes", + "purl" + ] + }, + "PeBinary": { + "properties": { + "VersionResources": { + "$ref": "#/$defs/KeyValues" + } + }, + "type": "object", + "required": [ + "VersionResources" + ] + }, + "PhpComposerAuthors": { + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name" + ] + }, + "PhpComposerExternalReference": { + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "shasum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "type", + "url", + "reference" + ] + }, + "PhpComposerInstalledEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpComposerLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpPearEntry": { + "properties": { + "name": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PhpPeclEntry": { + "properties": { + "name": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PortageDbEntry": { + "properties": { + "installedSize": { + "type": "integer" + }, + "licenses": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PortageFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "installedSize", + "files" + ] + }, + "PortageFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonDirectURLOriginInfo": { + "properties": { + "url": { + "type": "string" + }, + "commitId": { + "type": "string" + }, + "vcs": { + "type": "string" + } + }, + "type": "object", + "required": [ + "url" + ] + }, + "PythonFileDigest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "PythonFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/PythonFileDigest" + }, + "size": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PythonFileRecord" + }, + "type": "array" + }, + "sitePackagesRootPath": { + "type": "string" + }, + "topLevelPackages": { + "items": { + "type": "string" + }, + "type": "array" + }, + "directUrlOrigin": { + "$ref": "#/$defs/PythonDirectURLOriginInfo" + }, + "requiresPython": { + "type": "string" + }, + "requiresDist": { + "items": { + "type": "string" + }, + "type": "array" + }, + "providesExtra": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "platform", + "sitePackagesRootPath" + ] + }, + "PythonPipRequirementsEntry": { + "properties": { + "name": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + }, + "versionConstraint": { + "type": "string" + }, + "url": { + "type": "string" + }, + "markers": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "versionConstraint" + ] + }, + "PythonPipfileLockEntry": { + "properties": { + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "index": { + "type": "string" + } + }, + "type": "object", + "required": [ + "hashes", + "index" + ] + }, + "PythonPoetryLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "optional" + ] + }, + "PythonPoetryLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonPoetryLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonPoetryLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonPoetryLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "RDescription": { + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "url": { + "items": { + "type": "string" + }, + "type": "array" + }, + "repository": { + "type": "string" + }, + "built": { + "type": "string" + }, + "needsCompilation": { + "type": "boolean" + }, + "imports": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "suggests": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "Relationship": { + "properties": { + "parent": { + "type": "string" + }, + "child": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "parent", + "child", + "type" + ] + }, + "RpmArchive": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "signatures": { + "items": { + "$ref": "#/$defs/RpmSignature" + }, + "type": "array" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmDbEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "signatures": { + "items": { + "$ref": "#/$defs/RpmSignature" + }, + "type": "array" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "userName": { + "type": "string" + }, + "groupName": { + "type": "string" + }, + "flags": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "mode", + "size", + "digest", + "userName", + "groupName", + "flags" + ] + }, + "RpmSignature": { + "properties": { + "algo": { + "type": "string" + }, + "hash": { + "type": "string" + }, + "created": { + "type": "string" + }, + "issuer": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algo", + "hash", + "created", + "issuer" + ] + }, + "RubyGemspec": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "RustCargoAuditEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source" + ] + }, + "RustCargoLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + }, + "checksum": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "checksum", + "dependencies" + ] + }, + "Schema": { + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "version", + "url" + ] + }, + "Source": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "metadata" + ] + }, + "SwiftPackageManagerLockEntry": { + "properties": { + "revision": { + "type": "string" + } + }, + "type": "object", + "required": [ + "revision" + ] + }, + "SwiplpackPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "packager": { + "type": "string" + }, + "packagerEmail": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "packager", + "packagerEmail", + "homepage", + "dependencies" + ] + }, + "TerraformLockProviderEntry": { + "properties": { + "url": { + "type": "string" + }, + "constraints": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "url", + "constraints", + "version", + "hashes" + ] + }, + "WordpressPluginEntry": { + "properties": { + "pluginInstallDirectory": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorUri": { + "type": "string" + } + }, + "type": "object", + "required": [ + "pluginInstallDirectory" + ] + }, + "cpes": { + "items": { + "$ref": "#/$defs/CPE" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/License" + }, + "type": "array" + } + } +} diff --git a/schema/json/schema-16.0.36.json b/schema/json/schema-16.0.36.json new file mode 100644 index 00000000000..1e0a395cf9f --- /dev/null +++ b/schema/json/schema-16.0.36.json @@ -0,0 +1,3173 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "anchore.io/schema/syft/json/16.0.36/document", + "$ref": "#/$defs/Document", + "$defs": { + "AlpmDbEntry": { + "properties": { + "basepackage": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "packager": { + "type": "string" + }, + "url": { + "type": "string" + }, + "validation": { + "type": "string" + }, + "reason": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "backup": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "basepackage", + "package", + "version", + "description", + "architecture", + "size", + "packager", + "url", + "validation", + "reason", + "files", + "backup" + ] + }, + "AlpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "type": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "gid": { + "type": "string" + }, + "time": { + "type": "string", + "format": "date-time" + }, + "size": { + "type": "string" + }, + "link": { + "type": "string" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object" + }, + "ApkDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "originPackage": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "version": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "installedSize": { + "type": "integer" + }, + "pullDependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "pullChecksum": { + "type": "string" + }, + "gitCommitOfApkPort": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/ApkFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "originPackage", + "maintainer", + "version", + "architecture", + "url", + "description", + "size", + "installedSize", + "pullDependencies", + "provides", + "pullChecksum", + "gitCommitOfApkPort", + "files" + ] + }, + "ApkFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "ownerUid": { + "type": "string" + }, + "ownerGid": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "BinarySignature": { + "properties": { + "matches": { + "items": { + "$ref": "#/$defs/ClassifierMatch" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "matches" + ] + }, + "BitnamiSbomEntry": { + "properties": { + "name": { + "type": "string" + }, + "arch": { + "type": "string" + }, + "distro": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "arch", + "distro", + "revision", + "version", + "path", + "files" + ] + }, + "CConanFileEntry": { + "properties": { + "ref": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanInfoEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "build_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "py_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "options": { + "$ref": "#/$defs/KeyValues" + }, + "path": { + "type": "string" + }, + "context": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockV2Entry": { + "properties": { + "ref": { + "type": "string" + }, + "packageID": { + "type": "string" + }, + "username": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "recipeRevision": { + "type": "string" + }, + "packageRevision": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CPE": { + "properties": { + "cpe": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "cpe" + ] + }, + "ClassifierMatch": { + "properties": { + "classifier": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Location" + } + }, + "type": "object", + "required": [ + "classifier", + "location" + ] + }, + "CocoaPodfileLockEntry": { + "properties": { + "checksum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "checksum" + ] + }, + "Coordinates": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "DartPubspec": { + "properties": { + "homepage": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "documentation": { + "type": "string" + }, + "publish_to": { + "type": "string" + }, + "environment": { + "$ref": "#/$defs/DartPubspecEnvironment" + }, + "platforms": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ignored_advisories": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "DartPubspecEnvironment": { + "properties": { + "sdk": { + "type": "string" + }, + "flutter": { + "type": "string" + } + }, + "type": "object" + }, + "DartPubspecLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hosted_url": { + "type": "string" + }, + "vcs_url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Descriptor": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "configuration": true + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Digest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "Document": { + "properties": { + "artifacts": { + "items": { + "$ref": "#/$defs/Package" + }, + "type": "array" + }, + "artifactRelationships": { + "items": { + "$ref": "#/$defs/Relationship" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/File" + }, + "type": "array" + }, + "source": { + "$ref": "#/$defs/Source" + }, + "distro": { + "$ref": "#/$defs/LinuxRelease" + }, + "descriptor": { + "$ref": "#/$defs/Descriptor" + }, + "schema": { + "$ref": "#/$defs/Schema" + } + }, + "type": "object", + "required": [ + "artifacts", + "artifactRelationships", + "source", + "distro", + "descriptor", + "schema" + ] + }, + "DotnetDepsEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "sha512": { + "type": "string" + }, + "hashPath": { + "type": "string" + }, + "executables": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "path", + "sha512", + "hashPath" + ] + }, + "DotnetPackagesLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "contentHash": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "contentHash", + "type" + ] + }, + "DotnetPortableExecutableEntry": { + "properties": { + "assemblyVersion": { + "type": "string" + }, + "legalCopyright": { + "type": "string" + }, + "comments": { + "type": "string" + }, + "internalName": { + "type": "string" + }, + "companyName": { + "type": "string" + }, + "productName": { + "type": "string" + }, + "productVersion": { + "type": "string" + } + }, + "type": "object", + "required": [ + "assemblyVersion", + "legalCopyright", + "companyName", + "productName", + "productVersion" + ] + }, + "DpkgArchiveEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "isConfigFile": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "path", + "isConfigFile" + ] + }, + "ELFSecurityFeatures": { + "properties": { + "symbolTableStripped": { + "type": "boolean" + }, + "stackCanary": { + "type": "boolean" + }, + "nx": { + "type": "boolean" + }, + "relRO": { + "type": "string" + }, + "pie": { + "type": "boolean" + }, + "dso": { + "type": "boolean" + }, + "safeStack": { + "type": "boolean" + }, + "cfi": { + "type": "boolean" + }, + "fortify": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "symbolTableStripped", + "nx", + "relRO", + "pie", + "dso" + ] + }, + "ElfBinaryPackageNoteJsonPayload": { + "properties": { + "type": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "osCPE": { + "type": "string" + }, + "os": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "system": { + "type": "string" + }, + "vendor": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "commit": { + "type": "string" + } + }, + "type": "object" + }, + "ElixirMixLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "ErlangRebarLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "Executable": { + "properties": { + "format": { + "type": "string" + }, + "hasExports": { + "type": "boolean" + }, + "hasEntrypoint": { + "type": "boolean" + }, + "importedLibraries": { + "items": { + "type": "string" + }, + "type": "array" + }, + "elfSecurityFeatures": { + "$ref": "#/$defs/ELFSecurityFeatures" + } + }, + "type": "object", + "required": [ + "format", + "hasExports", + "hasEntrypoint", + "importedLibraries" + ] + }, + "File": { + "properties": { + "id": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Coordinates" + }, + "metadata": { + "$ref": "#/$defs/FileMetadataEntry" + }, + "contents": { + "type": "string" + }, + "digests": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/FileLicense" + }, + "type": "array" + }, + "executable": { + "$ref": "#/$defs/Executable" + }, + "unknowns": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "id", + "location" + ] + }, + "FileLicense": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "evidence": { + "$ref": "#/$defs/FileLicenseEvidence" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type" + ] + }, + "FileLicenseEvidence": { + "properties": { + "confidence": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "extent": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "confidence", + "offset", + "extent" + ] + }, + "FileMetadataEntry": { + "properties": { + "mode": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "userID": { + "type": "integer" + }, + "groupID": { + "type": "integer" + }, + "mimeType": { + "type": "string" + }, + "size": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "mode", + "type", + "userID", + "groupID", + "mimeType", + "size" + ] + }, + "GithubActionsUseStatement": { + "properties": { + "value": { + "type": "string" + }, + "comment": { + "type": "string" + } + }, + "type": "object", + "required": [ + "value" + ] + }, + "GoModuleBuildinfoEntry": { + "properties": { + "goBuildSettings": { + "$ref": "#/$defs/KeyValues" + }, + "goCompiledVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "h1Digest": { + "type": "string" + }, + "mainModule": { + "type": "string" + }, + "goCryptoSettings": { + "items": { + "type": "string" + }, + "type": "array" + }, + "goExperiments": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "goCompiledVersion", + "architecture" + ] + }, + "GoModuleEntry": { + "properties": { + "h1Digest": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackEntry": { + "properties": { + "pkgHash": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackLockEntry": { + "properties": { + "pkgHash": { + "type": "string" + }, + "snapshotURL": { + "type": "string" + } + }, + "type": "object" + }, + "HomebrewFormula": { + "properties": { + "tap": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "IDLikes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "JavaArchive": { + "properties": { + "virtualPath": { + "type": "string" + }, + "manifest": { + "$ref": "#/$defs/JavaManifest" + }, + "pomProperties": { + "$ref": "#/$defs/JavaPomProperties" + }, + "pomProject": { + "$ref": "#/$defs/JavaPomProject" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "virtualPath" + ] + }, + "JavaJvmInstallation": { + "properties": { + "release": { + "$ref": "#/$defs/JavaVMRelease" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "release", + "files" + ] + }, + "JavaManifest": { + "properties": { + "main": { + "$ref": "#/$defs/KeyValues" + }, + "sections": { + "items": { + "$ref": "#/$defs/KeyValues" + }, + "type": "array" + } + }, + "type": "object" + }, + "JavaPomParent": { + "properties": { + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object", + "required": [ + "groupId", + "artifactId", + "version" + ] + }, + "JavaPomProject": { + "properties": { + "path": { + "type": "string" + }, + "parent": { + "$ref": "#/$defs/JavaPomParent" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "groupId", + "artifactId", + "version", + "name" + ] + }, + "JavaPomProperties": { + "properties": { + "path": { + "type": "string" + }, + "name": { + "type": "string" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "extraFields": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "name", + "groupId", + "artifactId", + "version" + ] + }, + "JavaVMRelease": { + "properties": { + "implementor": { + "type": "string" + }, + "implementorVersion": { + "type": "string" + }, + "javaRuntimeVersion": { + "type": "string" + }, + "javaVersion": { + "type": "string" + }, + "javaVersionDate": { + "type": "string" + }, + "libc": { + "type": "string" + }, + "modules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "osArch": { + "type": "string" + }, + "osName": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "source": { + "type": "string" + }, + "buildSource": { + "type": "string" + }, + "buildSourceRepo": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "fullVersion": { + "type": "string" + }, + "semanticVersion": { + "type": "string" + }, + "buildInfo": { + "type": "string" + }, + "jvmVariant": { + "type": "string" + }, + "jvmVersion": { + "type": "string" + }, + "imageType": { + "type": "string" + }, + "buildType": { + "type": "string" + } + }, + "type": "object" + }, + "JavascriptNpmPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "private": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "homepage", + "description", + "url", + "private" + ] + }, + "JavascriptNpmPackageLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "JavascriptYarnLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "KeyValue": { + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "key", + "value" + ] + }, + "KeyValues": { + "items": { + "$ref": "#/$defs/KeyValue" + }, + "type": "array" + }, + "License": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "urls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "contents": { + "type": "string" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type", + "urls", + "locations" + ] + }, + "LinuxKernelArchive": { + "properties": { + "name": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "version": { + "type": "string" + }, + "extendedVersion": { + "type": "string" + }, + "buildTime": { + "type": "string" + }, + "author": { + "type": "string" + }, + "format": { + "type": "string" + }, + "rwRootFS": { + "type": "boolean" + }, + "swapDevice": { + "type": "integer" + }, + "rootDevice": { + "type": "integer" + }, + "videoMode": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "architecture", + "version" + ] + }, + "LinuxKernelModule": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "path": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "license": { + "type": "string" + }, + "kernelVersion": { + "type": "string" + }, + "versionMagic": { + "type": "string" + }, + "parameters": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/LinuxKernelModuleParameter" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "LinuxKernelModuleParameter": { + "properties": { + "type": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "LinuxRelease": { + "properties": { + "prettyName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idLike": { + "$ref": "#/$defs/IDLikes" + }, + "version": { + "type": "string" + }, + "versionID": { + "type": "string" + }, + "versionCodename": { + "type": "string" + }, + "buildID": { + "type": "string" + }, + "imageID": { + "type": "string" + }, + "imageVersion": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "variantID": { + "type": "string" + }, + "homeURL": { + "type": "string" + }, + "supportURL": { + "type": "string" + }, + "bugReportURL": { + "type": "string" + }, + "privacyPolicyURL": { + "type": "string" + }, + "cpeName": { + "type": "string" + }, + "supportEnd": { + "type": "string" + }, + "extendedSupport": { + "type": "boolean" + } + }, + "type": "object" + }, + "Location": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + }, + "accessPath": { + "type": "string" + }, + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "accessPath" + ] + }, + "LuarocksPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "dependencies": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "license", + "homepage", + "description", + "url", + "dependencies" + ] + }, + "MicrosoftKbPatch": { + "properties": { + "product_id": { + "type": "string" + }, + "kb": { + "type": "string" + } + }, + "type": "object", + "required": [ + "product_id", + "kb" + ] + }, + "NixDerivation": { + "properties": { + "path": { + "type": "string" + }, + "system": { + "type": "string" + }, + "inputDerivations": { + "items": { + "$ref": "#/$defs/NixDerivationReference" + }, + "type": "array" + }, + "inputSources": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "NixDerivationReference": { + "properties": { + "path": { + "type": "string" + }, + "outputs": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "NixStoreEntry": { + "properties": { + "path": { + "type": "string" + }, + "output": { + "type": "string" + }, + "outputHash": { + "type": "string" + }, + "derivation": { + "$ref": "#/$defs/NixDerivation" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "outputHash" + ] + }, + "OpamPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "url": { + "type": "string" + }, + "checksum": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "licenses", + "url", + "checksum", + "homepage", + "dependencies" + ] + }, + "Package": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "foundBy": { + "type": "string" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "licenses": { + "$ref": "#/$defs/licenses" + }, + "language": { + "type": "string" + }, + "cpes": { + "$ref": "#/$defs/cpes" + }, + "purl": { + "type": "string" + }, + "metadataType": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/AlpmDbEntry" + }, + { + "$ref": "#/$defs/ApkDbEntry" + }, + { + "$ref": "#/$defs/BinarySignature" + }, + { + "$ref": "#/$defs/BitnamiSbomEntry" + }, + { + "$ref": "#/$defs/CConanFileEntry" + }, + { + "$ref": "#/$defs/CConanInfoEntry" + }, + { + "$ref": "#/$defs/CConanLockEntry" + }, + { + "$ref": "#/$defs/CConanLockV2Entry" + }, + { + "$ref": "#/$defs/CocoaPodfileLockEntry" + }, + { + "$ref": "#/$defs/DartPubspec" + }, + { + "$ref": "#/$defs/DartPubspecLockEntry" + }, + { + "$ref": "#/$defs/DotnetDepsEntry" + }, + { + "$ref": "#/$defs/DotnetPackagesLockEntry" + }, + { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + }, + { + "$ref": "#/$defs/DpkgArchiveEntry" + }, + { + "$ref": "#/$defs/DpkgDbEntry" + }, + { + "$ref": "#/$defs/ElfBinaryPackageNoteJsonPayload" + }, + { + "$ref": "#/$defs/ElixirMixLockEntry" + }, + { + "$ref": "#/$defs/ErlangRebarLockEntry" + }, + { + "$ref": "#/$defs/GithubActionsUseStatement" + }, + { + "$ref": "#/$defs/GoModuleBuildinfoEntry" + }, + { + "$ref": "#/$defs/GoModuleEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackLockEntry" + }, + { + "$ref": "#/$defs/HomebrewFormula" + }, + { + "$ref": "#/$defs/JavaArchive" + }, + { + "$ref": "#/$defs/JavaJvmInstallation" + }, + { + "$ref": "#/$defs/JavascriptNpmPackage" + }, + { + "$ref": "#/$defs/JavascriptNpmPackageLockEntry" + }, + { + "$ref": "#/$defs/JavascriptYarnLockEntry" + }, + { + "$ref": "#/$defs/LinuxKernelArchive" + }, + { + "$ref": "#/$defs/LinuxKernelModule" + }, + { + "$ref": "#/$defs/LuarocksPackage" + }, + { + "$ref": "#/$defs/MicrosoftKbPatch" + }, + { + "$ref": "#/$defs/NixStoreEntry" + }, + { + "$ref": "#/$defs/OpamPackage" + }, + { + "$ref": "#/$defs/PeBinary" + }, + { + "$ref": "#/$defs/PhpComposerInstalledEntry" + }, + { + "$ref": "#/$defs/PhpComposerLockEntry" + }, + { + "$ref": "#/$defs/PhpPearEntry" + }, + { + "$ref": "#/$defs/PhpPeclEntry" + }, + { + "$ref": "#/$defs/PortageDbEntry" + }, + { + "$ref": "#/$defs/PythonPackage" + }, + { + "$ref": "#/$defs/PythonPipRequirementsEntry" + }, + { + "$ref": "#/$defs/PythonPipfileLockEntry" + }, + { + "$ref": "#/$defs/PythonPoetryLockEntry" + }, + { + "$ref": "#/$defs/PythonUvLockEntry" + }, + { + "$ref": "#/$defs/RDescription" + }, + { + "$ref": "#/$defs/RpmArchive" + }, + { + "$ref": "#/$defs/RpmDbEntry" + }, + { + "$ref": "#/$defs/RubyGemspec" + }, + { + "$ref": "#/$defs/RustCargoAuditEntry" + }, + { + "$ref": "#/$defs/RustCargoLockEntry" + }, + { + "$ref": "#/$defs/SwiftPackageManagerLockEntry" + }, + { + "$ref": "#/$defs/SwiplpackPackage" + }, + { + "$ref": "#/$defs/TerraformLockProviderEntry" + }, + { + "$ref": "#/$defs/WordpressPluginEntry" + } + ] + } + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "foundBy", + "locations", + "licenses", + "language", + "cpes", + "purl" + ] + }, + "PeBinary": { + "properties": { + "VersionResources": { + "$ref": "#/$defs/KeyValues" + } + }, + "type": "object", + "required": [ + "VersionResources" + ] + }, + "PhpComposerAuthors": { + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name" + ] + }, + "PhpComposerExternalReference": { + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "shasum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "type", + "url", + "reference" + ] + }, + "PhpComposerInstalledEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpComposerLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpPearEntry": { + "properties": { + "name": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PhpPeclEntry": { + "properties": { + "name": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PortageDbEntry": { + "properties": { + "installedSize": { + "type": "integer" + }, + "licenses": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PortageFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "installedSize", + "files" + ] + }, + "PortageFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonDirectURLOriginInfo": { + "properties": { + "url": { + "type": "string" + }, + "commitId": { + "type": "string" + }, + "vcs": { + "type": "string" + } + }, + "type": "object", + "required": [ + "url" + ] + }, + "PythonFileDigest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "PythonFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/PythonFileDigest" + }, + "size": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PythonFileRecord" + }, + "type": "array" + }, + "sitePackagesRootPath": { + "type": "string" + }, + "topLevelPackages": { + "items": { + "type": "string" + }, + "type": "array" + }, + "directUrlOrigin": { + "$ref": "#/$defs/PythonDirectURLOriginInfo" + }, + "requiresPython": { + "type": "string" + }, + "requiresDist": { + "items": { + "type": "string" + }, + "type": "array" + }, + "providesExtra": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "platform", + "sitePackagesRootPath" + ] + }, + "PythonPipRequirementsEntry": { + "properties": { + "name": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + }, + "versionConstraint": { + "type": "string" + }, + "url": { + "type": "string" + }, + "markers": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "versionConstraint" + ] + }, + "PythonPipfileLockEntry": { + "properties": { + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "index": { + "type": "string" + } + }, + "type": "object", + "required": [ + "hashes", + "index" + ] + }, + "PythonPoetryLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "optional" + ] + }, + "PythonPoetryLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonPoetryLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonPoetryLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonPoetryLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "PythonUvLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "optional" + ] + }, + "PythonUvLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonUvLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonUvLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonUvLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "RDescription": { + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "url": { + "items": { + "type": "string" + }, + "type": "array" + }, + "repository": { + "type": "string" + }, + "built": { + "type": "string" + }, + "needsCompilation": { + "type": "boolean" + }, + "imports": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "suggests": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "Relationship": { + "properties": { + "parent": { + "type": "string" + }, + "child": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "parent", + "child", + "type" + ] + }, + "RpmArchive": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "signatures": { + "items": { + "$ref": "#/$defs/RpmSignature" + }, + "type": "array" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmDbEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "signatures": { + "items": { + "$ref": "#/$defs/RpmSignature" + }, + "type": "array" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "userName": { + "type": "string" + }, + "groupName": { + "type": "string" + }, + "flags": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "mode", + "size", + "digest", + "userName", + "groupName", + "flags" + ] + }, + "RpmSignature": { + "properties": { + "algo": { + "type": "string" + }, + "hash": { + "type": "string" + }, + "created": { + "type": "string" + }, + "issuer": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algo", + "hash", + "created", + "issuer" + ] + }, + "RubyGemspec": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "RustCargoAuditEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source" + ] + }, + "RustCargoLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + }, + "checksum": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "checksum", + "dependencies" + ] + }, + "Schema": { + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "version", + "url" + ] + }, + "Source": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "metadata" + ] + }, + "SwiftPackageManagerLockEntry": { + "properties": { + "revision": { + "type": "string" + } + }, + "type": "object", + "required": [ + "revision" + ] + }, + "SwiplpackPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "packager": { + "type": "string" + }, + "packagerEmail": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "packager", + "packagerEmail", + "homepage", + "dependencies" + ] + }, + "TerraformLockProviderEntry": { + "properties": { + "url": { + "type": "string" + }, + "constraints": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "url", + "constraints", + "version", + "hashes" + ] + }, + "WordpressPluginEntry": { + "properties": { + "pluginInstallDirectory": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorUri": { + "type": "string" + } + }, + "type": "object", + "required": [ + "pluginInstallDirectory" + ] + }, + "cpes": { + "items": { + "$ref": "#/$defs/CPE" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/License" + }, + "type": "array" + } + } +} diff --git a/schema/json/schema-16.0.37.json b/schema/json/schema-16.0.37.json new file mode 100644 index 00000000000..0de3d453fbb --- /dev/null +++ b/schema/json/schema-16.0.37.json @@ -0,0 +1,3176 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "anchore.io/schema/syft/json/16.0.37/document", + "$ref": "#/$defs/Document", + "$defs": { + "AlpmDbEntry": { + "properties": { + "basepackage": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "packager": { + "type": "string" + }, + "url": { + "type": "string" + }, + "validation": { + "type": "string" + }, + "reason": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "backup": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "basepackage", + "package", + "version", + "description", + "architecture", + "size", + "packager", + "url", + "validation", + "reason", + "files", + "backup" + ] + }, + "AlpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "type": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "gid": { + "type": "string" + }, + "time": { + "type": "string", + "format": "date-time" + }, + "size": { + "type": "string" + }, + "link": { + "type": "string" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object" + }, + "ApkDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "originPackage": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "version": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "installedSize": { + "type": "integer" + }, + "pullDependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "pullChecksum": { + "type": "string" + }, + "gitCommitOfApkPort": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/ApkFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "originPackage", + "maintainer", + "version", + "architecture", + "url", + "description", + "size", + "installedSize", + "pullDependencies", + "provides", + "pullChecksum", + "gitCommitOfApkPort", + "files" + ] + }, + "ApkFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "ownerUid": { + "type": "string" + }, + "ownerGid": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "BinarySignature": { + "properties": { + "matches": { + "items": { + "$ref": "#/$defs/ClassifierMatch" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "matches" + ] + }, + "BitnamiSbomEntry": { + "properties": { + "name": { + "type": "string" + }, + "arch": { + "type": "string" + }, + "distro": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "arch", + "distro", + "revision", + "version", + "path", + "files" + ] + }, + "CConanFileEntry": { + "properties": { + "ref": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanInfoEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "build_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "py_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "options": { + "$ref": "#/$defs/KeyValues" + }, + "path": { + "type": "string" + }, + "context": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockV2Entry": { + "properties": { + "ref": { + "type": "string" + }, + "packageID": { + "type": "string" + }, + "username": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "recipeRevision": { + "type": "string" + }, + "packageRevision": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CPE": { + "properties": { + "cpe": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "cpe" + ] + }, + "ClassifierMatch": { + "properties": { + "classifier": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Location" + } + }, + "type": "object", + "required": [ + "classifier", + "location" + ] + }, + "CocoaPodfileLockEntry": { + "properties": { + "checksum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "checksum" + ] + }, + "Coordinates": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "DartPubspec": { + "properties": { + "homepage": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "documentation": { + "type": "string" + }, + "publish_to": { + "type": "string" + }, + "environment": { + "$ref": "#/$defs/DartPubspecEnvironment" + }, + "platforms": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ignored_advisories": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "DartPubspecEnvironment": { + "properties": { + "sdk": { + "type": "string" + }, + "flutter": { + "type": "string" + } + }, + "type": "object" + }, + "DartPubspecLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hosted_url": { + "type": "string" + }, + "vcs_url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Descriptor": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "configuration": true + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Digest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "Document": { + "properties": { + "artifacts": { + "items": { + "$ref": "#/$defs/Package" + }, + "type": "array" + }, + "artifactRelationships": { + "items": { + "$ref": "#/$defs/Relationship" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/File" + }, + "type": "array" + }, + "source": { + "$ref": "#/$defs/Source" + }, + "distro": { + "$ref": "#/$defs/LinuxRelease" + }, + "descriptor": { + "$ref": "#/$defs/Descriptor" + }, + "schema": { + "$ref": "#/$defs/Schema" + } + }, + "type": "object", + "required": [ + "artifacts", + "artifactRelationships", + "source", + "distro", + "descriptor", + "schema" + ] + }, + "DotnetDepsEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "sha512": { + "type": "string" + }, + "hashPath": { + "type": "string" + }, + "executables": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "path", + "sha512", + "hashPath" + ] + }, + "DotnetPackagesLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "contentHash": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "contentHash", + "type" + ] + }, + "DotnetPortableExecutableEntry": { + "properties": { + "assemblyVersion": { + "type": "string" + }, + "legalCopyright": { + "type": "string" + }, + "comments": { + "type": "string" + }, + "internalName": { + "type": "string" + }, + "companyName": { + "type": "string" + }, + "productName": { + "type": "string" + }, + "productVersion": { + "type": "string" + } + }, + "type": "object", + "required": [ + "assemblyVersion", + "legalCopyright", + "companyName", + "productName", + "productVersion" + ] + }, + "DpkgArchiveEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "isConfigFile": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "path", + "isConfigFile" + ] + }, + "ELFSecurityFeatures": { + "properties": { + "symbolTableStripped": { + "type": "boolean" + }, + "stackCanary": { + "type": "boolean" + }, + "nx": { + "type": "boolean" + }, + "relRO": { + "type": "string" + }, + "pie": { + "type": "boolean" + }, + "dso": { + "type": "boolean" + }, + "safeStack": { + "type": "boolean" + }, + "cfi": { + "type": "boolean" + }, + "fortify": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "symbolTableStripped", + "nx", + "relRO", + "pie", + "dso" + ] + }, + "ElfBinaryPackageNoteJsonPayload": { + "properties": { + "type": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "osCPE": { + "type": "string" + }, + "os": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "system": { + "type": "string" + }, + "vendor": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "commit": { + "type": "string" + } + }, + "type": "object" + }, + "ElixirMixLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "ErlangRebarLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "Executable": { + "properties": { + "format": { + "type": "string" + }, + "hasExports": { + "type": "boolean" + }, + "hasEntrypoint": { + "type": "boolean" + }, + "importedLibraries": { + "items": { + "type": "string" + }, + "type": "array" + }, + "elfSecurityFeatures": { + "$ref": "#/$defs/ELFSecurityFeatures" + } + }, + "type": "object", + "required": [ + "format", + "hasExports", + "hasEntrypoint", + "importedLibraries" + ] + }, + "File": { + "properties": { + "id": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Coordinates" + }, + "metadata": { + "$ref": "#/$defs/FileMetadataEntry" + }, + "contents": { + "type": "string" + }, + "digests": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/FileLicense" + }, + "type": "array" + }, + "executable": { + "$ref": "#/$defs/Executable" + }, + "unknowns": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "id", + "location" + ] + }, + "FileLicense": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "evidence": { + "$ref": "#/$defs/FileLicenseEvidence" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type" + ] + }, + "FileLicenseEvidence": { + "properties": { + "confidence": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "extent": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "confidence", + "offset", + "extent" + ] + }, + "FileMetadataEntry": { + "properties": { + "mode": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "userID": { + "type": "integer" + }, + "groupID": { + "type": "integer" + }, + "mimeType": { + "type": "string" + }, + "size": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "mode", + "type", + "userID", + "groupID", + "mimeType", + "size" + ] + }, + "GithubActionsUseStatement": { + "properties": { + "value": { + "type": "string" + }, + "comment": { + "type": "string" + } + }, + "type": "object", + "required": [ + "value" + ] + }, + "GoModuleBuildinfoEntry": { + "properties": { + "goBuildSettings": { + "$ref": "#/$defs/KeyValues" + }, + "goCompiledVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "h1Digest": { + "type": "string" + }, + "mainModule": { + "type": "string" + }, + "goCryptoSettings": { + "items": { + "type": "string" + }, + "type": "array" + }, + "goExperiments": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "goCompiledVersion", + "architecture" + ] + }, + "GoModuleEntry": { + "properties": { + "h1Digest": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackEntry": { + "properties": { + "pkgHash": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackLockEntry": { + "properties": { + "pkgHash": { + "type": "string" + }, + "snapshotURL": { + "type": "string" + } + }, + "type": "object" + }, + "HomebrewFormula": { + "properties": { + "tap": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "IDLikes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "JavaArchive": { + "properties": { + "virtualPath": { + "type": "string" + }, + "manifest": { + "$ref": "#/$defs/JavaManifest" + }, + "pomProperties": { + "$ref": "#/$defs/JavaPomProperties" + }, + "pomProject": { + "$ref": "#/$defs/JavaPomProject" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "virtualPath" + ] + }, + "JavaJvmInstallation": { + "properties": { + "release": { + "$ref": "#/$defs/JavaVMRelease" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "release", + "files" + ] + }, + "JavaManifest": { + "properties": { + "main": { + "$ref": "#/$defs/KeyValues" + }, + "sections": { + "items": { + "$ref": "#/$defs/KeyValues" + }, + "type": "array" + } + }, + "type": "object" + }, + "JavaPomParent": { + "properties": { + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object", + "required": [ + "groupId", + "artifactId", + "version" + ] + }, + "JavaPomProject": { + "properties": { + "path": { + "type": "string" + }, + "parent": { + "$ref": "#/$defs/JavaPomParent" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "groupId", + "artifactId", + "version", + "name" + ] + }, + "JavaPomProperties": { + "properties": { + "path": { + "type": "string" + }, + "name": { + "type": "string" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "extraFields": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "name", + "groupId", + "artifactId", + "version" + ] + }, + "JavaVMRelease": { + "properties": { + "implementor": { + "type": "string" + }, + "implementorVersion": { + "type": "string" + }, + "javaRuntimeVersion": { + "type": "string" + }, + "javaVersion": { + "type": "string" + }, + "javaVersionDate": { + "type": "string" + }, + "libc": { + "type": "string" + }, + "modules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "osArch": { + "type": "string" + }, + "osName": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "source": { + "type": "string" + }, + "buildSource": { + "type": "string" + }, + "buildSourceRepo": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "fullVersion": { + "type": "string" + }, + "semanticVersion": { + "type": "string" + }, + "buildInfo": { + "type": "string" + }, + "jvmVariant": { + "type": "string" + }, + "jvmVersion": { + "type": "string" + }, + "imageType": { + "type": "string" + }, + "buildType": { + "type": "string" + } + }, + "type": "object" + }, + "JavascriptNpmPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "private": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "homepage", + "description", + "url", + "private" + ] + }, + "JavascriptNpmPackageLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "JavascriptYarnLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "KeyValue": { + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "key", + "value" + ] + }, + "KeyValues": { + "items": { + "$ref": "#/$defs/KeyValue" + }, + "type": "array" + }, + "License": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "urls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "contents": { + "type": "string" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type", + "urls", + "locations" + ] + }, + "LinuxKernelArchive": { + "properties": { + "name": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "version": { + "type": "string" + }, + "extendedVersion": { + "type": "string" + }, + "buildTime": { + "type": "string" + }, + "author": { + "type": "string" + }, + "format": { + "type": "string" + }, + "rwRootFS": { + "type": "boolean" + }, + "swapDevice": { + "type": "integer" + }, + "rootDevice": { + "type": "integer" + }, + "videoMode": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "architecture", + "version" + ] + }, + "LinuxKernelModule": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "path": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "license": { + "type": "string" + }, + "kernelVersion": { + "type": "string" + }, + "versionMagic": { + "type": "string" + }, + "parameters": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/LinuxKernelModuleParameter" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "LinuxKernelModuleParameter": { + "properties": { + "type": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "LinuxRelease": { + "properties": { + "prettyName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idLike": { + "$ref": "#/$defs/IDLikes" + }, + "version": { + "type": "string" + }, + "versionID": { + "type": "string" + }, + "versionCodename": { + "type": "string" + }, + "buildID": { + "type": "string" + }, + "imageID": { + "type": "string" + }, + "imageVersion": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "variantID": { + "type": "string" + }, + "homeURL": { + "type": "string" + }, + "supportURL": { + "type": "string" + }, + "bugReportURL": { + "type": "string" + }, + "privacyPolicyURL": { + "type": "string" + }, + "cpeName": { + "type": "string" + }, + "supportEnd": { + "type": "string" + }, + "extendedSupport": { + "type": "boolean" + } + }, + "type": "object" + }, + "Location": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + }, + "accessPath": { + "type": "string" + }, + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "accessPath" + ] + }, + "LuarocksPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "dependencies": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "license", + "homepage", + "description", + "url", + "dependencies" + ] + }, + "MicrosoftKbPatch": { + "properties": { + "product_id": { + "type": "string" + }, + "kb": { + "type": "string" + } + }, + "type": "object", + "required": [ + "product_id", + "kb" + ] + }, + "NixDerivation": { + "properties": { + "path": { + "type": "string" + }, + "system": { + "type": "string" + }, + "inputDerivations": { + "items": { + "$ref": "#/$defs/NixDerivationReference" + }, + "type": "array" + }, + "inputSources": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "NixDerivationReference": { + "properties": { + "path": { + "type": "string" + }, + "outputs": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "NixStoreEntry": { + "properties": { + "path": { + "type": "string" + }, + "output": { + "type": "string" + }, + "outputHash": { + "type": "string" + }, + "derivation": { + "$ref": "#/$defs/NixDerivation" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "outputHash" + ] + }, + "OpamPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "url": { + "type": "string" + }, + "checksum": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "licenses", + "url", + "checksum", + "homepage", + "dependencies" + ] + }, + "Package": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "foundBy": { + "type": "string" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "licenses": { + "$ref": "#/$defs/licenses" + }, + "language": { + "type": "string" + }, + "cpes": { + "$ref": "#/$defs/cpes" + }, + "purl": { + "type": "string" + }, + "metadataType": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/AlpmDbEntry" + }, + { + "$ref": "#/$defs/ApkDbEntry" + }, + { + "$ref": "#/$defs/BinarySignature" + }, + { + "$ref": "#/$defs/BitnamiSbomEntry" + }, + { + "$ref": "#/$defs/CConanFileEntry" + }, + { + "$ref": "#/$defs/CConanInfoEntry" + }, + { + "$ref": "#/$defs/CConanLockEntry" + }, + { + "$ref": "#/$defs/CConanLockV2Entry" + }, + { + "$ref": "#/$defs/CocoaPodfileLockEntry" + }, + { + "$ref": "#/$defs/DartPubspec" + }, + { + "$ref": "#/$defs/DartPubspecLockEntry" + }, + { + "$ref": "#/$defs/DotnetDepsEntry" + }, + { + "$ref": "#/$defs/DotnetPackagesLockEntry" + }, + { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + }, + { + "$ref": "#/$defs/DpkgArchiveEntry" + }, + { + "$ref": "#/$defs/DpkgDbEntry" + }, + { + "$ref": "#/$defs/ElfBinaryPackageNoteJsonPayload" + }, + { + "$ref": "#/$defs/ElixirMixLockEntry" + }, + { + "$ref": "#/$defs/ErlangRebarLockEntry" + }, + { + "$ref": "#/$defs/GithubActionsUseStatement" + }, + { + "$ref": "#/$defs/GoModuleBuildinfoEntry" + }, + { + "$ref": "#/$defs/GoModuleEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackLockEntry" + }, + { + "$ref": "#/$defs/HomebrewFormula" + }, + { + "$ref": "#/$defs/JavaArchive" + }, + { + "$ref": "#/$defs/JavaJvmInstallation" + }, + { + "$ref": "#/$defs/JavascriptNpmPackage" + }, + { + "$ref": "#/$defs/JavascriptNpmPackageLockEntry" + }, + { + "$ref": "#/$defs/JavascriptYarnLockEntry" + }, + { + "$ref": "#/$defs/LinuxKernelArchive" + }, + { + "$ref": "#/$defs/LinuxKernelModule" + }, + { + "$ref": "#/$defs/LuarocksPackage" + }, + { + "$ref": "#/$defs/MicrosoftKbPatch" + }, + { + "$ref": "#/$defs/NixStoreEntry" + }, + { + "$ref": "#/$defs/OpamPackage" + }, + { + "$ref": "#/$defs/PeBinary" + }, + { + "$ref": "#/$defs/PhpComposerInstalledEntry" + }, + { + "$ref": "#/$defs/PhpComposerLockEntry" + }, + { + "$ref": "#/$defs/PhpPearEntry" + }, + { + "$ref": "#/$defs/PhpPeclEntry" + }, + { + "$ref": "#/$defs/PortageDbEntry" + }, + { + "$ref": "#/$defs/PythonPackage" + }, + { + "$ref": "#/$defs/PythonPipRequirementsEntry" + }, + { + "$ref": "#/$defs/PythonPipfileLockEntry" + }, + { + "$ref": "#/$defs/PythonPoetryLockEntry" + }, + { + "$ref": "#/$defs/PythonUvLockEntry" + }, + { + "$ref": "#/$defs/RDescription" + }, + { + "$ref": "#/$defs/RpmArchive" + }, + { + "$ref": "#/$defs/RpmDbEntry" + }, + { + "$ref": "#/$defs/RubyGemspec" + }, + { + "$ref": "#/$defs/RustCargoAuditEntry" + }, + { + "$ref": "#/$defs/RustCargoLockEntry" + }, + { + "$ref": "#/$defs/SwiftPackageManagerLockEntry" + }, + { + "$ref": "#/$defs/SwiplpackPackage" + }, + { + "$ref": "#/$defs/TerraformLockProviderEntry" + }, + { + "$ref": "#/$defs/WordpressPluginEntry" + } + ] + } + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "foundBy", + "locations", + "licenses", + "language", + "cpes", + "purl" + ] + }, + "PeBinary": { + "properties": { + "VersionResources": { + "$ref": "#/$defs/KeyValues" + } + }, + "type": "object", + "required": [ + "VersionResources" + ] + }, + "PhpComposerAuthors": { + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name" + ] + }, + "PhpComposerExternalReference": { + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "shasum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "type", + "url", + "reference" + ] + }, + "PhpComposerInstalledEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpComposerLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpPearEntry": { + "properties": { + "name": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PhpPeclEntry": { + "properties": { + "name": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PortageDbEntry": { + "properties": { + "installedSize": { + "type": "integer" + }, + "licenses": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PortageFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "installedSize", + "files" + ] + }, + "PortageFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonDirectURLOriginInfo": { + "properties": { + "url": { + "type": "string" + }, + "commitId": { + "type": "string" + }, + "vcs": { + "type": "string" + } + }, + "type": "object", + "required": [ + "url" + ] + }, + "PythonFileDigest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "PythonFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/PythonFileDigest" + }, + "size": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PythonFileRecord" + }, + "type": "array" + }, + "sitePackagesRootPath": { + "type": "string" + }, + "topLevelPackages": { + "items": { + "type": "string" + }, + "type": "array" + }, + "directUrlOrigin": { + "$ref": "#/$defs/PythonDirectURLOriginInfo" + }, + "requiresPython": { + "type": "string" + }, + "requiresDist": { + "items": { + "type": "string" + }, + "type": "array" + }, + "providesExtra": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "platform", + "sitePackagesRootPath" + ] + }, + "PythonPipRequirementsEntry": { + "properties": { + "name": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + }, + "versionConstraint": { + "type": "string" + }, + "url": { + "type": "string" + }, + "markers": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "versionConstraint" + ] + }, + "PythonPipfileLockEntry": { + "properties": { + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "index": { + "type": "string" + } + }, + "type": "object", + "required": [ + "hashes", + "index" + ] + }, + "PythonPoetryLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "optional" + ] + }, + "PythonPoetryLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonPoetryLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonPoetryLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonPoetryLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "PythonUvLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "optional" + ] + }, + "PythonUvLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonUvLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonUvLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonUvLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "RDescription": { + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "url": { + "items": { + "type": "string" + }, + "type": "array" + }, + "repository": { + "type": "string" + }, + "built": { + "type": "string" + }, + "needsCompilation": { + "type": "boolean" + }, + "imports": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "suggests": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "Relationship": { + "properties": { + "parent": { + "type": "string" + }, + "child": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "parent", + "child", + "type" + ] + }, + "RpmArchive": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "signatures": { + "items": { + "$ref": "#/$defs/RpmSignature" + }, + "type": "array" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmDbEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "signatures": { + "items": { + "$ref": "#/$defs/RpmSignature" + }, + "type": "array" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "userName": { + "type": "string" + }, + "groupName": { + "type": "string" + }, + "flags": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "mode", + "size", + "digest", + "userName", + "groupName", + "flags" + ] + }, + "RpmSignature": { + "properties": { + "algo": { + "type": "string" + }, + "hash": { + "type": "string" + }, + "created": { + "type": "string" + }, + "issuer": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algo", + "hash", + "created", + "issuer" + ] + }, + "RubyGemspec": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "RustCargoAuditEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source" + ] + }, + "RustCargoLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + }, + "checksum": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "checksum", + "dependencies" + ] + }, + "Schema": { + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "version", + "url" + ] + }, + "Source": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "supplier": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "metadata" + ] + }, + "SwiftPackageManagerLockEntry": { + "properties": { + "revision": { + "type": "string" + } + }, + "type": "object", + "required": [ + "revision" + ] + }, + "SwiplpackPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "packager": { + "type": "string" + }, + "packagerEmail": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "packager", + "packagerEmail", + "homepage", + "dependencies" + ] + }, + "TerraformLockProviderEntry": { + "properties": { + "url": { + "type": "string" + }, + "constraints": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "url", + "constraints", + "version", + "hashes" + ] + }, + "WordpressPluginEntry": { + "properties": { + "pluginInstallDirectory": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorUri": { + "type": "string" + } + }, + "type": "object", + "required": [ + "pluginInstallDirectory" + ] + }, + "cpes": { + "items": { + "$ref": "#/$defs/CPE" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/License" + }, + "type": "array" + } + } +} diff --git a/schema/json/schema-16.0.38.json b/schema/json/schema-16.0.38.json new file mode 100644 index 00000000000..ef868a71250 --- /dev/null +++ b/schema/json/schema-16.0.38.json @@ -0,0 +1,3319 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "anchore.io/schema/syft/json/16.0.38/document", + "$ref": "#/$defs/Document", + "$defs": { + "AlpmDbEntry": { + "properties": { + "basepackage": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "packager": { + "type": "string" + }, + "url": { + "type": "string" + }, + "validation": { + "type": "string" + }, + "reason": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "backup": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "basepackage", + "package", + "version", + "description", + "architecture", + "size", + "packager", + "url", + "validation", + "reason", + "files", + "backup" + ] + }, + "AlpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "type": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "gid": { + "type": "string" + }, + "time": { + "type": "string", + "format": "date-time" + }, + "size": { + "type": "string" + }, + "link": { + "type": "string" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object" + }, + "ApkDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "originPackage": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "version": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "installedSize": { + "type": "integer" + }, + "pullDependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "pullChecksum": { + "type": "string" + }, + "gitCommitOfApkPort": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/ApkFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "originPackage", + "maintainer", + "version", + "architecture", + "url", + "description", + "size", + "installedSize", + "pullDependencies", + "provides", + "pullChecksum", + "gitCommitOfApkPort", + "files" + ] + }, + "ApkFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "ownerUid": { + "type": "string" + }, + "ownerGid": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "BinarySignature": { + "properties": { + "matches": { + "items": { + "$ref": "#/$defs/ClassifierMatch" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "matches" + ] + }, + "BitnamiSbomEntry": { + "properties": { + "name": { + "type": "string" + }, + "arch": { + "type": "string" + }, + "distro": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "arch", + "distro", + "revision", + "version", + "path", + "files" + ] + }, + "CConanFileEntry": { + "properties": { + "ref": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanInfoEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "build_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "py_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "options": { + "$ref": "#/$defs/KeyValues" + }, + "path": { + "type": "string" + }, + "context": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockV2Entry": { + "properties": { + "ref": { + "type": "string" + }, + "packageID": { + "type": "string" + }, + "username": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "recipeRevision": { + "type": "string" + }, + "packageRevision": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CPE": { + "properties": { + "cpe": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "cpe" + ] + }, + "ClassifierMatch": { + "properties": { + "classifier": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Location" + } + }, + "type": "object", + "required": [ + "classifier", + "location" + ] + }, + "CocoaPodfileLockEntry": { + "properties": { + "checksum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "checksum" + ] + }, + "CondaLink": { + "properties": { + "source": { + "type": "string" + }, + "type": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "source", + "type" + ] + }, + "CondaMetadataEntry": { + "properties": { + "arch": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "build": { + "type": "string" + }, + "build_number": { + "type": "integer" + }, + "channel": { + "type": "string" + }, + "subdir": { + "type": "string" + }, + "noarch": { + "type": "string" + }, + "license": { + "type": "string" + }, + "license_family": { + "type": "string" + }, + "md5": { + "type": "string" + }, + "sha256": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "timestamp": { + "type": "integer" + }, + "fn": { + "type": "string" + }, + "url": { + "type": "string" + }, + "extracted_package_dir": { + "type": "string" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "paths_data": { + "$ref": "#/$defs/CondaPathsData" + }, + "link": { + "$ref": "#/$defs/CondaLink" + } + }, + "type": "object", + "required": [ + "name", + "version", + "build", + "build_number" + ] + }, + "CondaPathData": { + "properties": { + "_path": { + "type": "string" + }, + "path_type": { + "type": "string" + }, + "sha256": { + "type": "string" + }, + "sha256_in_prefix": { + "type": "string" + }, + "size_in_bytes": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "_path", + "path_type", + "sha256", + "sha256_in_prefix", + "size_in_bytes" + ] + }, + "CondaPathsData": { + "properties": { + "paths_version": { + "type": "integer" + }, + "paths": { + "items": { + "$ref": "#/$defs/CondaPathData" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "paths_version", + "paths" + ] + }, + "Coordinates": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "DartPubspec": { + "properties": { + "homepage": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "documentation": { + "type": "string" + }, + "publish_to": { + "type": "string" + }, + "environment": { + "$ref": "#/$defs/DartPubspecEnvironment" + }, + "platforms": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ignored_advisories": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "DartPubspecEnvironment": { + "properties": { + "sdk": { + "type": "string" + }, + "flutter": { + "type": "string" + } + }, + "type": "object" + }, + "DartPubspecLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hosted_url": { + "type": "string" + }, + "vcs_url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Descriptor": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "configuration": true + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Digest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "Document": { + "properties": { + "artifacts": { + "items": { + "$ref": "#/$defs/Package" + }, + "type": "array" + }, + "artifactRelationships": { + "items": { + "$ref": "#/$defs/Relationship" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/File" + }, + "type": "array" + }, + "source": { + "$ref": "#/$defs/Source" + }, + "distro": { + "$ref": "#/$defs/LinuxRelease" + }, + "descriptor": { + "$ref": "#/$defs/Descriptor" + }, + "schema": { + "$ref": "#/$defs/Schema" + } + }, + "type": "object", + "required": [ + "artifacts", + "artifactRelationships", + "source", + "distro", + "descriptor", + "schema" + ] + }, + "DotnetDepsEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "sha512": { + "type": "string" + }, + "hashPath": { + "type": "string" + }, + "executables": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "path", + "sha512", + "hashPath" + ] + }, + "DotnetPackagesLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "contentHash": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "contentHash", + "type" + ] + }, + "DotnetPortableExecutableEntry": { + "properties": { + "assemblyVersion": { + "type": "string" + }, + "legalCopyright": { + "type": "string" + }, + "comments": { + "type": "string" + }, + "internalName": { + "type": "string" + }, + "companyName": { + "type": "string" + }, + "productName": { + "type": "string" + }, + "productVersion": { + "type": "string" + } + }, + "type": "object", + "required": [ + "assemblyVersion", + "legalCopyright", + "companyName", + "productName", + "productVersion" + ] + }, + "DpkgArchiveEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "isConfigFile": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "path", + "isConfigFile" + ] + }, + "ELFSecurityFeatures": { + "properties": { + "symbolTableStripped": { + "type": "boolean" + }, + "stackCanary": { + "type": "boolean" + }, + "nx": { + "type": "boolean" + }, + "relRO": { + "type": "string" + }, + "pie": { + "type": "boolean" + }, + "dso": { + "type": "boolean" + }, + "safeStack": { + "type": "boolean" + }, + "cfi": { + "type": "boolean" + }, + "fortify": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "symbolTableStripped", + "nx", + "relRO", + "pie", + "dso" + ] + }, + "ElfBinaryPackageNoteJsonPayload": { + "properties": { + "type": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "osCPE": { + "type": "string" + }, + "os": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "system": { + "type": "string" + }, + "vendor": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "commit": { + "type": "string" + } + }, + "type": "object" + }, + "ElixirMixLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "ErlangRebarLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "Executable": { + "properties": { + "format": { + "type": "string" + }, + "hasExports": { + "type": "boolean" + }, + "hasEntrypoint": { + "type": "boolean" + }, + "importedLibraries": { + "items": { + "type": "string" + }, + "type": "array" + }, + "elfSecurityFeatures": { + "$ref": "#/$defs/ELFSecurityFeatures" + } + }, + "type": "object", + "required": [ + "format", + "hasExports", + "hasEntrypoint", + "importedLibraries" + ] + }, + "File": { + "properties": { + "id": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Coordinates" + }, + "metadata": { + "$ref": "#/$defs/FileMetadataEntry" + }, + "contents": { + "type": "string" + }, + "digests": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/FileLicense" + }, + "type": "array" + }, + "executable": { + "$ref": "#/$defs/Executable" + }, + "unknowns": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "id", + "location" + ] + }, + "FileLicense": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "evidence": { + "$ref": "#/$defs/FileLicenseEvidence" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type" + ] + }, + "FileLicenseEvidence": { + "properties": { + "confidence": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "extent": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "confidence", + "offset", + "extent" + ] + }, + "FileMetadataEntry": { + "properties": { + "mode": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "userID": { + "type": "integer" + }, + "groupID": { + "type": "integer" + }, + "mimeType": { + "type": "string" + }, + "size": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "mode", + "type", + "userID", + "groupID", + "mimeType", + "size" + ] + }, + "GithubActionsUseStatement": { + "properties": { + "value": { + "type": "string" + }, + "comment": { + "type": "string" + } + }, + "type": "object", + "required": [ + "value" + ] + }, + "GoModuleBuildinfoEntry": { + "properties": { + "goBuildSettings": { + "$ref": "#/$defs/KeyValues" + }, + "goCompiledVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "h1Digest": { + "type": "string" + }, + "mainModule": { + "type": "string" + }, + "goCryptoSettings": { + "items": { + "type": "string" + }, + "type": "array" + }, + "goExperiments": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "goCompiledVersion", + "architecture" + ] + }, + "GoModuleEntry": { + "properties": { + "h1Digest": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackEntry": { + "properties": { + "pkgHash": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackLockEntry": { + "properties": { + "pkgHash": { + "type": "string" + }, + "snapshotURL": { + "type": "string" + } + }, + "type": "object" + }, + "HomebrewFormula": { + "properties": { + "tap": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "IDLikes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "JavaArchive": { + "properties": { + "virtualPath": { + "type": "string" + }, + "manifest": { + "$ref": "#/$defs/JavaManifest" + }, + "pomProperties": { + "$ref": "#/$defs/JavaPomProperties" + }, + "pomProject": { + "$ref": "#/$defs/JavaPomProject" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "virtualPath" + ] + }, + "JavaJvmInstallation": { + "properties": { + "release": { + "$ref": "#/$defs/JavaVMRelease" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "release", + "files" + ] + }, + "JavaManifest": { + "properties": { + "main": { + "$ref": "#/$defs/KeyValues" + }, + "sections": { + "items": { + "$ref": "#/$defs/KeyValues" + }, + "type": "array" + } + }, + "type": "object" + }, + "JavaPomParent": { + "properties": { + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object", + "required": [ + "groupId", + "artifactId", + "version" + ] + }, + "JavaPomProject": { + "properties": { + "path": { + "type": "string" + }, + "parent": { + "$ref": "#/$defs/JavaPomParent" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "groupId", + "artifactId", + "version", + "name" + ] + }, + "JavaPomProperties": { + "properties": { + "path": { + "type": "string" + }, + "name": { + "type": "string" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "extraFields": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "name", + "groupId", + "artifactId", + "version" + ] + }, + "JavaVMRelease": { + "properties": { + "implementor": { + "type": "string" + }, + "implementorVersion": { + "type": "string" + }, + "javaRuntimeVersion": { + "type": "string" + }, + "javaVersion": { + "type": "string" + }, + "javaVersionDate": { + "type": "string" + }, + "libc": { + "type": "string" + }, + "modules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "osArch": { + "type": "string" + }, + "osName": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "source": { + "type": "string" + }, + "buildSource": { + "type": "string" + }, + "buildSourceRepo": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "fullVersion": { + "type": "string" + }, + "semanticVersion": { + "type": "string" + }, + "buildInfo": { + "type": "string" + }, + "jvmVariant": { + "type": "string" + }, + "jvmVersion": { + "type": "string" + }, + "imageType": { + "type": "string" + }, + "buildType": { + "type": "string" + } + }, + "type": "object" + }, + "JavascriptNpmPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "private": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "homepage", + "description", + "url", + "private" + ] + }, + "JavascriptNpmPackageLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "JavascriptYarnLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "KeyValue": { + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "key", + "value" + ] + }, + "KeyValues": { + "items": { + "$ref": "#/$defs/KeyValue" + }, + "type": "array" + }, + "License": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "urls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "contents": { + "type": "string" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type", + "urls", + "locations" + ] + }, + "LinuxKernelArchive": { + "properties": { + "name": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "version": { + "type": "string" + }, + "extendedVersion": { + "type": "string" + }, + "buildTime": { + "type": "string" + }, + "author": { + "type": "string" + }, + "format": { + "type": "string" + }, + "rwRootFS": { + "type": "boolean" + }, + "swapDevice": { + "type": "integer" + }, + "rootDevice": { + "type": "integer" + }, + "videoMode": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "architecture", + "version" + ] + }, + "LinuxKernelModule": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "path": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "license": { + "type": "string" + }, + "kernelVersion": { + "type": "string" + }, + "versionMagic": { + "type": "string" + }, + "parameters": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/LinuxKernelModuleParameter" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "LinuxKernelModuleParameter": { + "properties": { + "type": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "LinuxRelease": { + "properties": { + "prettyName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idLike": { + "$ref": "#/$defs/IDLikes" + }, + "version": { + "type": "string" + }, + "versionID": { + "type": "string" + }, + "versionCodename": { + "type": "string" + }, + "buildID": { + "type": "string" + }, + "imageID": { + "type": "string" + }, + "imageVersion": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "variantID": { + "type": "string" + }, + "homeURL": { + "type": "string" + }, + "supportURL": { + "type": "string" + }, + "bugReportURL": { + "type": "string" + }, + "privacyPolicyURL": { + "type": "string" + }, + "cpeName": { + "type": "string" + }, + "supportEnd": { + "type": "string" + }, + "extendedSupport": { + "type": "boolean" + } + }, + "type": "object" + }, + "Location": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + }, + "accessPath": { + "type": "string" + }, + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "accessPath" + ] + }, + "LuarocksPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "dependencies": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "license", + "homepage", + "description", + "url", + "dependencies" + ] + }, + "MicrosoftKbPatch": { + "properties": { + "product_id": { + "type": "string" + }, + "kb": { + "type": "string" + } + }, + "type": "object", + "required": [ + "product_id", + "kb" + ] + }, + "NixDerivation": { + "properties": { + "path": { + "type": "string" + }, + "system": { + "type": "string" + }, + "inputDerivations": { + "items": { + "$ref": "#/$defs/NixDerivationReference" + }, + "type": "array" + }, + "inputSources": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "NixDerivationReference": { + "properties": { + "path": { + "type": "string" + }, + "outputs": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "NixStoreEntry": { + "properties": { + "path": { + "type": "string" + }, + "output": { + "type": "string" + }, + "outputHash": { + "type": "string" + }, + "derivation": { + "$ref": "#/$defs/NixDerivation" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "outputHash" + ] + }, + "OpamPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "url": { + "type": "string" + }, + "checksum": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "licenses", + "url", + "checksum", + "homepage", + "dependencies" + ] + }, + "Package": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "foundBy": { + "type": "string" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "licenses": { + "$ref": "#/$defs/licenses" + }, + "language": { + "type": "string" + }, + "cpes": { + "$ref": "#/$defs/cpes" + }, + "purl": { + "type": "string" + }, + "metadataType": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/AlpmDbEntry" + }, + { + "$ref": "#/$defs/ApkDbEntry" + }, + { + "$ref": "#/$defs/BinarySignature" + }, + { + "$ref": "#/$defs/BitnamiSbomEntry" + }, + { + "$ref": "#/$defs/CConanFileEntry" + }, + { + "$ref": "#/$defs/CConanInfoEntry" + }, + { + "$ref": "#/$defs/CConanLockEntry" + }, + { + "$ref": "#/$defs/CConanLockV2Entry" + }, + { + "$ref": "#/$defs/CocoaPodfileLockEntry" + }, + { + "$ref": "#/$defs/CondaMetadataEntry" + }, + { + "$ref": "#/$defs/DartPubspec" + }, + { + "$ref": "#/$defs/DartPubspecLockEntry" + }, + { + "$ref": "#/$defs/DotnetDepsEntry" + }, + { + "$ref": "#/$defs/DotnetPackagesLockEntry" + }, + { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + }, + { + "$ref": "#/$defs/DpkgArchiveEntry" + }, + { + "$ref": "#/$defs/DpkgDbEntry" + }, + { + "$ref": "#/$defs/ElfBinaryPackageNoteJsonPayload" + }, + { + "$ref": "#/$defs/ElixirMixLockEntry" + }, + { + "$ref": "#/$defs/ErlangRebarLockEntry" + }, + { + "$ref": "#/$defs/GithubActionsUseStatement" + }, + { + "$ref": "#/$defs/GoModuleBuildinfoEntry" + }, + { + "$ref": "#/$defs/GoModuleEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackLockEntry" + }, + { + "$ref": "#/$defs/HomebrewFormula" + }, + { + "$ref": "#/$defs/JavaArchive" + }, + { + "$ref": "#/$defs/JavaJvmInstallation" + }, + { + "$ref": "#/$defs/JavascriptNpmPackage" + }, + { + "$ref": "#/$defs/JavascriptNpmPackageLockEntry" + }, + { + "$ref": "#/$defs/JavascriptYarnLockEntry" + }, + { + "$ref": "#/$defs/LinuxKernelArchive" + }, + { + "$ref": "#/$defs/LinuxKernelModule" + }, + { + "$ref": "#/$defs/LuarocksPackage" + }, + { + "$ref": "#/$defs/MicrosoftKbPatch" + }, + { + "$ref": "#/$defs/NixStoreEntry" + }, + { + "$ref": "#/$defs/OpamPackage" + }, + { + "$ref": "#/$defs/PeBinary" + }, + { + "$ref": "#/$defs/PhpComposerInstalledEntry" + }, + { + "$ref": "#/$defs/PhpComposerLockEntry" + }, + { + "$ref": "#/$defs/PhpPearEntry" + }, + { + "$ref": "#/$defs/PhpPeclEntry" + }, + { + "$ref": "#/$defs/PortageDbEntry" + }, + { + "$ref": "#/$defs/PythonPackage" + }, + { + "$ref": "#/$defs/PythonPipRequirementsEntry" + }, + { + "$ref": "#/$defs/PythonPipfileLockEntry" + }, + { + "$ref": "#/$defs/PythonPoetryLockEntry" + }, + { + "$ref": "#/$defs/PythonUvLockEntry" + }, + { + "$ref": "#/$defs/RDescription" + }, + { + "$ref": "#/$defs/RpmArchive" + }, + { + "$ref": "#/$defs/RpmDbEntry" + }, + { + "$ref": "#/$defs/RubyGemspec" + }, + { + "$ref": "#/$defs/RustCargoAuditEntry" + }, + { + "$ref": "#/$defs/RustCargoLockEntry" + }, + { + "$ref": "#/$defs/SwiftPackageManagerLockEntry" + }, + { + "$ref": "#/$defs/SwiplpackPackage" + }, + { + "$ref": "#/$defs/TerraformLockProviderEntry" + }, + { + "$ref": "#/$defs/WordpressPluginEntry" + } + ] + } + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "foundBy", + "locations", + "licenses", + "language", + "cpes", + "purl" + ] + }, + "PeBinary": { + "properties": { + "VersionResources": { + "$ref": "#/$defs/KeyValues" + } + }, + "type": "object", + "required": [ + "VersionResources" + ] + }, + "PhpComposerAuthors": { + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name" + ] + }, + "PhpComposerExternalReference": { + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "shasum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "type", + "url", + "reference" + ] + }, + "PhpComposerInstalledEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpComposerLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpPearEntry": { + "properties": { + "name": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PhpPeclEntry": { + "properties": { + "name": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PortageDbEntry": { + "properties": { + "installedSize": { + "type": "integer" + }, + "licenses": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PortageFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "installedSize", + "files" + ] + }, + "PortageFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonDirectURLOriginInfo": { + "properties": { + "url": { + "type": "string" + }, + "commitId": { + "type": "string" + }, + "vcs": { + "type": "string" + } + }, + "type": "object", + "required": [ + "url" + ] + }, + "PythonFileDigest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "PythonFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/PythonFileDigest" + }, + "size": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PythonFileRecord" + }, + "type": "array" + }, + "sitePackagesRootPath": { + "type": "string" + }, + "topLevelPackages": { + "items": { + "type": "string" + }, + "type": "array" + }, + "directUrlOrigin": { + "$ref": "#/$defs/PythonDirectURLOriginInfo" + }, + "requiresPython": { + "type": "string" + }, + "requiresDist": { + "items": { + "type": "string" + }, + "type": "array" + }, + "providesExtra": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "platform", + "sitePackagesRootPath" + ] + }, + "PythonPipRequirementsEntry": { + "properties": { + "name": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + }, + "versionConstraint": { + "type": "string" + }, + "url": { + "type": "string" + }, + "markers": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "versionConstraint" + ] + }, + "PythonPipfileLockEntry": { + "properties": { + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "index": { + "type": "string" + } + }, + "type": "object", + "required": [ + "hashes", + "index" + ] + }, + "PythonPoetryLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "optional" + ] + }, + "PythonPoetryLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonPoetryLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonPoetryLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonPoetryLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "PythonUvLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "optional" + ] + }, + "PythonUvLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonUvLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonUvLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonUvLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "RDescription": { + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "url": { + "items": { + "type": "string" + }, + "type": "array" + }, + "repository": { + "type": "string" + }, + "built": { + "type": "string" + }, + "needsCompilation": { + "type": "boolean" + }, + "imports": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "suggests": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "Relationship": { + "properties": { + "parent": { + "type": "string" + }, + "child": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "parent", + "child", + "type" + ] + }, + "RpmArchive": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "signatures": { + "items": { + "$ref": "#/$defs/RpmSignature" + }, + "type": "array" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmDbEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "signatures": { + "items": { + "$ref": "#/$defs/RpmSignature" + }, + "type": "array" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "userName": { + "type": "string" + }, + "groupName": { + "type": "string" + }, + "flags": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "mode", + "size", + "digest", + "userName", + "groupName", + "flags" + ] + }, + "RpmSignature": { + "properties": { + "algo": { + "type": "string" + }, + "hash": { + "type": "string" + }, + "created": { + "type": "string" + }, + "issuer": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algo", + "hash", + "created", + "issuer" + ] + }, + "RubyGemspec": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "RustCargoAuditEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source" + ] + }, + "RustCargoLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + }, + "checksum": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "checksum", + "dependencies" + ] + }, + "Schema": { + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "version", + "url" + ] + }, + "Source": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "supplier": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "metadata" + ] + }, + "SwiftPackageManagerLockEntry": { + "properties": { + "revision": { + "type": "string" + } + }, + "type": "object", + "required": [ + "revision" + ] + }, + "SwiplpackPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "packager": { + "type": "string" + }, + "packagerEmail": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "packager", + "packagerEmail", + "homepage", + "dependencies" + ] + }, + "TerraformLockProviderEntry": { + "properties": { + "url": { + "type": "string" + }, + "constraints": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "url", + "constraints", + "version", + "hashes" + ] + }, + "WordpressPluginEntry": { + "properties": { + "pluginInstallDirectory": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorUri": { + "type": "string" + } + }, + "type": "object", + "required": [ + "pluginInstallDirectory" + ] + }, + "cpes": { + "items": { + "$ref": "#/$defs/CPE" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/License" + }, + "type": "array" + } + } +} diff --git a/schema/json/schema-16.0.39.json b/schema/json/schema-16.0.39.json new file mode 100644 index 00000000000..ce190f88520 --- /dev/null +++ b/schema/json/schema-16.0.39.json @@ -0,0 +1,3345 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "anchore.io/schema/syft/json/16.0.39/document", + "$ref": "#/$defs/Document", + "$defs": { + "AlpmDbEntry": { + "properties": { + "basepackage": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "packager": { + "type": "string" + }, + "url": { + "type": "string" + }, + "validation": { + "type": "string" + }, + "reason": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "backup": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "basepackage", + "package", + "version", + "description", + "architecture", + "size", + "packager", + "url", + "validation", + "reason", + "files", + "backup" + ] + }, + "AlpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "type": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "gid": { + "type": "string" + }, + "time": { + "type": "string", + "format": "date-time" + }, + "size": { + "type": "string" + }, + "link": { + "type": "string" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object" + }, + "ApkDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "originPackage": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "version": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "installedSize": { + "type": "integer" + }, + "pullDependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "pullChecksum": { + "type": "string" + }, + "gitCommitOfApkPort": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/ApkFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "originPackage", + "maintainer", + "version", + "architecture", + "url", + "description", + "size", + "installedSize", + "pullDependencies", + "provides", + "pullChecksum", + "gitCommitOfApkPort", + "files" + ] + }, + "ApkFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "ownerUid": { + "type": "string" + }, + "ownerGid": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "BinarySignature": { + "properties": { + "matches": { + "items": { + "$ref": "#/$defs/ClassifierMatch" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "matches" + ] + }, + "BitnamiSbomEntry": { + "properties": { + "name": { + "type": "string" + }, + "arch": { + "type": "string" + }, + "distro": { + "type": "string" + }, + "revision": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "arch", + "distro", + "revision", + "version", + "path", + "files" + ] + }, + "CConanFileEntry": { + "properties": { + "ref": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanInfoEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockEntry": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "build_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "py_requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "options": { + "$ref": "#/$defs/KeyValues" + }, + "path": { + "type": "string" + }, + "context": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CConanLockV2Entry": { + "properties": { + "ref": { + "type": "string" + }, + "packageID": { + "type": "string" + }, + "username": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "recipeRevision": { + "type": "string" + }, + "packageRevision": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "CPE": { + "properties": { + "cpe": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "cpe" + ] + }, + "ClassifierMatch": { + "properties": { + "classifier": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Location" + } + }, + "type": "object", + "required": [ + "classifier", + "location" + ] + }, + "CocoaPodfileLockEntry": { + "properties": { + "checksum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "checksum" + ] + }, + "CondaLink": { + "properties": { + "source": { + "type": "string" + }, + "type": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "source", + "type" + ] + }, + "CondaMetadataEntry": { + "properties": { + "arch": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "build": { + "type": "string" + }, + "build_number": { + "type": "integer" + }, + "channel": { + "type": "string" + }, + "subdir": { + "type": "string" + }, + "noarch": { + "type": "string" + }, + "license": { + "type": "string" + }, + "license_family": { + "type": "string" + }, + "md5": { + "type": "string" + }, + "sha256": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "timestamp": { + "type": "integer" + }, + "fn": { + "type": "string" + }, + "url": { + "type": "string" + }, + "extracted_package_dir": { + "type": "string" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "paths_data": { + "$ref": "#/$defs/CondaPathsData" + }, + "link": { + "$ref": "#/$defs/CondaLink" + } + }, + "type": "object", + "required": [ + "name", + "version", + "build", + "build_number" + ] + }, + "CondaPathData": { + "properties": { + "_path": { + "type": "string" + }, + "path_type": { + "type": "string" + }, + "sha256": { + "type": "string" + }, + "sha256_in_prefix": { + "type": "string" + }, + "size_in_bytes": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "_path", + "path_type", + "sha256", + "sha256_in_prefix", + "size_in_bytes" + ] + }, + "CondaPathsData": { + "properties": { + "paths_version": { + "type": "integer" + }, + "paths": { + "items": { + "$ref": "#/$defs/CondaPathData" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "paths_version", + "paths" + ] + }, + "Coordinates": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "DartPubspec": { + "properties": { + "homepage": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "documentation": { + "type": "string" + }, + "publish_to": { + "type": "string" + }, + "environment": { + "$ref": "#/$defs/DartPubspecEnvironment" + }, + "platforms": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ignored_advisories": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "DartPubspecEnvironment": { + "properties": { + "sdk": { + "type": "string" + }, + "flutter": { + "type": "string" + } + }, + "type": "object" + }, + "DartPubspecLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hosted_url": { + "type": "string" + }, + "vcs_url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Descriptor": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "configuration": true + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Digest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "Document": { + "properties": { + "artifacts": { + "items": { + "$ref": "#/$defs/Package" + }, + "type": "array" + }, + "artifactRelationships": { + "items": { + "$ref": "#/$defs/Relationship" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/File" + }, + "type": "array" + }, + "source": { + "$ref": "#/$defs/Source" + }, + "distro": { + "$ref": "#/$defs/LinuxRelease" + }, + "descriptor": { + "$ref": "#/$defs/Descriptor" + }, + "schema": { + "$ref": "#/$defs/Schema" + } + }, + "type": "object", + "required": [ + "artifacts", + "artifactRelationships", + "source", + "distro", + "descriptor", + "schema" + ] + }, + "DotnetDepsEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "sha512": { + "type": "string" + }, + "hashPath": { + "type": "string" + }, + "executables": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "path", + "sha512", + "hashPath" + ] + }, + "DotnetPackagesLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "contentHash": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "contentHash", + "type" + ] + }, + "DotnetPortableExecutableEntry": { + "properties": { + "assemblyVersion": { + "type": "string" + }, + "legalCopyright": { + "type": "string" + }, + "comments": { + "type": "string" + }, + "internalName": { + "type": "string" + }, + "companyName": { + "type": "string" + }, + "productName": { + "type": "string" + }, + "productVersion": { + "type": "string" + } + }, + "type": "object", + "required": [ + "assemblyVersion", + "legalCopyright", + "companyName", + "productName", + "productVersion" + ] + }, + "DpkgArchiveEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgDbEntry": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "DpkgFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "isConfigFile": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "path", + "isConfigFile" + ] + }, + "ELFSecurityFeatures": { + "properties": { + "symbolTableStripped": { + "type": "boolean" + }, + "stackCanary": { + "type": "boolean" + }, + "nx": { + "type": "boolean" + }, + "relRO": { + "type": "string" + }, + "pie": { + "type": "boolean" + }, + "dso": { + "type": "boolean" + }, + "safeStack": { + "type": "boolean" + }, + "cfi": { + "type": "boolean" + }, + "fortify": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "symbolTableStripped", + "nx", + "relRO", + "pie", + "dso" + ] + }, + "ElfBinaryPackageNoteJsonPayload": { + "properties": { + "type": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "osCPE": { + "type": "string" + }, + "os": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "system": { + "type": "string" + }, + "vendor": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "commit": { + "type": "string" + } + }, + "type": "object" + }, + "ElixirMixLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "ErlangRebarLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "Executable": { + "properties": { + "format": { + "type": "string" + }, + "hasExports": { + "type": "boolean" + }, + "hasEntrypoint": { + "type": "boolean" + }, + "importedLibraries": { + "items": { + "type": "string" + }, + "type": "array" + }, + "elfSecurityFeatures": { + "$ref": "#/$defs/ELFSecurityFeatures" + } + }, + "type": "object", + "required": [ + "format", + "hasExports", + "hasEntrypoint", + "importedLibraries" + ] + }, + "File": { + "properties": { + "id": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Coordinates" + }, + "metadata": { + "$ref": "#/$defs/FileMetadataEntry" + }, + "contents": { + "type": "string" + }, + "digests": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/FileLicense" + }, + "type": "array" + }, + "executable": { + "$ref": "#/$defs/Executable" + }, + "unknowns": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "id", + "location" + ] + }, + "FileLicense": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "evidence": { + "$ref": "#/$defs/FileLicenseEvidence" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type" + ] + }, + "FileLicenseEvidence": { + "properties": { + "confidence": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "extent": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "confidence", + "offset", + "extent" + ] + }, + "FileMetadataEntry": { + "properties": { + "mode": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "userID": { + "type": "integer" + }, + "groupID": { + "type": "integer" + }, + "mimeType": { + "type": "string" + }, + "size": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "mode", + "type", + "userID", + "groupID", + "mimeType", + "size" + ] + }, + "GithubActionsUseStatement": { + "properties": { + "value": { + "type": "string" + }, + "comment": { + "type": "string" + } + }, + "type": "object", + "required": [ + "value" + ] + }, + "GoModuleBuildinfoEntry": { + "properties": { + "goBuildSettings": { + "$ref": "#/$defs/KeyValues" + }, + "goCompiledVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "h1Digest": { + "type": "string" + }, + "mainModule": { + "type": "string" + }, + "goCryptoSettings": { + "items": { + "type": "string" + }, + "type": "array" + }, + "goExperiments": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "goCompiledVersion", + "architecture" + ] + }, + "GoModuleEntry": { + "properties": { + "h1Digest": { + "type": "string" + } + }, + "type": "object" + }, + "GoSourceEntry": { + "properties": { + "h1Digest": { + "type": "string" + }, + "os": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "buildTags": { + "type": "string" + }, + "cgoEnabled": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "cgoEnabled" + ] + }, + "HaskellHackageStackEntry": { + "properties": { + "pkgHash": { + "type": "string" + } + }, + "type": "object" + }, + "HaskellHackageStackLockEntry": { + "properties": { + "pkgHash": { + "type": "string" + }, + "snapshotURL": { + "type": "string" + } + }, + "type": "object" + }, + "HomebrewFormula": { + "properties": { + "tap": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "IDLikes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "JavaArchive": { + "properties": { + "virtualPath": { + "type": "string" + }, + "manifest": { + "$ref": "#/$defs/JavaManifest" + }, + "pomProperties": { + "$ref": "#/$defs/JavaPomProperties" + }, + "pomProject": { + "$ref": "#/$defs/JavaPomProject" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "virtualPath" + ] + }, + "JavaJvmInstallation": { + "properties": { + "release": { + "$ref": "#/$defs/JavaVMRelease" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "release", + "files" + ] + }, + "JavaManifest": { + "properties": { + "main": { + "$ref": "#/$defs/KeyValues" + }, + "sections": { + "items": { + "$ref": "#/$defs/KeyValues" + }, + "type": "array" + } + }, + "type": "object" + }, + "JavaPomParent": { + "properties": { + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object", + "required": [ + "groupId", + "artifactId", + "version" + ] + }, + "JavaPomProject": { + "properties": { + "path": { + "type": "string" + }, + "parent": { + "$ref": "#/$defs/JavaPomParent" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "groupId", + "artifactId", + "version", + "name" + ] + }, + "JavaPomProperties": { + "properties": { + "path": { + "type": "string" + }, + "name": { + "type": "string" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "extraFields": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "name", + "groupId", + "artifactId", + "version" + ] + }, + "JavaVMRelease": { + "properties": { + "implementor": { + "type": "string" + }, + "implementorVersion": { + "type": "string" + }, + "javaRuntimeVersion": { + "type": "string" + }, + "javaVersion": { + "type": "string" + }, + "javaVersionDate": { + "type": "string" + }, + "libc": { + "type": "string" + }, + "modules": { + "items": { + "type": "string" + }, + "type": "array" + }, + "osArch": { + "type": "string" + }, + "osName": { + "type": "string" + }, + "osVersion": { + "type": "string" + }, + "source": { + "type": "string" + }, + "buildSource": { + "type": "string" + }, + "buildSourceRepo": { + "type": "string" + }, + "sourceRepo": { + "type": "string" + }, + "fullVersion": { + "type": "string" + }, + "semanticVersion": { + "type": "string" + }, + "buildInfo": { + "type": "string" + }, + "jvmVariant": { + "type": "string" + }, + "jvmVersion": { + "type": "string" + }, + "imageType": { + "type": "string" + }, + "buildType": { + "type": "string" + } + }, + "type": "object" + }, + "JavascriptNpmPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "private": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "homepage", + "description", + "url", + "private" + ] + }, + "JavascriptNpmPackageLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "JavascriptYarnLockEntry": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "KeyValue": { + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "key", + "value" + ] + }, + "KeyValues": { + "items": { + "$ref": "#/$defs/KeyValue" + }, + "type": "array" + }, + "License": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "urls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "contents": { + "type": "string" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type", + "urls", + "locations" + ] + }, + "LinuxKernelArchive": { + "properties": { + "name": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "version": { + "type": "string" + }, + "extendedVersion": { + "type": "string" + }, + "buildTime": { + "type": "string" + }, + "author": { + "type": "string" + }, + "format": { + "type": "string" + }, + "rwRootFS": { + "type": "boolean" + }, + "swapDevice": { + "type": "integer" + }, + "rootDevice": { + "type": "integer" + }, + "videoMode": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "architecture", + "version" + ] + }, + "LinuxKernelModule": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "path": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "license": { + "type": "string" + }, + "kernelVersion": { + "type": "string" + }, + "versionMagic": { + "type": "string" + }, + "parameters": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/LinuxKernelModuleParameter" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "LinuxKernelModuleParameter": { + "properties": { + "type": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "type": "object" + }, + "LinuxRelease": { + "properties": { + "prettyName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idLike": { + "$ref": "#/$defs/IDLikes" + }, + "version": { + "type": "string" + }, + "versionID": { + "type": "string" + }, + "versionCodename": { + "type": "string" + }, + "buildID": { + "type": "string" + }, + "imageID": { + "type": "string" + }, + "imageVersion": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "variantID": { + "type": "string" + }, + "homeURL": { + "type": "string" + }, + "supportURL": { + "type": "string" + }, + "bugReportURL": { + "type": "string" + }, + "privacyPolicyURL": { + "type": "string" + }, + "cpeName": { + "type": "string" + }, + "supportEnd": { + "type": "string" + }, + "extendedSupport": { + "type": "boolean" + } + }, + "type": "object" + }, + "Location": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + }, + "accessPath": { + "type": "string" + }, + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "accessPath" + ] + }, + "LuarocksPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "dependencies": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "name", + "version", + "license", + "homepage", + "description", + "url", + "dependencies" + ] + }, + "MicrosoftKbPatch": { + "properties": { + "product_id": { + "type": "string" + }, + "kb": { + "type": "string" + } + }, + "type": "object", + "required": [ + "product_id", + "kb" + ] + }, + "NixDerivation": { + "properties": { + "path": { + "type": "string" + }, + "system": { + "type": "string" + }, + "inputDerivations": { + "items": { + "$ref": "#/$defs/NixDerivationReference" + }, + "type": "array" + }, + "inputSources": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "NixDerivationReference": { + "properties": { + "path": { + "type": "string" + }, + "outputs": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "NixStoreEntry": { + "properties": { + "path": { + "type": "string" + }, + "output": { + "type": "string" + }, + "outputHash": { + "type": "string" + }, + "derivation": { + "$ref": "#/$defs/NixDerivation" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "outputHash" + ] + }, + "OpamPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "url": { + "type": "string" + }, + "checksum": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "licenses", + "url", + "checksum", + "homepage", + "dependencies" + ] + }, + "Package": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "foundBy": { + "type": "string" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "licenses": { + "$ref": "#/$defs/licenses" + }, + "language": { + "type": "string" + }, + "cpes": { + "$ref": "#/$defs/cpes" + }, + "purl": { + "type": "string" + }, + "metadataType": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/AlpmDbEntry" + }, + { + "$ref": "#/$defs/ApkDbEntry" + }, + { + "$ref": "#/$defs/BinarySignature" + }, + { + "$ref": "#/$defs/BitnamiSbomEntry" + }, + { + "$ref": "#/$defs/CConanFileEntry" + }, + { + "$ref": "#/$defs/CConanInfoEntry" + }, + { + "$ref": "#/$defs/CConanLockEntry" + }, + { + "$ref": "#/$defs/CConanLockV2Entry" + }, + { + "$ref": "#/$defs/CocoaPodfileLockEntry" + }, + { + "$ref": "#/$defs/CondaMetadataEntry" + }, + { + "$ref": "#/$defs/DartPubspec" + }, + { + "$ref": "#/$defs/DartPubspecLockEntry" + }, + { + "$ref": "#/$defs/DotnetDepsEntry" + }, + { + "$ref": "#/$defs/DotnetPackagesLockEntry" + }, + { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + }, + { + "$ref": "#/$defs/DpkgArchiveEntry" + }, + { + "$ref": "#/$defs/DpkgDbEntry" + }, + { + "$ref": "#/$defs/ElfBinaryPackageNoteJsonPayload" + }, + { + "$ref": "#/$defs/ElixirMixLockEntry" + }, + { + "$ref": "#/$defs/ErlangRebarLockEntry" + }, + { + "$ref": "#/$defs/GithubActionsUseStatement" + }, + { + "$ref": "#/$defs/GoModuleBuildinfoEntry" + }, + { + "$ref": "#/$defs/GoModuleEntry" + }, + { + "$ref": "#/$defs/GoSourceEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackLockEntry" + }, + { + "$ref": "#/$defs/HomebrewFormula" + }, + { + "$ref": "#/$defs/JavaArchive" + }, + { + "$ref": "#/$defs/JavaJvmInstallation" + }, + { + "$ref": "#/$defs/JavascriptNpmPackage" + }, + { + "$ref": "#/$defs/JavascriptNpmPackageLockEntry" + }, + { + "$ref": "#/$defs/JavascriptYarnLockEntry" + }, + { + "$ref": "#/$defs/LinuxKernelArchive" + }, + { + "$ref": "#/$defs/LinuxKernelModule" + }, + { + "$ref": "#/$defs/LuarocksPackage" + }, + { + "$ref": "#/$defs/MicrosoftKbPatch" + }, + { + "$ref": "#/$defs/NixStoreEntry" + }, + { + "$ref": "#/$defs/OpamPackage" + }, + { + "$ref": "#/$defs/PeBinary" + }, + { + "$ref": "#/$defs/PhpComposerInstalledEntry" + }, + { + "$ref": "#/$defs/PhpComposerLockEntry" + }, + { + "$ref": "#/$defs/PhpPearEntry" + }, + { + "$ref": "#/$defs/PhpPeclEntry" + }, + { + "$ref": "#/$defs/PortageDbEntry" + }, + { + "$ref": "#/$defs/PythonPackage" + }, + { + "$ref": "#/$defs/PythonPipRequirementsEntry" + }, + { + "$ref": "#/$defs/PythonPipfileLockEntry" + }, + { + "$ref": "#/$defs/PythonPoetryLockEntry" + }, + { + "$ref": "#/$defs/PythonUvLockEntry" + }, + { + "$ref": "#/$defs/RDescription" + }, + { + "$ref": "#/$defs/RpmArchive" + }, + { + "$ref": "#/$defs/RpmDbEntry" + }, + { + "$ref": "#/$defs/RubyGemspec" + }, + { + "$ref": "#/$defs/RustCargoAuditEntry" + }, + { + "$ref": "#/$defs/RustCargoLockEntry" + }, + { + "$ref": "#/$defs/SwiftPackageManagerLockEntry" + }, + { + "$ref": "#/$defs/SwiplpackPackage" + }, + { + "$ref": "#/$defs/TerraformLockProviderEntry" + }, + { + "$ref": "#/$defs/WordpressPluginEntry" + } + ] + } + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "foundBy", + "locations", + "licenses", + "language", + "cpes", + "purl" + ] + }, + "PeBinary": { + "properties": { + "VersionResources": { + "$ref": "#/$defs/KeyValues" + } + }, + "type": "object", + "required": [ + "VersionResources" + ] + }, + "PhpComposerAuthors": { + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name" + ] + }, + "PhpComposerExternalReference": { + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "shasum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "type", + "url", + "reference" + ] + }, + "PhpComposerInstalledEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpComposerLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PhpPearEntry": { + "properties": { + "name": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PhpPeclEntry": { + "properties": { + "name": { + "type": "string" + }, + "channel": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "PortageDbEntry": { + "properties": { + "installedSize": { + "type": "integer" + }, + "licenses": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PortageFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "installedSize", + "files" + ] + }, + "PortageFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonDirectURLOriginInfo": { + "properties": { + "url": { + "type": "string" + }, + "commitId": { + "type": "string" + }, + "vcs": { + "type": "string" + } + }, + "type": "object", + "required": [ + "url" + ] + }, + "PythonFileDigest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "PythonFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/PythonFileDigest" + }, + "size": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PythonFileRecord" + }, + "type": "array" + }, + "sitePackagesRootPath": { + "type": "string" + }, + "topLevelPackages": { + "items": { + "type": "string" + }, + "type": "array" + }, + "directUrlOrigin": { + "$ref": "#/$defs/PythonDirectURLOriginInfo" + }, + "requiresPython": { + "type": "string" + }, + "requiresDist": { + "items": { + "type": "string" + }, + "type": "array" + }, + "providesExtra": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "platform", + "sitePackagesRootPath" + ] + }, + "PythonPipRequirementsEntry": { + "properties": { + "name": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + }, + "versionConstraint": { + "type": "string" + }, + "url": { + "type": "string" + }, + "markers": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "versionConstraint" + ] + }, + "PythonPipfileLockEntry": { + "properties": { + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "index": { + "type": "string" + } + }, + "type": "object", + "required": [ + "hashes", + "index" + ] + }, + "PythonPoetryLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "optional" + ] + }, + "PythonPoetryLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonPoetryLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonPoetryLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonPoetryLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "PythonUvLockDependencyEntry": { + "properties": { + "name": { + "type": "string" + }, + "optional": { + "type": "boolean" + }, + "markers": { + "type": "string" + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "optional" + ] + }, + "PythonUvLockEntry": { + "properties": { + "index": { + "type": "string" + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonUvLockDependencyEntry" + }, + "type": "array" + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonUvLockExtraEntry" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ] + }, + "PythonUvLockExtraEntry": { + "properties": { + "name": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ] + }, + "RDescription": { + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "url": { + "items": { + "type": "string" + }, + "type": "array" + }, + "repository": { + "type": "string" + }, + "built": { + "type": "string" + }, + "needsCompilation": { + "type": "boolean" + }, + "imports": { + "items": { + "type": "string" + }, + "type": "array" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array" + }, + "suggests": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object" + }, + "Relationship": { + "properties": { + "parent": { + "type": "string" + }, + "child": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "parent", + "child", + "type" + ] + }, + "RpmArchive": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "signatures": { + "items": { + "$ref": "#/$defs/RpmSignature" + }, + "type": "array" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmDbEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "signatures": { + "items": { + "$ref": "#/$defs/RpmSignature" + }, + "type": "array" + }, + "size": { + "type": "integer" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ] + }, + "RpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "userName": { + "type": "string" + }, + "groupName": { + "type": "string" + }, + "flags": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "mode", + "size", + "digest", + "userName", + "groupName", + "flags" + ] + }, + "RpmSignature": { + "properties": { + "algo": { + "type": "string" + }, + "hash": { + "type": "string" + }, + "created": { + "type": "string" + }, + "issuer": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algo", + "hash", + "created", + "issuer" + ] + }, + "RubyGemspec": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "RustCargoAuditEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source" + ] + }, + "RustCargoLockEntry": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + }, + "checksum": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "checksum", + "dependencies" + ] + }, + "Schema": { + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "version", + "url" + ] + }, + "Source": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "supplier": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "metadata" + ] + }, + "SwiftPackageManagerLockEntry": { + "properties": { + "revision": { + "type": "string" + } + }, + "type": "object", + "required": [ + "revision" + ] + }, + "SwiplpackPackage": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "packager": { + "type": "string" + }, + "packagerEmail": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "packager", + "packagerEmail", + "homepage", + "dependencies" + ] + }, + "TerraformLockProviderEntry": { + "properties": { + "url": { + "type": "string" + }, + "constraints": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "url", + "constraints", + "version", + "hashes" + ] + }, + "WordpressPluginEntry": { + "properties": { + "pluginInstallDirectory": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorUri": { + "type": "string" + } + }, + "type": "object", + "required": [ + "pluginInstallDirectory" + ] + }, + "cpes": { + "items": { + "$ref": "#/$defs/CPE" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/License" + }, + "type": "array" + } + } +} diff --git a/schema/json/schema-16.0.40.json b/schema/json/schema-16.0.40.json new file mode 100644 index 00000000000..cd8198acb3d --- /dev/null +++ b/schema/json/schema-16.0.40.json @@ -0,0 +1,3979 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "anchore.io/schema/syft/json/16.0.40/document", + "$ref": "#/$defs/Document", + "$defs": { + "AlpmDbEntry": { + "properties": { + "basepackage": { + "type": "string", + "description": "BasePackage is the base package name this package was built from (source package in Arch build system)" + }, + "package": { + "type": "string", + "description": "Package is the package name as found in the desc file" + }, + "version": { + "type": "string", + "description": "Version is the package version as found in the desc file" + }, + "description": { + "type": "string", + "description": "Description is a human-readable package description" + }, + "architecture": { + "type": "string", + "description": "Architecture is the target CPU architecture as defined in Arch architecture spec (e.g. x86_64, aarch64, or \"any\" for arch-independent packages)" + }, + "size": { + "type": "integer", + "description": "Size is the installed size in bytes" + }, + "packager": { + "type": "string", + "description": "Packager is the name and email of the person who packaged this (RFC822 format)" + }, + "url": { + "type": "string", + "description": "URL is the upstream project URL" + }, + "validation": { + "type": "string", + "description": "Validation is the validation method used for package integrity (e.g. pgp signature, sha256 checksum)" + }, + "reason": { + "type": "integer", + "description": "Reason is the installation reason tracked by pacman (0=explicitly installed by user, 1=installed as dependency)" + }, + "files": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array", + "description": "Files are the files installed by this package" + }, + "backup": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array", + "description": "Backup is the list of configuration files that pacman backs up before upgrades" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Provides are virtual packages provided by this package (allows other packages to depend on capabilities rather than specific packages)" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Depends are the runtime dependencies required by this package" + } + }, + "type": "object", + "required": [ + "basepackage", + "package", + "version", + "description", + "architecture", + "size", + "packager", + "url", + "validation", + "reason", + "files", + "backup" + ], + "description": "AlpmDBEntry is a struct that represents the package data stored in the pacman flat-file stores for arch linux." + }, + "AlpmFileRecord": { + "properties": { + "path": { + "type": "string", + "description": "Path is the file path relative to the filesystem root" + }, + "type": { + "type": "string", + "description": "Type is the file type (e.g. regular file, directory, symlink)" + }, + "uid": { + "type": "string", + "description": "UID is the file owner user ID as recorded by pacman" + }, + "gid": { + "type": "string", + "description": "GID is the file owner group ID as recorded by pacman" + }, + "time": { + "type": "string", + "format": "date-time", + "description": "Time is the file modification timestamp" + }, + "size": { + "type": "string", + "description": "Size is the file size in bytes" + }, + "link": { + "type": "string", + "description": "Link is the symlink target path if this is a symlink" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array", + "description": "Digests contains file content hashes for integrity verification" + } + }, + "type": "object" + }, + "ApkDbEntry": { + "properties": { + "package": { + "type": "string", + "description": "Package is the package name as found in the installed file" + }, + "originPackage": { + "type": "string", + "description": "OriginPackage is the original source package name this binary was built from (used to track which aport/source built this)" + }, + "maintainer": { + "type": "string", + "description": "Maintainer is the package maintainer name and email" + }, + "version": { + "type": "string", + "description": "Version is the package version as found in the installed file" + }, + "architecture": { + "type": "string", + "description": "Architecture is the target CPU architecture" + }, + "url": { + "type": "string", + "description": "URL is the upstream project URL" + }, + "description": { + "type": "string", + "description": "Description is a human-readable package description" + }, + "size": { + "type": "integer", + "description": "Size is the package archive size in bytes (.apk file size)" + }, + "installedSize": { + "type": "integer", + "description": "InstalledSize is the total size of installed files in bytes" + }, + "pullDependencies": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Dependencies are the runtime dependencies required by this package" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Provides are virtual packages provided by this package (for capability-based dependencies)" + }, + "pullChecksum": { + "type": "string", + "description": "Checksum is the package content checksum for integrity verification" + }, + "gitCommitOfApkPort": { + "type": "string", + "description": "GitCommit is the git commit hash of the APK port definition in Alpine's aports repository" + }, + "files": { + "items": { + "$ref": "#/$defs/ApkFileRecord" + }, + "type": "array", + "description": "Files are the files installed by this package" + } + }, + "type": "object", + "required": [ + "package", + "originPackage", + "maintainer", + "version", + "architecture", + "url", + "description", + "size", + "installedSize", + "pullDependencies", + "provides", + "pullChecksum", + "gitCommitOfApkPort", + "files" + ], + "description": "ApkDBEntry represents all captured data for the alpine linux package manager flat-file store." + }, + "ApkFileRecord": { + "properties": { + "path": { + "type": "string", + "description": "Path is the file path relative to the filesystem root" + }, + "ownerUid": { + "type": "string", + "description": "OwnerUID is the file owner user ID" + }, + "ownerGid": { + "type": "string", + "description": "OwnerGID is the file owner group ID" + }, + "permissions": { + "type": "string", + "description": "Permissions is the file permission mode string (e.g. \"0755\", \"0644\")" + }, + "digest": { + "$ref": "#/$defs/Digest", + "description": "Digest is the file content hash for integrity verification" + } + }, + "type": "object", + "required": [ + "path" + ], + "description": "ApkFileRecord represents a single file listing and metadata from a APK DB entry (which may have many of these file records)." + }, + "BinarySignature": { + "properties": { + "matches": { + "items": { + "$ref": "#/$defs/ClassifierMatch" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "matches" + ], + "description": "BinarySignature represents a set of matched values within a binary file." + }, + "BitnamiSbomEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the package name as found in the Bitnami SPDX file" + }, + "arch": { + "type": "string", + "description": "Architecture is the target CPU architecture (amd64 or arm64 in Bitnami images)" + }, + "distro": { + "type": "string", + "description": "Distro is the distribution name this package is for (base OS like debian, ubuntu, etc.)" + }, + "revision": { + "type": "string", + "description": "Revision is the Bitnami-specific package revision number (incremented for Bitnami rebuilds of same upstream version)" + }, + "version": { + "type": "string", + "description": "Version is the package version as found in the Bitnami SPDX file" + }, + "path": { + "type": "string", + "description": "Path is the installation path in the filesystem where the package is located" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Files are the file paths owned by this package (tracked via SPDX relationships)" + } + }, + "type": "object", + "required": [ + "name", + "arch", + "distro", + "revision", + "version", + "path", + "files" + ], + "description": "BitnamiSBOMEntry represents all captured data from Bitnami packages described in Bitnami' SPDX files." + }, + "CConanFileEntry": { + "properties": { + "ref": { + "type": "string", + "description": "Ref is the package reference string in format name/version@user/channel" + } + }, + "type": "object", + "required": [ + "ref" + ], + "description": "ConanfileEntry represents a single \"Requires\" entry from a conanfile.txt." + }, + "CConanInfoEntry": { + "properties": { + "ref": { + "type": "string", + "description": "Ref is the package reference string in format name/version@user/channel" + }, + "package_id": { + "type": "string", + "description": "PackageID is a unique package variant identifier" + } + }, + "type": "object", + "required": [ + "ref" + ], + "description": "ConaninfoEntry represents a single \"full_requires\" entry from a conaninfo.txt." + }, + "CConanLockEntry": { + "properties": { + "ref": { + "type": "string", + "description": "Ref is the package reference string in format name/version@user/channel" + }, + "package_id": { + "type": "string", + "description": "PackageID is a unique package variant identifier computed from settings/options (static hash in Conan 1.x, can have collisions with complex dependency graphs)" + }, + "prev": { + "type": "string", + "description": "Prev is the previous lock entry reference for versioning" + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Requires are the runtime package dependencies" + }, + "build_requires": { + "items": { + "type": "string" + }, + "type": "array", + "description": "BuildRequires are the build-time dependencies (e.g. cmake, compilers)" + }, + "py_requires": { + "items": { + "type": "string" + }, + "type": "array", + "description": "PythonRequires are the Python dependencies needed for Conan recipes" + }, + "options": { + "$ref": "#/$defs/KeyValues", + "description": "Options are package configuration options as key-value pairs (e.g. shared=True, fPIC=True)" + }, + "path": { + "type": "string", + "description": "Path is the filesystem path to the package in Conan cache" + }, + "context": { + "type": "string", + "description": "Context is the build context information" + } + }, + "type": "object", + "required": [ + "ref" + ], + "description": "ConanV1LockEntry represents a single \"node\" entry from a conan.lock V1 file." + }, + "CConanLockV2Entry": { + "properties": { + "ref": { + "type": "string", + "description": "Ref is the package reference string in format name/version@user/channel" + }, + "packageID": { + "type": "string", + "description": "PackageID is a unique package variant identifier (dynamic in Conan 2.0, more accurate than V1)" + }, + "username": { + "type": "string", + "description": "Username is the Conan user/organization name" + }, + "channel": { + "type": "string", + "description": "Channel is the Conan channel name indicating stability/purpose (e.g. stable, testing, experimental)" + }, + "recipeRevision": { + "type": "string", + "description": "RecipeRevision is a git-like revision hash (RREV) of the recipe" + }, + "packageRevision": { + "type": "string", + "description": "PackageRevision is a git-like revision hash of the built binary package" + }, + "timestamp": { + "type": "string", + "description": "TimeStamp is when this package was built/locked" + } + }, + "type": "object", + "required": [ + "ref" + ], + "description": "ConanV2LockEntry represents a single \"node\" entry from a conan.lock V2 file." + }, + "CPE": { + "properties": { + "cpe": { + "type": "string" + }, + "source": { + "type": "string" + } + }, + "type": "object", + "required": [ + "cpe" + ] + }, + "ClassifierMatch": { + "properties": { + "classifier": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Location" + } + }, + "type": "object", + "required": [ + "classifier", + "location" + ], + "description": "ClassifierMatch represents a single matched value within a binary file and the \"class\" name the search pattern represents." + }, + "CocoaPodfileLockEntry": { + "properties": { + "checksum": { + "type": "string", + "description": "Checksum is the SHA-1 hash of the podspec file for integrity verification (generated via `pod ipc spec ... | openssl sha1`), ensuring all team members use the same pod specification version" + } + }, + "type": "object", + "required": [ + "checksum" + ], + "description": "CocoaPodfileLockEntry represents a single entry from the \"Pods\" section of a Podfile.lock file." + }, + "CondaLink": { + "properties": { + "source": { + "type": "string", + "description": "Source is the original path where the package was extracted from cache." + }, + "type": { + "type": "integer", + "description": "Type indicates the link type (1 for hard link, 2 for soft link, 3 for copy)." + } + }, + "type": "object", + "required": [ + "source", + "type" + ], + "description": "CondaLink represents link metadata from a Conda package's link.json file describing package installation source." + }, + "CondaMetadataEntry": { + "properties": { + "arch": { + "type": "string", + "description": "Arch is the target CPU architecture for the package (e.g., \"arm64\", \"x86_64\")." + }, + "name": { + "type": "string", + "description": "Name is the package name as found in the conda-meta JSON file." + }, + "version": { + "type": "string", + "description": "Version is the package version as found in the conda-meta JSON file." + }, + "build": { + "type": "string", + "description": "Build is the build string identifier (e.g., \"h90dfc92_1014\")." + }, + "build_number": { + "type": "integer", + "description": "BuildNumber is the sequential build number for this version." + }, + "channel": { + "type": "string", + "description": "Channel is the Conda channel URL where the package was retrieved from." + }, + "subdir": { + "type": "string", + "description": "Subdir is the subdirectory within the channel (e.g., \"osx-arm64\", \"linux-64\")." + }, + "noarch": { + "type": "string", + "description": "Noarch indicates if the package is platform-independent (e.g., \"python\", \"generic\")." + }, + "license": { + "type": "string", + "description": "License is the package license identifier." + }, + "license_family": { + "type": "string", + "description": "LicenseFamily is the general license category (e.g., \"MIT\", \"Apache\", \"GPL\")." + }, + "md5": { + "type": "string", + "description": "MD5 is the MD5 hash of the package archive." + }, + "sha256": { + "type": "string", + "description": "SHA256 is the SHA-256 hash of the package archive." + }, + "size": { + "type": "integer", + "description": "Size is the package archive size in bytes." + }, + "timestamp": { + "type": "integer", + "description": "Timestamp is the Unix timestamp when the package was built." + }, + "fn": { + "type": "string", + "description": "Filename is the original package archive filename (e.g., \"zlib-1.2.11-h90dfc92_1014.tar.bz2\")." + }, + "url": { + "type": "string", + "description": "URL is the full download URL for the package archive." + }, + "extracted_package_dir": { + "type": "string", + "description": "ExtractedPackageDir is the local cache directory where the package was extracted." + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Depends is the list of runtime dependencies with version constraints." + }, + "files": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Files is the list of files installed by this package." + }, + "paths_data": { + "$ref": "#/$defs/CondaPathsData", + "description": "PathsData contains detailed file metadata from the paths.json file." + }, + "link": { + "$ref": "#/$defs/CondaLink", + "description": "Link contains installation source metadata from the link.json file." + } + }, + "type": "object", + "required": [ + "name", + "version", + "build", + "build_number" + ], + "description": "CondaMetaPackage represents metadata for a Conda package extracted from the conda-meta/*.json files." + }, + "CondaPathData": { + "properties": { + "_path": { + "type": "string", + "description": "Path is the file path relative to the Conda environment root." + }, + "path_type": { + "type": "string", + "description": "PathType indicates the link type for the file (e.g., \"hardlink\", \"softlink\", \"directory\")." + }, + "sha256": { + "type": "string", + "description": "SHA256 is the SHA-256 hash of the file contents." + }, + "sha256_in_prefix": { + "type": "string", + "description": "SHA256InPrefix is the SHA-256 hash of the file after prefix replacement during installation." + }, + "size_in_bytes": { + "type": "integer", + "description": "SizeInBytes is the file size in bytes." + } + }, + "type": "object", + "required": [ + "_path", + "path_type", + "sha256", + "sha256_in_prefix", + "size_in_bytes" + ], + "description": "CondaPathData represents metadata for a single file within a Conda package from the paths.json file." + }, + "CondaPathsData": { + "properties": { + "paths_version": { + "type": "integer", + "description": "PathsVersion is the schema version of the paths data format." + }, + "paths": { + "items": { + "$ref": "#/$defs/CondaPathData" + }, + "type": "array", + "description": "Paths is the list of file metadata entries for all files in the package." + } + }, + "type": "object", + "required": [ + "paths_version", + "paths" + ], + "description": "CondaPathsData represents the paths.json file structure from a Conda package containing file metadata." + }, + "Coordinates": { + "properties": { + "path": { + "type": "string", + "description": "RealPath is the canonical absolute form of the path accessed (all symbolic links have been followed and relative path components like '.' and '..' have been removed)." + }, + "layerID": { + "type": "string", + "description": "FileSystemID is an ID representing and entire filesystem. For container images, this is a layer digest. For directories or a root filesystem, this is blank." + } + }, + "type": "object", + "required": [ + "path" + ], + "description": "Coordinates contains the minimal information needed to describe how to find a file within any possible source object (e.g." + }, + "DartPubspec": { + "properties": { + "homepage": { + "type": "string", + "description": "Homepage is the package homepage URL" + }, + "repository": { + "type": "string", + "description": "Repository is the source code repository URL" + }, + "documentation": { + "type": "string", + "description": "Documentation is the documentation site URL" + }, + "publish_to": { + "type": "string", + "description": "PublishTo is the package repository to publish to, or \"none\" to prevent accidental publishing" + }, + "environment": { + "$ref": "#/$defs/DartPubspecEnvironment", + "description": "Environment is SDK version constraints for Dart and Flutter" + }, + "platforms": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Platforms are the supported platforms (Android, iOS, web, etc.)" + }, + "ignored_advisories": { + "items": { + "type": "string" + }, + "type": "array", + "description": "IgnoredAdvisories are the security advisories to explicitly ignore for this package" + } + }, + "type": "object", + "description": "DartPubspec is a struct that represents a package described in a pubspec.yaml file" + }, + "DartPubspecEnvironment": { + "properties": { + "sdk": { + "type": "string", + "description": "SDK is the Dart SDK version constraint (e.g. \"\u003e=2.12.0 \u003c3.0.0\")" + }, + "flutter": { + "type": "string", + "description": "Flutter is the Flutter SDK version constraint if this is a Flutter package" + } + }, + "type": "object", + "description": "DartPubspecEnvironment represents SDK version constraints from the environment section of pubspec.yaml." + }, + "DartPubspecLockEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the package name as found in the pubspec.lock file" + }, + "version": { + "type": "string", + "description": "Version is the package version as found in the pubspec.lock file" + }, + "hosted_url": { + "type": "string", + "description": "HostedURL is the URL of the package repository for hosted packages (typically pub.dev, but can be custom repository identified by hosted-url). When PUB_HOSTED_URL environment variable changes, lockfile tracks the source." + }, + "vcs_url": { + "type": "string", + "description": "VcsURL is the URL of the VCS repository for git/path dependencies (for packages fetched from version control systems like Git)" + } + }, + "type": "object", + "required": [ + "name", + "version" + ], + "description": "DartPubspecLockEntry is a struct that represents a single entry found in the \"packages\" section in a Dart pubspec.lock file." + }, + "Descriptor": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "configuration": true + }, + "type": "object", + "required": [ + "name", + "version" + ], + "description": "Descriptor describes what created the document as well as surrounding metadata" + }, + "Digest": { + "properties": { + "algorithm": { + "type": "string", + "description": "Algorithm specifies the hash algorithm used (e.g., \"sha256\", \"md5\")." + }, + "value": { + "type": "string", + "description": "Value is the hexadecimal string representation of the hash." + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ], + "description": "Digest represents a cryptographic hash of file contents." + }, + "Document": { + "properties": { + "artifacts": { + "items": { + "$ref": "#/$defs/Package" + }, + "type": "array" + }, + "artifactRelationships": { + "items": { + "$ref": "#/$defs/Relationship" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/File" + }, + "type": "array" + }, + "source": { + "$ref": "#/$defs/Source" + }, + "distro": { + "$ref": "#/$defs/LinuxRelease" + }, + "descriptor": { + "$ref": "#/$defs/Descriptor" + }, + "schema": { + "$ref": "#/$defs/Schema" + } + }, + "type": "object", + "required": [ + "artifacts", + "artifactRelationships", + "source", + "distro", + "descriptor", + "schema" + ], + "description": "Document represents the syft cataloging findings as a JSON document" + }, + "DotnetDepsEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the package name as found in the deps.json file" + }, + "version": { + "type": "string", + "description": "Version is the package version as found in the deps.json file" + }, + "path": { + "type": "string", + "description": "Path is the relative path to the package within the deps structure (e.g. \"app.metrics/3.0.0\")" + }, + "sha512": { + "type": "string", + "description": "Sha512 is the SHA-512 hash of the NuGet package content WITHOUT the signed content for verification (won't match hash from NuGet API or manual calculation of .nupkg file)" + }, + "hashPath": { + "type": "string", + "description": "HashPath is the relative path to the .nupkg.sha512 hash file (e.g. \"app.metrics.3.0.0.nupkg.sha512\")" + }, + "executables": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + } + }, + "type": "object", + "description": "Executables are the map of .NET Portable Executable files within this package with their version resources" + } + }, + "type": "object", + "required": [ + "name", + "version", + "path", + "sha512", + "hashPath" + ], + "description": "DotnetDepsEntry is a struct that represents a single entry found in the \"libraries\" section in a .NET [*.]deps.json file." + }, + "DotnetPackagesLockEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the package name as found in the packages.lock.json file" + }, + "version": { + "type": "string", + "description": "Version is the package version as found in the packages.lock.json file" + }, + "contentHash": { + "type": "string", + "description": "ContentHash is the hash of the package content for verification" + }, + "type": { + "type": "string", + "description": "Type is the dependency type indicating how this dependency was added (Direct=explicit in project file, Transitive=pulled in by another package, Project=project reference)" + } + }, + "type": "object", + "required": [ + "name", + "version", + "contentHash", + "type" + ], + "description": "DotnetPackagesLockEntry is a struct that represents a single entry found in the \"dependencies\" section in a .NET packages.lock.json file." + }, + "DotnetPortableExecutableEntry": { + "properties": { + "assemblyVersion": { + "type": "string", + "description": "AssemblyVersion is the .NET assembly version number (strong-named version)" + }, + "legalCopyright": { + "type": "string", + "description": "LegalCopyright is the copyright notice string" + }, + "comments": { + "type": "string", + "description": "Comments are additional comments or description embedded in PE resources" + }, + "internalName": { + "type": "string", + "description": "InternalName is the internal name of the file" + }, + "companyName": { + "type": "string", + "description": "CompanyName is the company that produced the file" + }, + "productName": { + "type": "string", + "description": "ProductName is the name of the product this file is part of" + }, + "productVersion": { + "type": "string", + "description": "ProductVersion is the version of the product (may differ from AssemblyVersion)" + } + }, + "type": "object", + "required": [ + "assemblyVersion", + "legalCopyright", + "companyName", + "productName", + "productVersion" + ], + "description": "DotnetPortableExecutableEntry is a struct that represents a single entry found within \"VersionResources\" section of a .NET Portable Executable binary file." + }, + "DpkgArchiveEntry": { + "properties": { + "package": { + "type": "string", + "description": "Package is the package name as found in the status file" + }, + "source": { + "type": "string", + "description": "Source is the source package name this binary was built from (one source can produce multiple binary packages)" + }, + "version": { + "type": "string", + "description": "Version is the binary package version as found in the status file" + }, + "sourceVersion": { + "type": "string", + "description": "SourceVersion is the source package version (may differ from binary version when binNMU rebuilds occur)" + }, + "architecture": { + "type": "string", + "description": "Architecture is the target architecture per Debian spec (specific arch like amd64/arm64, wildcard like any, architecture-independent \"all\", or \"source\" for source packages)" + }, + "maintainer": { + "type": "string", + "description": "Maintainer is the package maintainer's name and email in RFC822 format (name must come first, then email in angle brackets)" + }, + "installedSize": { + "type": "integer", + "description": "InstalledSize is the total size of installed files in kilobytes" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Provides are the virtual packages provided by this package (allows other packages to depend on capabilities. Can include versioned provides like \"libdigest-md5-perl (= 2.55.01)\")" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Depends are the packages required for this package to function (will not be installed unless these requirements are met, creates strict ordering constraint)" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array", + "description": "PreDepends are the packages that must be installed and configured BEFORE even starting installation of this package (stronger than Depends, discouraged unless absolutely necessary as it adds strict constraints for apt)" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array", + "description": "Files are the files installed by this package" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ], + "description": "DpkgArchiveEntry represents package metadata extracted from a .deb archive file." + }, + "DpkgDbEntry": { + "properties": { + "package": { + "type": "string", + "description": "Package is the package name as found in the status file" + }, + "source": { + "type": "string", + "description": "Source is the source package name this binary was built from (one source can produce multiple binary packages)" + }, + "version": { + "type": "string", + "description": "Version is the binary package version as found in the status file" + }, + "sourceVersion": { + "type": "string", + "description": "SourceVersion is the source package version (may differ from binary version when binNMU rebuilds occur)" + }, + "architecture": { + "type": "string", + "description": "Architecture is the target architecture per Debian spec (specific arch like amd64/arm64, wildcard like any, architecture-independent \"all\", or \"source\" for source packages)" + }, + "maintainer": { + "type": "string", + "description": "Maintainer is the package maintainer's name and email in RFC822 format (name must come first, then email in angle brackets)" + }, + "installedSize": { + "type": "integer", + "description": "InstalledSize is the total size of installed files in kilobytes" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Provides are the virtual packages provided by this package (allows other packages to depend on capabilities. Can include versioned provides like \"libdigest-md5-perl (= 2.55.01)\")" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Depends are the packages required for this package to function (will not be installed unless these requirements are met, creates strict ordering constraint)" + }, + "preDepends": { + "items": { + "type": "string" + }, + "type": "array", + "description": "PreDepends are the packages that must be installed and configured BEFORE even starting installation of this package (stronger than Depends, discouraged unless absolutely necessary as it adds strict constraints for apt)" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array", + "description": "Files are the files installed by this package" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ], + "description": "DpkgDBEntry represents all captured data for a Debian package DB entry; available fields are described at http://manpages.ubuntu.com/manpages/xenial/man1/dpkg-query.1.html in the --showformat section." + }, + "DpkgFileRecord": { + "properties": { + "path": { + "type": "string", + "description": "Path is the file path relative to the filesystem root" + }, + "digest": { + "$ref": "#/$defs/Digest", + "description": "Digest is the file content hash (typically MD5 for dpkg compatibility with legacy systems)" + }, + "isConfigFile": { + "type": "boolean", + "description": "IsConfigFile is whether this file is marked as a configuration file (dpkg will preserve user modifications during upgrades)" + } + }, + "type": "object", + "required": [ + "path", + "isConfigFile" + ], + "description": "DpkgFileRecord represents a single file attributed to a debian package." + }, + "ELFSecurityFeatures": { + "properties": { + "symbolTableStripped": { + "type": "boolean", + "description": "SymbolTableStripped indicates whether debugging symbols have been removed." + }, + "stackCanary": { + "type": "boolean", + "description": "StackCanary indicates whether stack smashing protection is enabled." + }, + "nx": { + "type": "boolean", + "description": "NoExecutable indicates whether NX (no-execute) protection is enabled for the stack." + }, + "relRO": { + "type": "string", + "description": "RelocationReadOnly indicates the RELRO protection level." + }, + "pie": { + "type": "boolean", + "description": "PositionIndependentExecutable indicates whether the binary is compiled as PIE." + }, + "dso": { + "type": "boolean", + "description": "DynamicSharedObject indicates whether the binary is a shared library." + }, + "safeStack": { + "type": "boolean", + "description": "LlvmSafeStack represents a compiler-based security mechanism that separates the stack into a safe stack for storing return addresses and other critical data, and an unsafe stack for everything else, to mitigate stack-based memory corruption errors\nsee https://clang.llvm.org/docs/SafeStack.html" + }, + "cfi": { + "type": "boolean", + "description": "ControlFlowIntegrity represents runtime checks to ensure a program's control flow adheres to the legal paths determined at compile time, thus protecting against various types of control-flow hijacking attacks\nsee https://clang.llvm.org/docs/ControlFlowIntegrity.html" + }, + "fortify": { + "type": "boolean", + "description": "ClangFortifySource is a broad suite of extensions to libc aimed at catching misuses of common library functions\nsee https://android.googlesource.com/platform//bionic/+/d192dbecf0b2a371eb127c0871f77a9caf81c4d2/docs/clang_fortify_anatomy.md" + } + }, + "type": "object", + "required": [ + "symbolTableStripped", + "nx", + "relRO", + "pie", + "dso" + ], + "description": "ELFSecurityFeatures captures security hardening and protection mechanisms in ELF binaries." + }, + "ElfBinaryPackageNoteJsonPayload": { + "properties": { + "type": { + "type": "string", + "description": "Type is the type of the package (e.g. \"rpm\", \"deb\", \"apk\", etc.)" + }, + "architecture": { + "type": "string", + "description": "Architecture of the binary package (e.g. \"amd64\", \"arm\", etc.)" + }, + "osCPE": { + "type": "string", + "description": "OSCPE is a CPE name for the OS, typically corresponding to CPE_NAME in os-release (e.g. cpe:/o:fedoraproject:fedora:33)" + }, + "os": { + "type": "string", + "description": "OS is the OS name, typically corresponding to ID in os-release (e.g. \"fedora\")" + }, + "osVersion": { + "type": "string", + "description": "osVersion is the version of the OS, typically corresponding to VERSION_ID in os-release (e.g. \"33\")" + }, + "system": { + "type": "string", + "description": "System is a context-specific name for the system that the binary package is intended to run on or a part of" + }, + "vendor": { + "type": "string", + "description": "Vendor is the individual or organization that produced the source code for the binary" + }, + "sourceRepo": { + "type": "string", + "description": "SourceRepo is the URL to the source repository for which the binary was built from" + }, + "commit": { + "type": "string", + "description": "Commit is the commit hash of the source repository for which the binary was built from" + } + }, + "type": "object", + "description": "ELFBinaryPackageNoteJSONPayload Represents metadata captured from the .note.package section of an ELF-formatted binary" + }, + "ElixirMixLockEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the package name as found in the mix.lock file" + }, + "version": { + "type": "string", + "description": "Version is the package version as found in the mix.lock file" + }, + "pkgHash": { + "type": "string", + "description": "PkgHash is the outer checksum (SHA-256) of the entire Hex package tarball for integrity verification (preferred method, replaces deprecated inner checksum)" + }, + "pkgHashExt": { + "type": "string", + "description": "PkgHashExt is the extended package hash format (inner checksum is deprecated - SHA-256 of concatenated file contents excluding CHECKSUM file, now replaced by outer checksum)" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ], + "description": "ElixirMixLockEntry is a struct that represents a single entry in a mix.lock file" + }, + "ErlangRebarLockEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the package name as found in the rebar.lock file" + }, + "version": { + "type": "string", + "description": "Version is the package version as found in the rebar.lock file" + }, + "pkgHash": { + "type": "string", + "description": "PkgHash is the outer checksum (SHA-256) of the entire Hex package tarball for integrity verification (preferred method over deprecated inner checksum)" + }, + "pkgHashExt": { + "type": "string", + "description": "PkgHashExt is the extended package hash format (inner checksum deprecated - was SHA-256 of concatenated file contents)" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ], + "description": "ErlangRebarLockEntry represents a single package entry from the \"deps\" section within an Erlang rebar.lock file." + }, + "Executable": { + "properties": { + "format": { + "type": "string", + "description": "Format denotes either ELF, Mach-O, or PE" + }, + "hasExports": { + "type": "boolean", + "description": "HasExports indicates whether the binary exports symbols." + }, + "hasEntrypoint": { + "type": "boolean", + "description": "HasEntrypoint indicates whether the binary has an entry point function." + }, + "importedLibraries": { + "items": { + "type": "string" + }, + "type": "array", + "description": "ImportedLibraries lists the shared libraries required by this executable." + }, + "elfSecurityFeatures": { + "$ref": "#/$defs/ELFSecurityFeatures", + "description": "ELFSecurityFeatures contains ELF-specific security hardening information when Format is ELF." + } + }, + "type": "object", + "required": [ + "format", + "hasExports", + "hasEntrypoint", + "importedLibraries" + ], + "description": "Executable contains metadata about binary files and their security features." + }, + "File": { + "properties": { + "id": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Coordinates" + }, + "metadata": { + "$ref": "#/$defs/FileMetadataEntry" + }, + "contents": { + "type": "string" + }, + "digests": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/FileLicense" + }, + "type": "array" + }, + "executable": { + "$ref": "#/$defs/Executable" + }, + "unknowns": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "id", + "location" + ] + }, + "FileLicense": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "evidence": { + "$ref": "#/$defs/FileLicenseEvidence" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type" + ] + }, + "FileLicenseEvidence": { + "properties": { + "confidence": { + "type": "integer" + }, + "offset": { + "type": "integer" + }, + "extent": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "confidence", + "offset", + "extent" + ] + }, + "FileMetadataEntry": { + "properties": { + "mode": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "userID": { + "type": "integer" + }, + "groupID": { + "type": "integer" + }, + "mimeType": { + "type": "string" + }, + "size": { + "type": "integer" + } + }, + "type": "object", + "required": [ + "mode", + "type", + "userID", + "groupID", + "mimeType", + "size" + ] + }, + "GithubActionsUseStatement": { + "properties": { + "value": { + "type": "string", + "description": "Value is the action reference (e.g. \"actions/checkout@v3\")" + }, + "comment": { + "type": "string", + "description": "Comment is the inline comment associated with this uses statement" + } + }, + "type": "object", + "required": [ + "value" + ], + "description": "GitHubActionsUseStatement represents a single 'uses' statement in a GitHub Actions workflow file referencing an action or reusable workflow." + }, + "GoModuleBuildinfoEntry": { + "properties": { + "goBuildSettings": { + "$ref": "#/$defs/KeyValues", + "description": "BuildSettings contains the Go build settings and flags used to compile the binary (e.g., GOARCH, GOOS, CGO_ENABLED)." + }, + "goCompiledVersion": { + "type": "string", + "description": "GoCompiledVersion is the version of Go used to compile the binary." + }, + "architecture": { + "type": "string", + "description": "Architecture is the target CPU architecture for the binary (extracted from GOARCH build setting)." + }, + "h1Digest": { + "type": "string", + "description": "H1Digest is the Go module hash in h1: format for the main module from go.sum." + }, + "mainModule": { + "type": "string", + "description": "MainModule is the main module path for the binary (e.g., \"github.com/anchore/syft\")." + }, + "goCryptoSettings": { + "items": { + "type": "string" + }, + "type": "array", + "description": "GoCryptoSettings contains FIPS and cryptographic configuration settings if present." + }, + "goExperiments": { + "items": { + "type": "string" + }, + "type": "array", + "description": "GoExperiments lists experimental Go features enabled during compilation (e.g., \"arenas\", \"cgocheck2\")." + } + }, + "type": "object", + "required": [ + "goCompiledVersion", + "architecture" + ], + "description": "GolangBinaryBuildinfoEntry represents all captured data for a Golang binary" + }, + "GoModuleEntry": { + "properties": { + "h1Digest": { + "type": "string", + "description": "H1Digest is the Go module hash in h1: format from go.sum for verifying module contents." + } + }, + "type": "object", + "description": "GolangModuleEntry represents all captured data for a Golang source scan with go.mod/go.sum" + }, + "GoSourceEntry": { + "properties": { + "h1Digest": { + "type": "string", + "description": "H1Digest is the Go module hash in h1: format from go.sum for verifying module contents." + }, + "os": { + "type": "string", + "description": "OperatingSystem is the target OS for build constraints (e.g., \"linux\", \"darwin\", \"windows\")." + }, + "architecture": { + "type": "string", + "description": "Architecture is the target CPU architecture for build constraints (e.g., \"amd64\", \"arm64\")." + }, + "buildTags": { + "type": "string", + "description": "BuildTags are the build tags used to conditionally compile code (e.g., \"integration,debug\")." + }, + "cgoEnabled": { + "type": "boolean", + "description": "CgoEnabled indicates whether CGO was enabled for this package." + } + }, + "type": "object", + "required": [ + "cgoEnabled" + ], + "description": "GolangSourceEntry represents all captured data for a Golang package found through source analysis" + }, + "HaskellHackageStackEntry": { + "properties": { + "pkgHash": { + "type": "string", + "description": "PkgHash is the package content hash for verification" + } + }, + "type": "object", + "description": "HackageStackYamlEntry represents a single entry from the \"extra-deps\" section of a stack.yaml file." + }, + "HaskellHackageStackLockEntry": { + "properties": { + "pkgHash": { + "type": "string", + "description": "PkgHash is the package content hash for verification" + }, + "snapshotURL": { + "type": "string", + "description": "SnapshotURL is the URL to the Stack snapshot this package came from" + } + }, + "type": "object", + "description": "HackageStackYamlLockEntry represents a single entry from the \"packages\" section of a stack.yaml.lock file." + }, + "HomebrewFormula": { + "properties": { + "tap": { + "type": "string", + "description": "Tap is Homebrew tap this formula belongs to (e.g. \"homebrew/core\")" + }, + "homepage": { + "type": "string", + "description": "Homepage is the upstream project homepage URL" + }, + "description": { + "type": "string", + "description": "Description is a human-readable formula description" + } + }, + "type": "object", + "description": "HomebrewFormula represents metadata about a Homebrew formula package extracted from formula JSON files." + }, + "IDLikes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "JavaArchive": { + "properties": { + "virtualPath": { + "type": "string", + "description": "VirtualPath is path within the archive hierarchy, where nested entries are delimited with ':' (for nested JARs)" + }, + "manifest": { + "$ref": "#/$defs/JavaManifest", + "description": "Manifest is parsed META-INF/MANIFEST.MF contents" + }, + "pomProperties": { + "$ref": "#/$defs/JavaPomProperties", + "description": "PomProperties is parsed pom.properties file contents" + }, + "pomProject": { + "$ref": "#/$defs/JavaPomProject", + "description": "PomProject is parsed pom.xml file contents" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array", + "description": "ArchiveDigests is cryptographic hashes of the archive file" + } + }, + "type": "object", + "required": [ + "virtualPath" + ], + "description": "JavaArchive encapsulates all Java ecosystem metadata for a package as well as an (optional) parent relationship." + }, + "JavaJvmInstallation": { + "properties": { + "release": { + "$ref": "#/$defs/JavaVMRelease", + "description": "Release is JVM release information and version details" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Files are the list of files that are part of this JVM installation" + } + }, + "type": "object", + "required": [ + "release", + "files" + ], + "description": "JavaVMInstallation represents a Java Virtual Machine installation discovered on the system with its release information and file list." + }, + "JavaManifest": { + "properties": { + "main": { + "$ref": "#/$defs/KeyValues", + "description": "Main is main manifest attributes as key-value pairs" + }, + "sections": { + "items": { + "$ref": "#/$defs/KeyValues" + }, + "type": "array", + "description": "Sections are the named sections from the manifest (e.g. per-entry attributes)" + } + }, + "type": "object", + "description": "JavaManifest represents the fields of interest extracted from a Java archive's META-INF/MANIFEST.MF file." + }, + "JavaPomParent": { + "properties": { + "groupId": { + "type": "string", + "description": "GroupID is the parent Maven group identifier" + }, + "artifactId": { + "type": "string", + "description": "ArtifactID is the parent Maven artifact identifier" + }, + "version": { + "type": "string", + "description": "Version is the parent version (child inherits configuration from this specific version of parent POM)" + } + }, + "type": "object", + "required": [ + "groupId", + "artifactId", + "version" + ], + "description": "JavaPomParent contains the fields within the \u003cparent\u003e tag in a pom.xml file" + }, + "JavaPomProject": { + "properties": { + "path": { + "type": "string", + "description": "Path is path to the pom.xml file within the archive" + }, + "parent": { + "$ref": "#/$defs/JavaPomParent", + "description": "Parent is the parent POM reference for inheritance (child POMs inherit configuration from parent)" + }, + "groupId": { + "type": "string", + "description": "GroupID is Maven group identifier (reversed domain name like org.apache.maven)" + }, + "artifactId": { + "type": "string", + "description": "ArtifactID is Maven artifact identifier (project name)" + }, + "version": { + "type": "string", + "description": "Version is project version (together with groupId and artifactId forms Maven coordinates groupId:artifactId:version)" + }, + "name": { + "type": "string", + "description": "Name is a human-readable project name (displayed in Maven-generated documentation)" + }, + "description": { + "type": "string", + "description": "Description is detailed project description" + }, + "url": { + "type": "string", + "description": "URL is the project URL (typically project website or repository)" + } + }, + "type": "object", + "required": [ + "path", + "groupId", + "artifactId", + "version", + "name" + ], + "description": "JavaPomProject represents fields of interest extracted from a Java archive's pom.xml file." + }, + "JavaPomProperties": { + "properties": { + "path": { + "type": "string", + "description": "Path is path to the pom.properties file within the archive" + }, + "name": { + "type": "string", + "description": "Name is the project name" + }, + "groupId": { + "type": "string", + "description": "GroupID is Maven group identifier uniquely identifying the project across all projects (follows reversed domain name convention like com.company.project)" + }, + "artifactId": { + "type": "string", + "description": "ArtifactID is Maven artifact identifier, the name of the jar/artifact (unique within the groupId scope)" + }, + "version": { + "type": "string", + "description": "Version is artifact version" + }, + "scope": { + "type": "string", + "description": "Scope is dependency scope determining when dependency is available (compile=default all phases, test=test compilation/execution only, runtime=runtime and test not compile, provided=expected from JDK or container)" + }, + "extraFields": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object", + "description": "Extra is additional custom properties not in standard Maven coordinates" + } + }, + "type": "object", + "required": [ + "path", + "name", + "groupId", + "artifactId", + "version" + ], + "description": "JavaPomProperties represents the fields of interest extracted from a Java archive's pom.properties file." + }, + "JavaVMRelease": { + "properties": { + "implementor": { + "type": "string", + "description": "Implementor is extracted with the `java.vendor` JVM property" + }, + "implementorVersion": { + "type": "string", + "description": "ImplementorVersion is extracted with the `java.vendor.version` JVM property" + }, + "javaRuntimeVersion": { + "type": "string", + "description": "JavaRuntimeVersion is extracted from the 'java.runtime.version' JVM property" + }, + "javaVersion": { + "type": "string", + "description": "JavaVersion matches that from `java -version` command output" + }, + "javaVersionDate": { + "type": "string", + "description": "JavaVersionDate is extracted from the 'java.version.date' JVM property" + }, + "libc": { + "type": "string", + "description": "Libc can either be 'glibc' or 'musl'" + }, + "modules": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Modules is a list of JVM modules that are packaged" + }, + "osArch": { + "type": "string", + "description": "OsArch is the target CPU architecture" + }, + "osName": { + "type": "string", + "description": "OsName is the name of the target runtime operating system environment" + }, + "osVersion": { + "type": "string", + "description": "OsVersion is the version of the target runtime operating system environment" + }, + "source": { + "type": "string", + "description": "Source refers to the origin repository of OpenJDK source" + }, + "buildSource": { + "type": "string", + "description": "BuildSource Git SHA of the build repository" + }, + "buildSourceRepo": { + "type": "string", + "description": "BuildSourceRepo refers to rhe repository URL for the build source" + }, + "sourceRepo": { + "type": "string", + "description": "SourceRepo refers to the OpenJDK repository URL" + }, + "fullVersion": { + "type": "string", + "description": "FullVersion is extracted from the 'java.runtime.version' JVM property" + }, + "semanticVersion": { + "type": "string", + "description": "SemanticVersion is derived from the OpenJDK version" + }, + "buildInfo": { + "type": "string", + "description": "BuildInfo contains additional build information" + }, + "jvmVariant": { + "type": "string", + "description": "JvmVariant specifies the JVM variant (e.g., Hotspot or OpenJ9)" + }, + "jvmVersion": { + "type": "string", + "description": "JvmVersion is extracted from the 'java.vm.version' JVM property" + }, + "imageType": { + "type": "string", + "description": "ImageType can be 'JDK' or 'JRE'" + }, + "buildType": { + "type": "string", + "description": "BuildType can be 'commercial' (used in some older oracle JDK distributions)" + } + }, + "type": "object", + "description": "JavaVMRelease represents JVM version and build information extracted from the release file in a Java installation." + }, + "JavascriptNpmPackage": { + "properties": { + "name": { + "type": "string", + "description": "Name is the package name as found in package.json" + }, + "version": { + "type": "string", + "description": "Version is the package version as found in package.json" + }, + "author": { + "type": "string", + "description": "Author is package author name" + }, + "homepage": { + "type": "string", + "description": "Homepage is project homepage URL" + }, + "description": { + "type": "string", + "description": "Description is a human-readable package description" + }, + "url": { + "type": "string", + "description": "URL is repository or project URL" + }, + "private": { + "type": "boolean", + "description": "Private is whether this is a private package" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "homepage", + "description", + "url", + "private" + ], + "description": "NpmPackage represents the contents of a javascript package.json file." + }, + "JavascriptNpmPackageLockEntry": { + "properties": { + "resolved": { + "type": "string", + "description": "Resolved is URL where this package was downloaded from (registry source)" + }, + "integrity": { + "type": "string", + "description": "Integrity is Subresource Integrity hash for verification using standard SRI format (sha512-... or sha1-...). npm changed from SHA-1 to SHA-512 in newer versions. For registry sources this is the integrity from registry, for remote tarballs it's SHA-512 of the file. npm verifies tarball matches this hash before unpacking, throwing EINTEGRITY error if mismatch detected." + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ], + "description": "NpmPackageLockEntry represents a single entry within the \"packages\" section of a package-lock.json file." + }, + "JavascriptYarnLockEntry": { + "properties": { + "resolved": { + "type": "string", + "description": "Resolved is URL where this package was downloaded from" + }, + "integrity": { + "type": "string", + "description": "Integrity is Subresource Integrity hash for verification (SRI format)" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ], + "description": "YarnLockEntry represents a single entry section of a yarn.lock file." + }, + "KeyValue": { + "properties": { + "key": { + "type": "string", + "description": "Key is the key name" + }, + "value": { + "type": "string", + "description": "Value is the value associated with the key" + } + }, + "type": "object", + "required": [ + "key", + "value" + ], + "description": "KeyValue represents a single key-value pair." + }, + "KeyValues": { + "items": { + "$ref": "#/$defs/KeyValue" + }, + "type": "array", + "description": "KeyValues represents an ordered collection of key-value pairs that preserves insertion order." + }, + "License": { + "properties": { + "value": { + "type": "string" + }, + "spdxExpression": { + "type": "string" + }, + "type": { + "type": "string" + }, + "urls": { + "items": { + "type": "string" + }, + "type": "array" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "contents": { + "type": "string" + } + }, + "type": "object", + "required": [ + "value", + "spdxExpression", + "type", + "urls", + "locations" + ] + }, + "LinuxKernelArchive": { + "properties": { + "name": { + "type": "string", + "description": "Name is kernel name (typically \"Linux\")" + }, + "architecture": { + "type": "string", + "description": "Architecture is the target CPU architecture" + }, + "version": { + "type": "string", + "description": "Version is kernel version string" + }, + "extendedVersion": { + "type": "string", + "description": "ExtendedVersion is additional version information" + }, + "buildTime": { + "type": "string", + "description": "BuildTime is when the kernel was built" + }, + "author": { + "type": "string", + "description": "Author is who built the kernel" + }, + "format": { + "type": "string", + "description": "Format is kernel image format (e.g. bzImage, zImage)" + }, + "rwRootFS": { + "type": "boolean", + "description": "RWRootFS is whether root filesystem is mounted read-write" + }, + "swapDevice": { + "type": "integer", + "description": "SwapDevice is swap device number" + }, + "rootDevice": { + "type": "integer", + "description": "RootDevice is root device number" + }, + "videoMode": { + "type": "string", + "description": "VideoMode is default video mode setting" + } + }, + "type": "object", + "required": [ + "name", + "architecture", + "version" + ], + "description": "LinuxKernel represents all captured data for a Linux kernel" + }, + "LinuxKernelModule": { + "properties": { + "name": { + "type": "string", + "description": "Name is module name" + }, + "version": { + "type": "string", + "description": "Version is module version string" + }, + "sourceVersion": { + "type": "string", + "description": "SourceVersion is the source code version identifier" + }, + "path": { + "type": "string", + "description": "Path is the filesystem path to the .ko kernel object file (absolute path)" + }, + "description": { + "type": "string", + "description": "Description is a human-readable module description" + }, + "author": { + "type": "string", + "description": "Author is module author name and email" + }, + "license": { + "type": "string", + "description": "License is module license (e.g. GPL, BSD) which must be compatible with kernel" + }, + "kernelVersion": { + "type": "string", + "description": "KernelVersion is kernel version this module was built for" + }, + "versionMagic": { + "type": "string", + "description": "VersionMagic is version magic string for compatibility checking (includes kernel version, SMP status, module loading capabilities like \"3.17.4-302.fc21.x86_64 SMP mod_unload modversions\"). Module will NOT load if vermagic doesn't match running kernel." + }, + "parameters": { + "patternProperties": { + ".*": { + "$ref": "#/$defs/LinuxKernelModuleParameter" + } + }, + "type": "object", + "description": "Parameters are the module parameters that can be configured at load time (user-settable values like module options)" + } + }, + "type": "object", + "description": "LinuxKernelModule represents a loadable kernel module (.ko file) with its metadata, parameters, and dependencies." + }, + "LinuxKernelModuleParameter": { + "properties": { + "type": { + "type": "string", + "description": "Type is parameter data type (e.g. int, string, bool, array types)" + }, + "description": { + "type": "string", + "description": "Description is a human-readable parameter description explaining what the parameter controls" + } + }, + "type": "object", + "description": "LinuxKernelModuleParameter represents a configurable parameter for a kernel module with its type and description." + }, + "LinuxRelease": { + "properties": { + "prettyName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idLike": { + "$ref": "#/$defs/IDLikes" + }, + "version": { + "type": "string" + }, + "versionID": { + "type": "string" + }, + "versionCodename": { + "type": "string" + }, + "buildID": { + "type": "string" + }, + "imageID": { + "type": "string" + }, + "imageVersion": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "variantID": { + "type": "string" + }, + "homeURL": { + "type": "string" + }, + "supportURL": { + "type": "string" + }, + "bugReportURL": { + "type": "string" + }, + "privacyPolicyURL": { + "type": "string" + }, + "cpeName": { + "type": "string" + }, + "supportEnd": { + "type": "string" + }, + "extendedSupport": { + "type": "boolean" + } + }, + "type": "object" + }, + "Location": { + "properties": { + "path": { + "type": "string", + "description": "RealPath is the canonical absolute form of the path accessed (all symbolic links have been followed and relative path components like '.' and '..' have been removed)." + }, + "layerID": { + "type": "string", + "description": "FileSystemID is an ID representing and entire filesystem. For container images, this is a layer digest. For directories or a root filesystem, this is blank." + }, + "accessPath": { + "type": "string", + "description": "AccessPath is the path used to retrieve file contents (which may or may not have hardlinks / symlinks in the path)" + }, + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "accessPath" + ], + "description": "Location represents a path relative to a particular filesystem resolved to a specific file.Reference." + }, + "LuarocksPackage": { + "properties": { + "name": { + "type": "string", + "description": "Name is the package name as found in the .rockspec file" + }, + "version": { + "type": "string", + "description": "Version is the package version as found in the .rockspec file" + }, + "license": { + "type": "string", + "description": "License is license identifier" + }, + "homepage": { + "type": "string", + "description": "Homepage is project homepage URL" + }, + "description": { + "type": "string", + "description": "Description is a human-readable package description" + }, + "url": { + "type": "string", + "description": "URL is the source download URL" + }, + "dependencies": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object", + "description": "Dependencies are the map of dependency names to version constraints" + } + }, + "type": "object", + "required": [ + "name", + "version", + "license", + "homepage", + "description", + "url", + "dependencies" + ], + "description": "LuaRocksPackage represents a Lua package managed by the LuaRocks package manager with metadata from .rockspec files." + }, + "MicrosoftKbPatch": { + "properties": { + "product_id": { + "type": "string", + "description": "ProductID is MSRC Product ID (e.g. \"Windows 10 Version 1703 for 32-bit Systems\")" + }, + "kb": { + "type": "string", + "description": "Kb is Knowledge Base article number (e.g. \"5001028\")" + } + }, + "type": "object", + "required": [ + "product_id", + "kb" + ], + "description": "MicrosoftKbPatch is slightly odd in how it is expected to map onto data." + }, + "NixDerivation": { + "properties": { + "path": { + "type": "string", + "description": "Path is path to the .drv file in Nix store" + }, + "system": { + "type": "string", + "description": "System is target system string indicating where derivation can be built (e.g. \"x86_64-linux\", \"aarch64-darwin\"). Must match current system for local builds." + }, + "inputDerivations": { + "items": { + "$ref": "#/$defs/NixDerivationReference" + }, + "type": "array", + "description": "InputDerivations are the list of other derivations that were inputs to this build (dependencies)" + }, + "inputSources": { + "items": { + "type": "string" + }, + "type": "array", + "description": "InputSources are the list of source file paths that were inputs to this build" + } + }, + "type": "object", + "description": "NixDerivation represents a Nix .drv file that describes how to build a package including inputs, outputs, and build instructions." + }, + "NixDerivationReference": { + "properties": { + "path": { + "type": "string", + "description": "Path is path to the referenced .drv file" + }, + "outputs": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Outputs are which outputs of the referenced derivation were used (e.g. [\"out\"], [\"bin\", \"dev\"])" + } + }, + "type": "object", + "description": "NixDerivationReference represents a reference to another derivation used as a build input or runtime dependency." + }, + "NixStoreEntry": { + "properties": { + "path": { + "type": "string", + "description": "Path is full store path for this output (e.g. /nix/store/abc123...-package-1.0)" + }, + "output": { + "type": "string", + "description": "Output is the specific output name for multi-output packages (empty string for default \"out\" output, can be \"bin\", \"dev\", \"doc\", etc.)" + }, + "outputHash": { + "type": "string", + "description": "OutputHash is hash prefix of the store path basename (first part before the dash)" + }, + "derivation": { + "$ref": "#/$defs/NixDerivation", + "description": "Derivation is information about the .drv file that describes how this package was built" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Files are the list of files under the nix/store path for this package" + } + }, + "type": "object", + "required": [ + "outputHash" + ], + "description": "NixStoreEntry represents a package in the Nix store (/nix/store) with its derivation information and metadata." + }, + "OpamPackage": { + "properties": { + "name": { + "type": "string", + "description": "Name is the package name as found in the .opam file" + }, + "version": { + "type": "string", + "description": "Version is the package version as found in the .opam file" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Licenses are the list of applicable licenses" + }, + "url": { + "type": "string", + "description": "URL is download URL for the package source" + }, + "checksum": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Checksums are the list of checksums for verification" + }, + "homepage": { + "type": "string", + "description": "Homepage is project homepage URL" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Dependencies are the list of required dependencies" + } + }, + "type": "object", + "required": [ + "name", + "version", + "licenses", + "url", + "checksum", + "homepage", + "dependencies" + ], + "description": "OpamPackage represents an OCaml package managed by the OPAM package manager with metadata from .opam files." + }, + "Package": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "foundBy": { + "type": "string" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "licenses": { + "$ref": "#/$defs/licenses" + }, + "language": { + "type": "string" + }, + "cpes": { + "$ref": "#/$defs/cpes" + }, + "purl": { + "type": "string" + }, + "metadataType": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/AlpmDbEntry" + }, + { + "$ref": "#/$defs/ApkDbEntry" + }, + { + "$ref": "#/$defs/BinarySignature" + }, + { + "$ref": "#/$defs/BitnamiSbomEntry" + }, + { + "$ref": "#/$defs/CConanFileEntry" + }, + { + "$ref": "#/$defs/CConanInfoEntry" + }, + { + "$ref": "#/$defs/CConanLockEntry" + }, + { + "$ref": "#/$defs/CConanLockV2Entry" + }, + { + "$ref": "#/$defs/CocoaPodfileLockEntry" + }, + { + "$ref": "#/$defs/CondaMetadataEntry" + }, + { + "$ref": "#/$defs/DartPubspec" + }, + { + "$ref": "#/$defs/DartPubspecLockEntry" + }, + { + "$ref": "#/$defs/DotnetDepsEntry" + }, + { + "$ref": "#/$defs/DotnetPackagesLockEntry" + }, + { + "$ref": "#/$defs/DotnetPortableExecutableEntry" + }, + { + "$ref": "#/$defs/DpkgArchiveEntry" + }, + { + "$ref": "#/$defs/DpkgDbEntry" + }, + { + "$ref": "#/$defs/ElfBinaryPackageNoteJsonPayload" + }, + { + "$ref": "#/$defs/ElixirMixLockEntry" + }, + { + "$ref": "#/$defs/ErlangRebarLockEntry" + }, + { + "$ref": "#/$defs/GithubActionsUseStatement" + }, + { + "$ref": "#/$defs/GoModuleBuildinfoEntry" + }, + { + "$ref": "#/$defs/GoModuleEntry" + }, + { + "$ref": "#/$defs/GoSourceEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackEntry" + }, + { + "$ref": "#/$defs/HaskellHackageStackLockEntry" + }, + { + "$ref": "#/$defs/HomebrewFormula" + }, + { + "$ref": "#/$defs/JavaArchive" + }, + { + "$ref": "#/$defs/JavaJvmInstallation" + }, + { + "$ref": "#/$defs/JavascriptNpmPackage" + }, + { + "$ref": "#/$defs/JavascriptNpmPackageLockEntry" + }, + { + "$ref": "#/$defs/JavascriptYarnLockEntry" + }, + { + "$ref": "#/$defs/LinuxKernelArchive" + }, + { + "$ref": "#/$defs/LinuxKernelModule" + }, + { + "$ref": "#/$defs/LuarocksPackage" + }, + { + "$ref": "#/$defs/MicrosoftKbPatch" + }, + { + "$ref": "#/$defs/NixStoreEntry" + }, + { + "$ref": "#/$defs/OpamPackage" + }, + { + "$ref": "#/$defs/PeBinary" + }, + { + "$ref": "#/$defs/PhpComposerInstalledEntry" + }, + { + "$ref": "#/$defs/PhpComposerLockEntry" + }, + { + "$ref": "#/$defs/PhpPearEntry" + }, + { + "$ref": "#/$defs/PhpPeclEntry" + }, + { + "$ref": "#/$defs/PortageDbEntry" + }, + { + "$ref": "#/$defs/PythonPackage" + }, + { + "$ref": "#/$defs/PythonPipRequirementsEntry" + }, + { + "$ref": "#/$defs/PythonPipfileLockEntry" + }, + { + "$ref": "#/$defs/PythonPoetryLockEntry" + }, + { + "$ref": "#/$defs/PythonUvLockEntry" + }, + { + "$ref": "#/$defs/RDescription" + }, + { + "$ref": "#/$defs/RpmArchive" + }, + { + "$ref": "#/$defs/RpmDbEntry" + }, + { + "$ref": "#/$defs/RubyGemspec" + }, + { + "$ref": "#/$defs/RustCargoAuditEntry" + }, + { + "$ref": "#/$defs/RustCargoLockEntry" + }, + { + "$ref": "#/$defs/SnapEntry" + }, + { + "$ref": "#/$defs/SwiftPackageManagerLockEntry" + }, + { + "$ref": "#/$defs/SwiplpackPackage" + }, + { + "$ref": "#/$defs/TerraformLockProviderEntry" + }, + { + "$ref": "#/$defs/WordpressPluginEntry" + } + ] + } + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "foundBy", + "locations", + "licenses", + "language", + "cpes", + "purl" + ], + "description": "Package represents a pkg.Package object specialized for JSON marshaling and unmarshalling." + }, + "PeBinary": { + "properties": { + "VersionResources": { + "$ref": "#/$defs/KeyValues", + "description": "VersionResources contains key-value pairs extracted from the PE file's version resource section (e.g., FileVersion, ProductName, CompanyName)." + } + }, + "type": "object", + "required": [ + "VersionResources" + ], + "description": "PEBinary represents metadata captured from a Portable Executable formatted binary (dll, exe, etc.)" + }, + "PhpComposerAuthors": { + "properties": { + "name": { + "type": "string", + "description": "Name is author's full name" + }, + "email": { + "type": "string", + "description": "Email is author's email address" + }, + "homepage": { + "type": "string", + "description": "Homepage is author's personal or company website" + } + }, + "type": "object", + "required": [ + "name" + ], + "description": "PhpComposerAuthors represents author information for a PHP Composer package from the authors field in composer.json." + }, + "PhpComposerExternalReference": { + "properties": { + "type": { + "type": "string", + "description": "Type is reference type (git for source VCS, zip/tar for dist archives)" + }, + "url": { + "type": "string", + "description": "URL is the URL to the resource (git repository URL or archive download URL)" + }, + "reference": { + "type": "string", + "description": "Reference is git commit hash or version tag for source, or archive version for dist" + }, + "shasum": { + "type": "string", + "description": "Shasum is SHA hash of the archive file for integrity verification (dist only)" + } + }, + "type": "object", + "required": [ + "type", + "url", + "reference" + ], + "description": "PhpComposerExternalReference represents source or distribution information for a PHP package, indicating where the package code is retrieved from." + }, + "PhpComposerInstalledEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is package name in vendor/package format (e.g. symfony/console)" + }, + "version": { + "type": "string", + "description": "Version is the package version" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference", + "description": "Source is the source repository information for development (typically git repo, used when passing --prefer-source). Originates from source code repository." + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference", + "description": "Dist is distribution archive information for production (typically zip/tar, default install method). Packaged version of released code." + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object", + "description": "Require is runtime dependencies with version constraints (package will not install unless these requirements can be met)" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object", + "description": "Provide is virtual packages/functionality provided by this package (allows other packages to depend on capabilities)" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object", + "description": "RequireDev is development-only dependencies (not installed in production, only when developing this package or running tests)" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object", + "description": "Suggest is optional but recommended dependencies (suggestions for packages that would extend functionality)" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array", + "description": "License is the list of license identifiers (SPDX format)" + }, + "type": { + "type": "string", + "description": "Type is package type indicating purpose (library=reusable code, project=application, metapackage=aggregates dependencies, etc.)" + }, + "notification-url": { + "type": "string", + "description": "NotificationURL is the URL to notify when package is installed (for tracking/statistics)" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Bin is the list of binary/executable files that should be added to PATH" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array", + "description": "Authors are the list of package authors with name/email/homepage" + }, + "description": { + "type": "string", + "description": "Description is a human-readable package description" + }, + "homepage": { + "type": "string", + "description": "Homepage is project homepage URL" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Keywords are the list of keywords for package discovery/search" + }, + "time": { + "type": "string", + "description": "Time is timestamp when this package version was released" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ], + "description": "PhpComposerInstalledEntry represents a single package entry from a composer v1/v2 \"installed.json\" files (very similar to composer.lock files)." + }, + "PhpComposerLockEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is package name in vendor/package format (e.g. symfony/console)" + }, + "version": { + "type": "string", + "description": "Version is the package version" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference", + "description": "Source is the source repository information for development (typically git repo, used when passing --prefer-source). Originates from source code repository." + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference", + "description": "Dist is distribution archive information for production (typically zip/tar, default install method). Packaged version of released code." + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object", + "description": "Require is runtime dependencies with version constraints (package will not install unless these requirements can be met)" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object", + "description": "Provide is virtual packages/functionality provided by this package (allows other packages to depend on capabilities)" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object", + "description": "RequireDev is development-only dependencies (not installed in production, only when developing this package or running tests)" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object", + "description": "Suggest is optional but recommended dependencies (suggestions for packages that would extend functionality)" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array", + "description": "License is the list of license identifiers (SPDX format)" + }, + "type": { + "type": "string", + "description": "Type is package type indicating purpose (library=reusable code, project=application, metapackage=aggregates dependencies, etc.)" + }, + "notification-url": { + "type": "string", + "description": "NotificationURL is the URL to notify when package is installed (for tracking/statistics)" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Bin is the list of binary/executable files that should be added to PATH" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array", + "description": "Authors are the list of package authors with name/email/homepage" + }, + "description": { + "type": "string", + "description": "Description is a human-readable package description" + }, + "homepage": { + "type": "string", + "description": "Homepage is project homepage URL" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Keywords are the list of keywords for package discovery/search" + }, + "time": { + "type": "string", + "description": "Time is timestamp when this package version was released" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ], + "description": "PhpComposerLockEntry represents a single package entry found from a composer.lock file." + }, + "PhpPearEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the package name" + }, + "channel": { + "type": "string", + "description": "Channel is PEAR channel this package is from" + }, + "version": { + "type": "string", + "description": "Version is the package version" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array", + "description": "License is the list of applicable licenses" + } + }, + "type": "object", + "required": [ + "name", + "version" + ], + "description": "PhpPearEntry represents a single package entry found within php pear metadata files." + }, + "PhpPeclEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the package name" + }, + "channel": { + "type": "string", + "description": "Channel is PEAR channel this package is from" + }, + "version": { + "type": "string", + "description": "Version is the package version" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array", + "description": "License is the list of applicable licenses" + } + }, + "type": "object", + "required": [ + "name", + "version" + ], + "description": "PhpPeclEntry represents a single package entry found within php pecl metadata files." + }, + "PortageDbEntry": { + "properties": { + "installedSize": { + "type": "integer", + "description": "InstalledSize is total size of installed files in bytes" + }, + "licenses": { + "type": "string", + "description": "Licenses is license string which may be an expression (e.g. \"GPL-2 OR Apache-2.0\")" + }, + "files": { + "items": { + "$ref": "#/$defs/PortageFileRecord" + }, + "type": "array", + "description": "Files are the files installed by this package (tracked in CONTENTS file)" + } + }, + "type": "object", + "required": [ + "installedSize", + "files" + ], + "description": "PortageEntry represents a single package entry in the portage DB flat-file store." + }, + "PortageFileRecord": { + "properties": { + "path": { + "type": "string", + "description": "Path is the file path relative to the filesystem root" + }, + "digest": { + "$ref": "#/$defs/Digest", + "description": "Digest is file content hash (MD5 for regular files in CONTENTS format: \"obj filename md5hash mtime\")" + } + }, + "type": "object", + "required": [ + "path" + ], + "description": "PortageFileRecord represents a single file attributed to a portage package." + }, + "PythonDirectURLOriginInfo": { + "properties": { + "url": { + "type": "string", + "description": "URL is the source URL from which the package was installed." + }, + "commitId": { + "type": "string", + "description": "CommitID is the VCS commit hash if installed from version control." + }, + "vcs": { + "type": "string", + "description": "VCS is the version control system type (e.g., \"git\", \"hg\")." + } + }, + "type": "object", + "required": [ + "url" + ], + "description": "PythonDirectURLOriginInfo represents installation source metadata from direct_url.json for packages installed from VCS or direct URLs." + }, + "PythonFileDigest": { + "properties": { + "algorithm": { + "type": "string", + "description": "Algorithm is the hash algorithm used (e.g., \"sha256\")." + }, + "value": { + "type": "string", + "description": "Value is the hex-encoded hash digest value." + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ], + "description": "PythonFileDigest represents the file metadata for a single file attributed to a python package." + }, + "PythonFileRecord": { + "properties": { + "path": { + "type": "string", + "description": "Path is the installed file path from the RECORD file." + }, + "digest": { + "$ref": "#/$defs/PythonFileDigest", + "description": "Digest contains the hash algorithm and value for file integrity verification." + }, + "size": { + "type": "string", + "description": "Size is the file size in bytes as a string." + } + }, + "type": "object", + "required": [ + "path" + ], + "description": "PythonFileRecord represents a single entry within a RECORD file for a python wheel or egg package" + }, + "PythonPackage": { + "properties": { + "name": { + "type": "string", + "description": "Name is the package name from the Name field in PKG-INFO or METADATA." + }, + "version": { + "type": "string", + "description": "Version is the package version from the Version field in PKG-INFO or METADATA." + }, + "author": { + "type": "string", + "description": "Author is the package author name from the Author field." + }, + "authorEmail": { + "type": "string", + "description": "AuthorEmail is the package author's email address from the Author-Email field." + }, + "platform": { + "type": "string", + "description": "Platform indicates the target platform for the package (e.g., \"any\", \"linux\", \"win32\")." + }, + "files": { + "items": { + "$ref": "#/$defs/PythonFileRecord" + }, + "type": "array", + "description": "Files are the installed files listed in the RECORD file for wheels or installed-files.txt for eggs." + }, + "sitePackagesRootPath": { + "type": "string", + "description": "SitePackagesRootPath is the root directory path containing the package (e.g., \"/usr/lib/python3.9/site-packages\")." + }, + "topLevelPackages": { + "items": { + "type": "string" + }, + "type": "array", + "description": "TopLevelPackages are the top-level Python module names from top_level.txt file." + }, + "directUrlOrigin": { + "$ref": "#/$defs/PythonDirectURLOriginInfo", + "description": "DirectURLOrigin contains VCS or direct URL installation information from direct_url.json." + }, + "requiresPython": { + "type": "string", + "description": "RequiresPython specifies the Python version requirement (e.g., \"\u003e=3.6\")." + }, + "requiresDist": { + "items": { + "type": "string" + }, + "type": "array", + "description": "RequiresDist lists the package dependencies with version specifiers from Requires-Dist fields." + }, + "providesExtra": { + "items": { + "type": "string" + }, + "type": "array", + "description": "ProvidesExtra lists optional feature names that can be installed via extras (e.g., \"dev\", \"test\")." + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "platform", + "sitePackagesRootPath" + ], + "description": "PythonPackage represents all captured data for a python egg or wheel package (specifically as outlined in the PyPA core metadata specification https://packaging.python.org/en/latest/specifications/core-metadata/)." + }, + "PythonPipRequirementsEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the package name from the requirements file." + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Extras are the optional features to install from the package (e.g., package[dev,test])." + }, + "versionConstraint": { + "type": "string", + "description": "VersionConstraint specifies version requirements (e.g., \"\u003e=1.0,\u003c2.0\")." + }, + "url": { + "type": "string", + "description": "URL is the direct download URL or VCS URL if specified instead of a PyPI package." + }, + "markers": { + "type": "string", + "description": "Markers are environment marker expressions for conditional installation (e.g., \"python_version \u003e= '3.8'\")." + } + }, + "type": "object", + "required": [ + "name", + "versionConstraint" + ], + "description": "PythonRequirementsEntry represents a single entry within a [*-]requirements.txt file." + }, + "PythonPipfileLockEntry": { + "properties": { + "hashes": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Hashes are the package file hash values in the format \"algorithm:digest\" for integrity verification." + }, + "index": { + "type": "string", + "description": "Index is the PyPI index name where the package should be fetched from." + } + }, + "type": "object", + "required": [ + "hashes", + "index" + ], + "description": "PythonPipfileLockEntry represents a single package entry within a Pipfile.lock file." + }, + "PythonPoetryLockDependencyEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the dependency package name." + }, + "version": { + "type": "string", + "description": "Version is the locked version or version constraint for the dependency." + }, + "optional": { + "type": "boolean", + "description": "Optional indicates whether this dependency is optional (only needed for certain extras)." + }, + "markers": { + "type": "string", + "description": "Markers are environment marker expressions that conditionally enable the dependency (e.g., \"python_version \u003e= '3.8'\")." + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Extras are the optional feature names from the dependency that should be installed." + } + }, + "type": "object", + "required": [ + "name", + "version", + "optional" + ], + "description": "PythonPoetryLockDependencyEntry represents a single dependency entry within a Poetry lock file." + }, + "PythonPoetryLockEntry": { + "properties": { + "index": { + "type": "string", + "description": "Index is the package repository name where the package should be fetched from." + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonPoetryLockDependencyEntry" + }, + "type": "array", + "description": "Dependencies are the package's runtime dependencies with version constraints." + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonPoetryLockExtraEntry" + }, + "type": "array", + "description": "Extras are optional feature groups that include additional dependencies." + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ], + "description": "PythonPoetryLockEntry represents a single package entry within a Pipfile.lock file." + }, + "PythonPoetryLockExtraEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the optional feature name (e.g., \"dev\", \"test\")." + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Dependencies are the package names required when this extra is installed." + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ], + "description": "PythonPoetryLockExtraEntry represents an optional feature group in a Poetry lock file." + }, + "PythonUvLockDependencyEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the dependency package name." + }, + "optional": { + "type": "boolean", + "description": "Optional indicates whether this dependency is optional (only needed for certain extras)." + }, + "markers": { + "type": "string", + "description": "Markers are environment marker expressions that conditionally enable the dependency (e.g., \"python_version \u003e= '3.8'\")." + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Extras are the optional feature names from the dependency that should be installed." + } + }, + "type": "object", + "required": [ + "name", + "optional" + ], + "description": "PythonUvLockDependencyEntry represents a single dependency entry within a uv lock file." + }, + "PythonUvLockEntry": { + "properties": { + "index": { + "type": "string", + "description": "Index is the package repository name where the package should be fetched from." + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonUvLockDependencyEntry" + }, + "type": "array", + "description": "Dependencies are the package's runtime dependencies with version constraints." + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonUvLockExtraEntry" + }, + "type": "array", + "description": "Extras are optional feature groups that include additional dependencies." + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ], + "description": "PythonUvLockEntry represents a single package entry within a uv.lock file." + }, + "PythonUvLockExtraEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the optional feature name (e.g., \"dev\", \"test\")." + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Dependencies are the package names required when this extra is installed." + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ], + "description": "PythonUvLockExtraEntry represents an optional feature group in a uv lock file." + }, + "RDescription": { + "properties": { + "title": { + "type": "string", + "description": "Title is short one-line package title" + }, + "description": { + "type": "string", + "description": "Description is detailed package description" + }, + "author": { + "type": "string", + "description": "Author is package author(s)" + }, + "maintainer": { + "type": "string", + "description": "Maintainer is current package maintainer" + }, + "url": { + "items": { + "type": "string" + }, + "type": "array", + "description": "URL is the list of related URLs" + }, + "repository": { + "type": "string", + "description": "Repository is CRAN or other repository name" + }, + "built": { + "type": "string", + "description": "Built is R version and platform this was built with" + }, + "needsCompilation": { + "type": "boolean", + "description": "NeedsCompilation is whether this package requires compilation" + }, + "imports": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Imports are the packages imported in the NAMESPACE" + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Depends are the packages this package depends on" + }, + "suggests": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Suggests are the optional packages that extend functionality" + } + }, + "type": "object", + "description": "RDescription represents metadata from an R package DESCRIPTION file containing package information, dependencies, and author details." + }, + "Relationship": { + "properties": { + "parent": { + "type": "string" + }, + "child": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "parent", + "child", + "type" + ] + }, + "RpmArchive": { + "properties": { + "name": { + "type": "string", + "description": "Name is the RPM package name as found in the RPM database." + }, + "version": { + "type": "string", + "description": "Version is the upstream version of the package." + }, + "epoch": { + "oneOf": [ + { + "type": "integer", + "description": "Epoch is the version epoch used to force upgrade ordering (null if not set)." + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string", + "description": "Arch is the target CPU architecture (e.g., \"x86_64\", \"aarch64\", \"noarch\")." + }, + "release": { + "type": "string", + "description": "Release is the package release number or distribution-specific version suffix." + }, + "sourceRpm": { + "type": "string", + "description": "SourceRpm is the source RPM filename that was used to build this package." + }, + "signatures": { + "items": { + "$ref": "#/$defs/RpmSignature" + }, + "type": "array", + "description": "Signatures contains GPG signature metadata for package verification." + }, + "size": { + "type": "integer", + "description": "Size is the total installed size of the package in bytes." + }, + "vendor": { + "type": "string", + "description": "Vendor is the organization that packaged the software." + }, + "modularityLabel": { + "type": "string", + "description": "ModularityLabel identifies the module stream for modular RPM packages (e.g., \"nodejs:12:20200101\")." + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Provides lists the virtual packages and capabilities this package provides." + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Requires lists the dependencies required by this package." + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array", + "description": "Files are the file records for all files owned by this package." + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ], + "description": "RpmArchive represents package metadata extracted directly from a .rpm archive file, containing the same information as an RPM database entry." + }, + "RpmDbEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the RPM package name as found in the RPM database." + }, + "version": { + "type": "string", + "description": "Version is the upstream version of the package." + }, + "epoch": { + "oneOf": [ + { + "type": "integer", + "description": "Epoch is the version epoch used to force upgrade ordering (null if not set)." + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string", + "description": "Arch is the target CPU architecture (e.g., \"x86_64\", \"aarch64\", \"noarch\")." + }, + "release": { + "type": "string", + "description": "Release is the package release number or distribution-specific version suffix." + }, + "sourceRpm": { + "type": "string", + "description": "SourceRpm is the source RPM filename that was used to build this package." + }, + "signatures": { + "items": { + "$ref": "#/$defs/RpmSignature" + }, + "type": "array", + "description": "Signatures contains GPG signature metadata for package verification." + }, + "size": { + "type": "integer", + "description": "Size is the total installed size of the package in bytes." + }, + "vendor": { + "type": "string", + "description": "Vendor is the organization that packaged the software." + }, + "modularityLabel": { + "type": "string", + "description": "ModularityLabel identifies the module stream for modular RPM packages (e.g., \"nodejs:12:20200101\")." + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Provides lists the virtual packages and capabilities this package provides." + }, + "requires": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Requires lists the dependencies required by this package." + }, + "files": { + "items": { + "$ref": "#/$defs/RpmFileRecord" + }, + "type": "array", + "description": "Files are the file records for all files owned by this package." + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "vendor", + "files" + ], + "description": "RpmDBEntry represents all captured data from a RPM DB package entry." + }, + "RpmFileRecord": { + "properties": { + "path": { + "type": "string", + "description": "Path is the absolute file path where the file is installed." + }, + "mode": { + "type": "integer", + "description": "Mode is the file permission mode bits following Unix stat.h conventions." + }, + "size": { + "type": "integer", + "description": "Size is the file size in bytes." + }, + "digest": { + "$ref": "#/$defs/Digest", + "description": "Digest contains the hash algorithm and value for file integrity verification." + }, + "userName": { + "type": "string", + "description": "UserName is the owner username for the file." + }, + "groupName": { + "type": "string", + "description": "GroupName is the group name for the file." + }, + "flags": { + "type": "string", + "description": "Flags indicates the file type (e.g., \"%config\", \"%doc\", \"%ghost\")." + } + }, + "type": "object", + "required": [ + "path", + "mode", + "size", + "digest", + "userName", + "groupName", + "flags" + ], + "description": "RpmFileRecord represents the file metadata for a single file attributed to a RPM package." + }, + "RpmSignature": { + "properties": { + "algo": { + "type": "string", + "description": "PublicKeyAlgorithm is the public key algorithm used for signing (e.g., \"RSA\")." + }, + "hash": { + "type": "string", + "description": "HashAlgorithm is the hash algorithm used for the signature (e.g., \"SHA256\")." + }, + "created": { + "type": "string", + "description": "Created is the timestamp when the signature was created." + }, + "issuer": { + "type": "string", + "description": "IssuerKeyID is the GPG key ID that created the signature." + } + }, + "type": "object", + "required": [ + "algo", + "hash", + "created", + "issuer" + ], + "description": "RpmSignature represents a GPG signature for an RPM package used for authenticity verification." + }, + "RubyGemspec": { + "properties": { + "name": { + "type": "string", + "description": "Name is gem name as specified in the gemspec" + }, + "version": { + "type": "string", + "description": "Version is gem version as specified in the gemspec" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Files is logical list of files in the gem (NOT directly usable as filesystem paths. Example: bundler gem lists \"lib/bundler/vendor/uri/lib/uri/ldap.rb\" but actual path is \"/usr/local/lib/ruby/3.2.0/bundler/vendor/uri/lib/uri/ldap.rb\". Would need gem installation path, ruby version, and env vars like GEM_HOME to resolve actual paths.)" + }, + "authors": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Authors are the list of gem authors (stored as array regardless of using `author` or `authors` method in gemspec)" + }, + "homepage": { + "type": "string", + "description": "Homepage is project homepage URL" + } + }, + "type": "object", + "required": [ + "name", + "version" + ], + "description": "RubyGemspec represents all metadata parsed from the *.gemspec file" + }, + "RustCargoAuditEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is crate name as specified in audit section of the build binary" + }, + "version": { + "type": "string", + "description": "Version is crate version as specified in audit section of the build binary" + }, + "source": { + "type": "string", + "description": "Source is the source registry or repository where this crate came from" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source" + ], + "description": "RustBinaryAuditEntry represents Rust crate metadata extracted from a compiled binary using cargo-auditable format." + }, + "RustCargoLockEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is crate name as specified in Cargo.toml" + }, + "version": { + "type": "string", + "description": "Version is crate version as specified in Cargo.toml" + }, + "source": { + "type": "string", + "description": "Source is the source registry or repository URL in format \"registry+https://github.com/rust-lang/crates.io-index\" for registry packages" + }, + "checksum": { + "type": "string", + "description": "Checksum is content checksum for registry packages only (hexadecimal string). Cargo doesn't require or include checksums for git dependencies. Used to detect MITM attacks by verifying downloaded crate matches lockfile checksum." + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Dependencies are the list of dependencies with version constraints" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "checksum", + "dependencies" + ], + "description": "RustCargoLockEntry represents a locked dependency from a Cargo.lock file with precise version and checksum information." + }, + "Schema": { + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "version", + "url" + ] + }, + "SnapEntry": { + "properties": { + "snapType": { + "type": "string", + "description": "SnapType indicates the snap type (base, kernel, app, gadget, or snapd)." + }, + "base": { + "type": "string", + "description": "Base is the base snap name that this snap depends on (e.g., \"core20\", \"core22\")." + }, + "snapName": { + "type": "string", + "description": "SnapName is the snap package name." + }, + "snapVersion": { + "type": "string", + "description": "SnapVersion is the snap package version." + }, + "architecture": { + "type": "string", + "description": "Architecture is the target CPU architecture (e.g., \"amd64\", \"arm64\")." + } + }, + "type": "object", + "required": [ + "snapType", + "base", + "snapName", + "snapVersion", + "architecture" + ], + "description": "SnapEntry represents metadata for a Snap package extracted from snap.yaml or snapcraft.yaml files." + }, + "Source": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "supplier": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "metadata" + ], + "description": "Instead, the Supplier can be determined by the user of syft and passed as a config or flag to help fulfill the NTIA minimum elements." + }, + "SwiftPackageManagerLockEntry": { + "properties": { + "revision": { + "type": "string", + "description": "Revision is git commit hash of the resolved package" + } + }, + "type": "object", + "required": [ + "revision" + ], + "description": "SwiftPackageManagerResolvedEntry represents a resolved dependency from a Package.resolved file with its locked version and source location." + }, + "SwiplpackPackage": { + "properties": { + "name": { + "type": "string", + "description": "Name is the package name as found in the .toml file" + }, + "version": { + "type": "string", + "description": "Version is the package version as found in the .toml file" + }, + "author": { + "type": "string", + "description": "Author is author name" + }, + "authorEmail": { + "type": "string", + "description": "AuthorEmail is author email address" + }, + "packager": { + "type": "string", + "description": "Packager is packager name (if different from author)" + }, + "packagerEmail": { + "type": "string", + "description": "PackagerEmail is packager email address" + }, + "homepage": { + "type": "string", + "description": "Homepage is project homepage URL" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Dependencies are the list of required dependencies" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "authorEmail", + "packager", + "packagerEmail", + "homepage", + "dependencies" + ], + "description": "SwiplPackEntry represents a SWI-Prolog package from the pack system with metadata about the package and its dependencies." + }, + "TerraformLockProviderEntry": { + "properties": { + "url": { + "type": "string", + "description": "URL is the provider source address (e.g., \"registry.terraform.io/hashicorp/aws\")." + }, + "constraints": { + "type": "string", + "description": "Constraints specifies the version constraints for the provider (e.g., \"~\u003e 4.0\")." + }, + "version": { + "type": "string", + "description": "Version is the locked provider version selected during terraform init." + }, + "hashes": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Hashes are cryptographic checksums for the provider plugin archives across different platforms." + } + }, + "type": "object", + "required": [ + "url", + "constraints", + "version", + "hashes" + ], + "description": "TerraformLockProviderEntry represents a single provider entry in a Terraform dependency lock file (.terraform.lock.hcl)." + }, + "WordpressPluginEntry": { + "properties": { + "pluginInstallDirectory": { + "type": "string", + "description": "PluginInstallDirectory is directory name where the plugin is installed" + }, + "author": { + "type": "string", + "description": "Author is plugin author name" + }, + "authorUri": { + "type": "string", + "description": "AuthorURI is author's website URL" + } + }, + "type": "object", + "required": [ + "pluginInstallDirectory" + ], + "description": "WordpressPluginEntry represents all metadata parsed from the wordpress plugin file" + }, + "cpes": { + "items": { + "$ref": "#/$defs/CPE" + }, + "type": "array" + }, + "licenses": { + "items": { + "$ref": "#/$defs/License" + }, + "type": "array" + } + } +} diff --git a/schema/json/schema-latest.json b/schema/json/schema-latest.json index 2043f7cc46c..cd8198acb3d 100644 --- a/schema/json/schema-latest.json +++ b/schema/json/schema-latest.json @@ -1,63 +1,77 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "anchore.io/schema/syft/json/16.0.34/document", + "$id": "anchore.io/schema/syft/json/16.0.40/document", "$ref": "#/$defs/Document", "$defs": { "AlpmDbEntry": { "properties": { "basepackage": { - "type": "string" + "type": "string", + "description": "BasePackage is the base package name this package was built from (source package in Arch build system)" }, "package": { - "type": "string" + "type": "string", + "description": "Package is the package name as found in the desc file" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version as found in the desc file" }, "description": { - "type": "string" + "type": "string", + "description": "Description is a human-readable package description" }, "architecture": { - "type": "string" + "type": "string", + "description": "Architecture is the target CPU architecture as defined in Arch architecture spec (e.g. x86_64, aarch64, or \"any\" for arch-independent packages)" }, "size": { - "type": "integer" + "type": "integer", + "description": "Size is the installed size in bytes" }, "packager": { - "type": "string" + "type": "string", + "description": "Packager is the name and email of the person who packaged this (RFC822 format)" }, "url": { - "type": "string" + "type": "string", + "description": "URL is the upstream project URL" }, "validation": { - "type": "string" + "type": "string", + "description": "Validation is the validation method used for package integrity (e.g. pgp signature, sha256 checksum)" }, "reason": { - "type": "integer" + "type": "integer", + "description": "Reason is the installation reason tracked by pacman (0=explicitly installed by user, 1=installed as dependency)" }, "files": { "items": { "$ref": "#/$defs/AlpmFileRecord" }, - "type": "array" + "type": "array", + "description": "Files are the files installed by this package" }, "backup": { "items": { "$ref": "#/$defs/AlpmFileRecord" }, - "type": "array" + "type": "array", + "description": "Backup is the list of configuration files that pacman backs up before upgrades" }, "provides": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Provides are virtual packages provided by this package (allows other packages to depend on capabilities rather than specific packages)" }, "depends": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Depends are the runtime dependencies required by this package" } }, "type": "object", @@ -74,37 +88,46 @@ "reason", "files", "backup" - ] + ], + "description": "AlpmDBEntry is a struct that represents the package data stored in the pacman flat-file stores for arch linux." }, "AlpmFileRecord": { "properties": { "path": { - "type": "string" + "type": "string", + "description": "Path is the file path relative to the filesystem root" }, "type": { - "type": "string" + "type": "string", + "description": "Type is the file type (e.g. regular file, directory, symlink)" }, "uid": { - "type": "string" + "type": "string", + "description": "UID is the file owner user ID as recorded by pacman" }, "gid": { - "type": "string" + "type": "string", + "description": "GID is the file owner group ID as recorded by pacman" }, "time": { "type": "string", - "format": "date-time" + "format": "date-time", + "description": "Time is the file modification timestamp" }, "size": { - "type": "string" + "type": "string", + "description": "Size is the file size in bytes" }, "link": { - "type": "string" + "type": "string", + "description": "Link is the symlink target path if this is a symlink" }, "digest": { "items": { "$ref": "#/$defs/Digest" }, - "type": "array" + "type": "array", + "description": "Digests contains file content hashes for integrity verification" } }, "type": "object" @@ -112,55 +135,69 @@ "ApkDbEntry": { "properties": { "package": { - "type": "string" + "type": "string", + "description": "Package is the package name as found in the installed file" }, "originPackage": { - "type": "string" + "type": "string", + "description": "OriginPackage is the original source package name this binary was built from (used to track which aport/source built this)" }, "maintainer": { - "type": "string" + "type": "string", + "description": "Maintainer is the package maintainer name and email" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version as found in the installed file" }, "architecture": { - "type": "string" + "type": "string", + "description": "Architecture is the target CPU architecture" }, "url": { - "type": "string" + "type": "string", + "description": "URL is the upstream project URL" }, "description": { - "type": "string" + "type": "string", + "description": "Description is a human-readable package description" }, "size": { - "type": "integer" + "type": "integer", + "description": "Size is the package archive size in bytes (.apk file size)" }, "installedSize": { - "type": "integer" + "type": "integer", + "description": "InstalledSize is the total size of installed files in bytes" }, "pullDependencies": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Dependencies are the runtime dependencies required by this package" }, "provides": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Provides are virtual packages provided by this package (for capability-based dependencies)" }, "pullChecksum": { - "type": "string" + "type": "string", + "description": "Checksum is the package content checksum for integrity verification" }, "gitCommitOfApkPort": { - "type": "string" + "type": "string", + "description": "GitCommit is the git commit hash of the APK port definition in Alpine's aports repository" }, "files": { "items": { "$ref": "#/$defs/ApkFileRecord" }, - "type": "array" + "type": "array", + "description": "Files are the files installed by this package" } }, "type": "object", @@ -179,30 +216,37 @@ "pullChecksum", "gitCommitOfApkPort", "files" - ] + ], + "description": "ApkDBEntry represents all captured data for the alpine linux package manager flat-file store." }, "ApkFileRecord": { "properties": { "path": { - "type": "string" + "type": "string", + "description": "Path is the file path relative to the filesystem root" }, "ownerUid": { - "type": "string" + "type": "string", + "description": "OwnerUID is the file owner user ID" }, "ownerGid": { - "type": "string" + "type": "string", + "description": "OwnerGID is the file owner group ID" }, "permissions": { - "type": "string" + "type": "string", + "description": "Permissions is the file permission mode string (e.g. \"0755\", \"0644\")" }, "digest": { - "$ref": "#/$defs/Digest" + "$ref": "#/$defs/Digest", + "description": "Digest is the file content hash for integrity verification" } }, "type": "object", "required": [ "path" - ] + ], + "description": "ApkFileRecord represents a single file listing and metadata from a APK DB entry (which may have many of these file records)." }, "BinarySignature": { "properties": { @@ -216,33 +260,41 @@ "type": "object", "required": [ "matches" - ] + ], + "description": "BinarySignature represents a set of matched values within a binary file." }, "BitnamiSbomEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the package name as found in the Bitnami SPDX file" }, "arch": { - "type": "string" + "type": "string", + "description": "Architecture is the target CPU architecture (amd64 or arm64 in Bitnami images)" }, "distro": { - "type": "string" + "type": "string", + "description": "Distro is the distribution name this package is for (base OS like debian, ubuntu, etc.)" }, "revision": { - "type": "string" + "type": "string", + "description": "Revision is the Bitnami-specific package revision number (incremented for Bitnami rebuilds of same upstream version)" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version as found in the Bitnami SPDX file" }, "path": { - "type": "string" + "type": "string", + "description": "Path is the installation path in the filesystem where the package is located" }, "files": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Files are the file paths owned by this package (tracked via SPDX relationships)" } }, "type": "object", @@ -254,105 +306,129 @@ "version", "path", "files" - ] + ], + "description": "BitnamiSBOMEntry represents all captured data from Bitnami packages described in Bitnami' SPDX files." }, "CConanFileEntry": { "properties": { "ref": { - "type": "string" + "type": "string", + "description": "Ref is the package reference string in format name/version@user/channel" } }, "type": "object", "required": [ "ref" - ] + ], + "description": "ConanfileEntry represents a single \"Requires\" entry from a conanfile.txt." }, "CConanInfoEntry": { "properties": { "ref": { - "type": "string" + "type": "string", + "description": "Ref is the package reference string in format name/version@user/channel" }, "package_id": { - "type": "string" + "type": "string", + "description": "PackageID is a unique package variant identifier" } }, "type": "object", "required": [ "ref" - ] + ], + "description": "ConaninfoEntry represents a single \"full_requires\" entry from a conaninfo.txt." }, "CConanLockEntry": { "properties": { "ref": { - "type": "string" + "type": "string", + "description": "Ref is the package reference string in format name/version@user/channel" }, "package_id": { - "type": "string" + "type": "string", + "description": "PackageID is a unique package variant identifier computed from settings/options (static hash in Conan 1.x, can have collisions with complex dependency graphs)" }, "prev": { - "type": "string" + "type": "string", + "description": "Prev is the previous lock entry reference for versioning" }, "requires": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Requires are the runtime package dependencies" }, "build_requires": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "BuildRequires are the build-time dependencies (e.g. cmake, compilers)" }, "py_requires": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "PythonRequires are the Python dependencies needed for Conan recipes" }, "options": { - "$ref": "#/$defs/KeyValues" + "$ref": "#/$defs/KeyValues", + "description": "Options are package configuration options as key-value pairs (e.g. shared=True, fPIC=True)" }, "path": { - "type": "string" + "type": "string", + "description": "Path is the filesystem path to the package in Conan cache" }, "context": { - "type": "string" + "type": "string", + "description": "Context is the build context information" } }, "type": "object", "required": [ "ref" - ] + ], + "description": "ConanV1LockEntry represents a single \"node\" entry from a conan.lock V1 file." }, "CConanLockV2Entry": { "properties": { "ref": { - "type": "string" + "type": "string", + "description": "Ref is the package reference string in format name/version@user/channel" }, "packageID": { - "type": "string" + "type": "string", + "description": "PackageID is a unique package variant identifier (dynamic in Conan 2.0, more accurate than V1)" }, "username": { - "type": "string" + "type": "string", + "description": "Username is the Conan user/organization name" }, "channel": { - "type": "string" + "type": "string", + "description": "Channel is the Conan channel name indicating stability/purpose (e.g. stable, testing, experimental)" }, "recipeRevision": { - "type": "string" + "type": "string", + "description": "RecipeRevision is a git-like revision hash (RREV) of the recipe" }, "packageRevision": { - "type": "string" + "type": "string", + "description": "PackageRevision is a git-like revision hash of the built binary package" }, "timestamp": { - "type": "string" + "type": "string", + "description": "TimeStamp is when this package was built/locked" } }, "type": "object", "required": [ "ref" - ] + ], + "description": "ConanV2LockEntry represents a single \"node\" entry from a conan.lock V2 file." }, "CPE": { "properties": { @@ -381,96 +457,292 @@ "required": [ "classifier", "location" - ] + ], + "description": "ClassifierMatch represents a single matched value within a binary file and the \"class\" name the search pattern represents." }, "CocoaPodfileLockEntry": { "properties": { "checksum": { - "type": "string" + "type": "string", + "description": "Checksum is the SHA-1 hash of the podspec file for integrity verification (generated via `pod ipc spec ... | openssl sha1`), ensuring all team members use the same pod specification version" } }, "type": "object", "required": [ "checksum" - ] + ], + "description": "CocoaPodfileLockEntry represents a single entry from the \"Pods\" section of a Podfile.lock file." + }, + "CondaLink": { + "properties": { + "source": { + "type": "string", + "description": "Source is the original path where the package was extracted from cache." + }, + "type": { + "type": "integer", + "description": "Type indicates the link type (1 for hard link, 2 for soft link, 3 for copy)." + } + }, + "type": "object", + "required": [ + "source", + "type" + ], + "description": "CondaLink represents link metadata from a Conda package's link.json file describing package installation source." + }, + "CondaMetadataEntry": { + "properties": { + "arch": { + "type": "string", + "description": "Arch is the target CPU architecture for the package (e.g., \"arm64\", \"x86_64\")." + }, + "name": { + "type": "string", + "description": "Name is the package name as found in the conda-meta JSON file." + }, + "version": { + "type": "string", + "description": "Version is the package version as found in the conda-meta JSON file." + }, + "build": { + "type": "string", + "description": "Build is the build string identifier (e.g., \"h90dfc92_1014\")." + }, + "build_number": { + "type": "integer", + "description": "BuildNumber is the sequential build number for this version." + }, + "channel": { + "type": "string", + "description": "Channel is the Conda channel URL where the package was retrieved from." + }, + "subdir": { + "type": "string", + "description": "Subdir is the subdirectory within the channel (e.g., \"osx-arm64\", \"linux-64\")." + }, + "noarch": { + "type": "string", + "description": "Noarch indicates if the package is platform-independent (e.g., \"python\", \"generic\")." + }, + "license": { + "type": "string", + "description": "License is the package license identifier." + }, + "license_family": { + "type": "string", + "description": "LicenseFamily is the general license category (e.g., \"MIT\", \"Apache\", \"GPL\")." + }, + "md5": { + "type": "string", + "description": "MD5 is the MD5 hash of the package archive." + }, + "sha256": { + "type": "string", + "description": "SHA256 is the SHA-256 hash of the package archive." + }, + "size": { + "type": "integer", + "description": "Size is the package archive size in bytes." + }, + "timestamp": { + "type": "integer", + "description": "Timestamp is the Unix timestamp when the package was built." + }, + "fn": { + "type": "string", + "description": "Filename is the original package archive filename (e.g., \"zlib-1.2.11-h90dfc92_1014.tar.bz2\")." + }, + "url": { + "type": "string", + "description": "URL is the full download URL for the package archive." + }, + "extracted_package_dir": { + "type": "string", + "description": "ExtractedPackageDir is the local cache directory where the package was extracted." + }, + "depends": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Depends is the list of runtime dependencies with version constraints." + }, + "files": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Files is the list of files installed by this package." + }, + "paths_data": { + "$ref": "#/$defs/CondaPathsData", + "description": "PathsData contains detailed file metadata from the paths.json file." + }, + "link": { + "$ref": "#/$defs/CondaLink", + "description": "Link contains installation source metadata from the link.json file." + } + }, + "type": "object", + "required": [ + "name", + "version", + "build", + "build_number" + ], + "description": "CondaMetaPackage represents metadata for a Conda package extracted from the conda-meta/*.json files." + }, + "CondaPathData": { + "properties": { + "_path": { + "type": "string", + "description": "Path is the file path relative to the Conda environment root." + }, + "path_type": { + "type": "string", + "description": "PathType indicates the link type for the file (e.g., \"hardlink\", \"softlink\", \"directory\")." + }, + "sha256": { + "type": "string", + "description": "SHA256 is the SHA-256 hash of the file contents." + }, + "sha256_in_prefix": { + "type": "string", + "description": "SHA256InPrefix is the SHA-256 hash of the file after prefix replacement during installation." + }, + "size_in_bytes": { + "type": "integer", + "description": "SizeInBytes is the file size in bytes." + } + }, + "type": "object", + "required": [ + "_path", + "path_type", + "sha256", + "sha256_in_prefix", + "size_in_bytes" + ], + "description": "CondaPathData represents metadata for a single file within a Conda package from the paths.json file." + }, + "CondaPathsData": { + "properties": { + "paths_version": { + "type": "integer", + "description": "PathsVersion is the schema version of the paths data format." + }, + "paths": { + "items": { + "$ref": "#/$defs/CondaPathData" + }, + "type": "array", + "description": "Paths is the list of file metadata entries for all files in the package." + } + }, + "type": "object", + "required": [ + "paths_version", + "paths" + ], + "description": "CondaPathsData represents the paths.json file structure from a Conda package containing file metadata." }, "Coordinates": { "properties": { "path": { - "type": "string" + "type": "string", + "description": "RealPath is the canonical absolute form of the path accessed (all symbolic links have been followed and relative path components like '.' and '..' have been removed)." }, "layerID": { - "type": "string" + "type": "string", + "description": "FileSystemID is an ID representing and entire filesystem. For container images, this is a layer digest. For directories or a root filesystem, this is blank." } }, "type": "object", "required": [ "path" - ] + ], + "description": "Coordinates contains the minimal information needed to describe how to find a file within any possible source object (e.g." }, "DartPubspec": { "properties": { "homepage": { - "type": "string" + "type": "string", + "description": "Homepage is the package homepage URL" }, "repository": { - "type": "string" + "type": "string", + "description": "Repository is the source code repository URL" }, "documentation": { - "type": "string" + "type": "string", + "description": "Documentation is the documentation site URL" }, "publish_to": { - "type": "string" + "type": "string", + "description": "PublishTo is the package repository to publish to, or \"none\" to prevent accidental publishing" }, "environment": { - "$ref": "#/$defs/DartPubspecEnvironment" + "$ref": "#/$defs/DartPubspecEnvironment", + "description": "Environment is SDK version constraints for Dart and Flutter" }, "platforms": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Platforms are the supported platforms (Android, iOS, web, etc.)" }, "ignored_advisories": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "IgnoredAdvisories are the security advisories to explicitly ignore for this package" } }, - "type": "object" + "type": "object", + "description": "DartPubspec is a struct that represents a package described in a pubspec.yaml file" }, "DartPubspecEnvironment": { "properties": { "sdk": { - "type": "string" + "type": "string", + "description": "SDK is the Dart SDK version constraint (e.g. \"\u003e=2.12.0 \u003c3.0.0\")" }, "flutter": { - "type": "string" + "type": "string", + "description": "Flutter is the Flutter SDK version constraint if this is a Flutter package" } }, - "type": "object" + "type": "object", + "description": "DartPubspecEnvironment represents SDK version constraints from the environment section of pubspec.yaml." }, "DartPubspecLockEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the package name as found in the pubspec.lock file" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version as found in the pubspec.lock file" }, "hosted_url": { - "type": "string" + "type": "string", + "description": "HostedURL is the URL of the package repository for hosted packages (typically pub.dev, but can be custom repository identified by hosted-url). When PUB_HOSTED_URL environment variable changes, lockfile tracks the source." }, "vcs_url": { - "type": "string" + "type": "string", + "description": "VcsURL is the URL of the VCS repository for git/path dependencies (for packages fetched from version control systems like Git)" } }, "type": "object", "required": [ "name", "version" - ] + ], + "description": "DartPubspecLockEntry is a struct that represents a single entry found in the \"packages\" section in a Dart pubspec.lock file." }, "Descriptor": { "properties": { @@ -486,22 +758,26 @@ "required": [ "name", "version" - ] + ], + "description": "Descriptor describes what created the document as well as surrounding metadata" }, "Digest": { "properties": { "algorithm": { - "type": "string" + "type": "string", + "description": "Algorithm specifies the hash algorithm used (e.g., \"sha256\", \"md5\")." }, "value": { - "type": "string" + "type": "string", + "description": "Value is the hexadecimal string representation of the hash." } }, "type": "object", "required": [ "algorithm", "value" - ] + ], + "description": "Digest represents a cryptographic hash of file contents." }, "Document": { "properties": { @@ -544,24 +820,30 @@ "distro", "descriptor", "schema" - ] + ], + "description": "Document represents the syft cataloging findings as a JSON document" }, "DotnetDepsEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the package name as found in the deps.json file" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version as found in the deps.json file" }, "path": { - "type": "string" + "type": "string", + "description": "Path is the relative path to the package within the deps structure (e.g. \"app.metrics/3.0.0\")" }, "sha512": { - "type": "string" + "type": "string", + "description": "Sha512 is the SHA-512 hash of the NuGet package content WITHOUT the signed content for verification (won't match hash from NuGet API or manual calculation of .nupkg file)" }, "hashPath": { - "type": "string" + "type": "string", + "description": "HashPath is the relative path to the .nupkg.sha512 hash file (e.g. \"app.metrics.3.0.0.nupkg.sha512\")" }, "executables": { "patternProperties": { @@ -569,7 +851,8 @@ "$ref": "#/$defs/DotnetPortableExecutableEntry" } }, - "type": "object" + "type": "object", + "description": "Executables are the map of .NET Portable Executable files within this package with their version resources" } }, "type": "object", @@ -579,21 +862,26 @@ "path", "sha512", "hashPath" - ] + ], + "description": "DotnetDepsEntry is a struct that represents a single entry found in the \"libraries\" section in a .NET [*.]deps.json file." }, "DotnetPackagesLockEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the package name as found in the packages.lock.json file" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version as found in the packages.lock.json file" }, "contentHash": { - "type": "string" + "type": "string", + "description": "ContentHash is the hash of the package content for verification" }, "type": { - "type": "string" + "type": "string", + "description": "Type is the dependency type indicating how this dependency was added (Direct=explicit in project file, Transitive=pulled in by another package, Project=project reference)" } }, "type": "object", @@ -602,30 +890,38 @@ "version", "contentHash", "type" - ] + ], + "description": "DotnetPackagesLockEntry is a struct that represents a single entry found in the \"dependencies\" section in a .NET packages.lock.json file." }, "DotnetPortableExecutableEntry": { "properties": { "assemblyVersion": { - "type": "string" + "type": "string", + "description": "AssemblyVersion is the .NET assembly version number (strong-named version)" }, "legalCopyright": { - "type": "string" + "type": "string", + "description": "LegalCopyright is the copyright notice string" }, "comments": { - "type": "string" + "type": "string", + "description": "Comments are additional comments or description embedded in PE resources" }, "internalName": { - "type": "string" + "type": "string", + "description": "InternalName is the internal name of the file" }, "companyName": { - "type": "string" + "type": "string", + "description": "CompanyName is the company that produced the file" }, "productName": { - "type": "string" + "type": "string", + "description": "ProductName is the name of the product this file is part of" }, "productVersion": { - "type": "string" + "type": "string", + "description": "ProductVersion is the version of the product (may differ from AssemblyVersion)" } }, "type": "object", @@ -635,54 +931,66 @@ "companyName", "productName", "productVersion" - ] + ], + "description": "DotnetPortableExecutableEntry is a struct that represents a single entry found within \"VersionResources\" section of a .NET Portable Executable binary file." }, "DpkgArchiveEntry": { "properties": { "package": { - "type": "string" + "type": "string", + "description": "Package is the package name as found in the status file" }, "source": { - "type": "string" + "type": "string", + "description": "Source is the source package name this binary was built from (one source can produce multiple binary packages)" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the binary package version as found in the status file" }, "sourceVersion": { - "type": "string" + "type": "string", + "description": "SourceVersion is the source package version (may differ from binary version when binNMU rebuilds occur)" }, "architecture": { - "type": "string" + "type": "string", + "description": "Architecture is the target architecture per Debian spec (specific arch like amd64/arm64, wildcard like any, architecture-independent \"all\", or \"source\" for source packages)" }, "maintainer": { - "type": "string" + "type": "string", + "description": "Maintainer is the package maintainer's name and email in RFC822 format (name must come first, then email in angle brackets)" }, "installedSize": { - "type": "integer" + "type": "integer", + "description": "InstalledSize is the total size of installed files in kilobytes" }, "provides": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Provides are the virtual packages provided by this package (allows other packages to depend on capabilities. Can include versioned provides like \"libdigest-md5-perl (= 2.55.01)\")" }, "depends": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Depends are the packages required for this package to function (will not be installed unless these requirements are met, creates strict ordering constraint)" }, "preDepends": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "PreDepends are the packages that must be installed and configured BEFORE even starting installation of this package (stronger than Depends, discouraged unless absolutely necessary as it adds strict constraints for apt)" }, "files": { "items": { "$ref": "#/$defs/DpkgFileRecord" }, - "type": "array" + "type": "array", + "description": "Files are the files installed by this package" } }, "type": "object", @@ -695,54 +1003,66 @@ "maintainer", "installedSize", "files" - ] + ], + "description": "DpkgArchiveEntry represents package metadata extracted from a .deb archive file." }, "DpkgDbEntry": { "properties": { "package": { - "type": "string" + "type": "string", + "description": "Package is the package name as found in the status file" }, "source": { - "type": "string" + "type": "string", + "description": "Source is the source package name this binary was built from (one source can produce multiple binary packages)" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the binary package version as found in the status file" }, "sourceVersion": { - "type": "string" + "type": "string", + "description": "SourceVersion is the source package version (may differ from binary version when binNMU rebuilds occur)" }, "architecture": { - "type": "string" + "type": "string", + "description": "Architecture is the target architecture per Debian spec (specific arch like amd64/arm64, wildcard like any, architecture-independent \"all\", or \"source\" for source packages)" }, "maintainer": { - "type": "string" + "type": "string", + "description": "Maintainer is the package maintainer's name and email in RFC822 format (name must come first, then email in angle brackets)" }, "installedSize": { - "type": "integer" + "type": "integer", + "description": "InstalledSize is the total size of installed files in kilobytes" }, "provides": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Provides are the virtual packages provided by this package (allows other packages to depend on capabilities. Can include versioned provides like \"libdigest-md5-perl (= 2.55.01)\")" }, "depends": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Depends are the packages required for this package to function (will not be installed unless these requirements are met, creates strict ordering constraint)" }, "preDepends": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "PreDepends are the packages that must be installed and configured BEFORE even starting installation of this package (stronger than Depends, discouraged unless absolutely necessary as it adds strict constraints for apt)" }, "files": { "items": { "$ref": "#/$defs/DpkgFileRecord" }, - "type": "array" + "type": "array", + "description": "Files are the files installed by this package" } }, "type": "object", @@ -755,54 +1075,68 @@ "maintainer", "installedSize", "files" - ] + ], + "description": "DpkgDBEntry represents all captured data for a Debian package DB entry; available fields are described at http://manpages.ubuntu.com/manpages/xenial/man1/dpkg-query.1.html in the --showformat section." }, "DpkgFileRecord": { "properties": { "path": { - "type": "string" + "type": "string", + "description": "Path is the file path relative to the filesystem root" }, "digest": { - "$ref": "#/$defs/Digest" + "$ref": "#/$defs/Digest", + "description": "Digest is the file content hash (typically MD5 for dpkg compatibility with legacy systems)" }, "isConfigFile": { - "type": "boolean" + "type": "boolean", + "description": "IsConfigFile is whether this file is marked as a configuration file (dpkg will preserve user modifications during upgrades)" } }, "type": "object", "required": [ "path", "isConfigFile" - ] + ], + "description": "DpkgFileRecord represents a single file attributed to a debian package." }, "ELFSecurityFeatures": { "properties": { "symbolTableStripped": { - "type": "boolean" + "type": "boolean", + "description": "SymbolTableStripped indicates whether debugging symbols have been removed." }, "stackCanary": { - "type": "boolean" + "type": "boolean", + "description": "StackCanary indicates whether stack smashing protection is enabled." }, "nx": { - "type": "boolean" + "type": "boolean", + "description": "NoExecutable indicates whether NX (no-execute) protection is enabled for the stack." }, "relRO": { - "type": "string" + "type": "string", + "description": "RelocationReadOnly indicates the RELRO protection level." }, "pie": { - "type": "boolean" + "type": "boolean", + "description": "PositionIndependentExecutable indicates whether the binary is compiled as PIE." }, "dso": { - "type": "boolean" + "type": "boolean", + "description": "DynamicSharedObject indicates whether the binary is a shared library." }, "safeStack": { - "type": "boolean" + "type": "boolean", + "description": "LlvmSafeStack represents a compiler-based security mechanism that separates the stack into a safe stack for storing return addresses and other critical data, and an unsafe stack for everything else, to mitigate stack-based memory corruption errors\nsee https://clang.llvm.org/docs/SafeStack.html" }, "cfi": { - "type": "boolean" + "type": "boolean", + "description": "ControlFlowIntegrity represents runtime checks to ensure a program's control flow adheres to the legal paths determined at compile time, thus protecting against various types of control-flow hijacking attacks\nsee https://clang.llvm.org/docs/ControlFlowIntegrity.html" }, "fortify": { - "type": "boolean" + "type": "boolean", + "description": "ClangFortifySource is a broad suite of extensions to libc aimed at catching misuses of common library functions\nsee https://android.googlesource.com/platform//bionic/+/d192dbecf0b2a371eb127c0871f77a9caf81c4d2/docs/clang_fortify_anatomy.md" } }, "type": "object", @@ -812,53 +1146,68 @@ "relRO", "pie", "dso" - ] + ], + "description": "ELFSecurityFeatures captures security hardening and protection mechanisms in ELF binaries." }, "ElfBinaryPackageNoteJsonPayload": { "properties": { "type": { - "type": "string" + "type": "string", + "description": "Type is the type of the package (e.g. \"rpm\", \"deb\", \"apk\", etc.)" }, "architecture": { - "type": "string" + "type": "string", + "description": "Architecture of the binary package (e.g. \"amd64\", \"arm\", etc.)" }, "osCPE": { - "type": "string" + "type": "string", + "description": "OSCPE is a CPE name for the OS, typically corresponding to CPE_NAME in os-release (e.g. cpe:/o:fedoraproject:fedora:33)" }, "os": { - "type": "string" + "type": "string", + "description": "OS is the OS name, typically corresponding to ID in os-release (e.g. \"fedora\")" }, "osVersion": { - "type": "string" + "type": "string", + "description": "osVersion is the version of the OS, typically corresponding to VERSION_ID in os-release (e.g. \"33\")" }, "system": { - "type": "string" + "type": "string", + "description": "System is a context-specific name for the system that the binary package is intended to run on or a part of" }, "vendor": { - "type": "string" + "type": "string", + "description": "Vendor is the individual or organization that produced the source code for the binary" }, "sourceRepo": { - "type": "string" + "type": "string", + "description": "SourceRepo is the URL to the source repository for which the binary was built from" }, "commit": { - "type": "string" + "type": "string", + "description": "Commit is the commit hash of the source repository for which the binary was built from" } }, - "type": "object" + "type": "object", + "description": "ELFBinaryPackageNoteJSONPayload Represents metadata captured from the .note.package section of an ELF-formatted binary" }, "ElixirMixLockEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the package name as found in the mix.lock file" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version as found in the mix.lock file" }, "pkgHash": { - "type": "string" + "type": "string", + "description": "PkgHash is the outer checksum (SHA-256) of the entire Hex package tarball for integrity verification (preferred method, replaces deprecated inner checksum)" }, "pkgHashExt": { - "type": "string" + "type": "string", + "description": "PkgHashExt is the extended package hash format (inner checksum is deprecated - SHA-256 of concatenated file contents excluding CHECKSUM file, now replaced by outer checksum)" } }, "type": "object", @@ -867,21 +1216,26 @@ "version", "pkgHash", "pkgHashExt" - ] + ], + "description": "ElixirMixLockEntry is a struct that represents a single entry in a mix.lock file" }, "ErlangRebarLockEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the package name as found in the rebar.lock file" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version as found in the rebar.lock file" }, "pkgHash": { - "type": "string" + "type": "string", + "description": "PkgHash is the outer checksum (SHA-256) of the entire Hex package tarball for integrity verification (preferred method over deprecated inner checksum)" }, "pkgHashExt": { - "type": "string" + "type": "string", + "description": "PkgHashExt is the extended package hash format (inner checksum deprecated - was SHA-256 of concatenated file contents)" } }, "type": "object", @@ -890,27 +1244,33 @@ "version", "pkgHash", "pkgHashExt" - ] + ], + "description": "ErlangRebarLockEntry represents a single package entry from the \"deps\" section within an Erlang rebar.lock file." }, "Executable": { "properties": { "format": { - "type": "string" + "type": "string", + "description": "Format denotes either ELF, Mach-O, or PE" }, "hasExports": { - "type": "boolean" + "type": "boolean", + "description": "HasExports indicates whether the binary exports symbols." }, "hasEntrypoint": { - "type": "boolean" + "type": "boolean", + "description": "HasEntrypoint indicates whether the binary has an entry point function." }, "importedLibraries": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "ImportedLibraries lists the shared libraries required by this executable." }, "elfSecurityFeatures": { - "$ref": "#/$defs/ELFSecurityFeatures" + "$ref": "#/$defs/ELFSecurityFeatures", + "description": "ELFSecurityFeatures contains ELF-specific security hardening information when Format is ELF." } }, "type": "object", @@ -919,7 +1279,8 @@ "hasExports", "hasEntrypoint", "importedLibraries" - ] + ], + "description": "Executable contains metadata about binary files and their security features." }, "File": { "properties": { @@ -1041,93 +1402,144 @@ "GithubActionsUseStatement": { "properties": { "value": { - "type": "string" + "type": "string", + "description": "Value is the action reference (e.g. \"actions/checkout@v3\")" }, "comment": { - "type": "string" + "type": "string", + "description": "Comment is the inline comment associated with this uses statement" } }, "type": "object", "required": [ "value" - ] + ], + "description": "GitHubActionsUseStatement represents a single 'uses' statement in a GitHub Actions workflow file referencing an action or reusable workflow." }, "GoModuleBuildinfoEntry": { "properties": { "goBuildSettings": { - "$ref": "#/$defs/KeyValues" + "$ref": "#/$defs/KeyValues", + "description": "BuildSettings contains the Go build settings and flags used to compile the binary (e.g., GOARCH, GOOS, CGO_ENABLED)." }, "goCompiledVersion": { - "type": "string" + "type": "string", + "description": "GoCompiledVersion is the version of Go used to compile the binary." }, "architecture": { - "type": "string" + "type": "string", + "description": "Architecture is the target CPU architecture for the binary (extracted from GOARCH build setting)." }, "h1Digest": { - "type": "string" + "type": "string", + "description": "H1Digest is the Go module hash in h1: format for the main module from go.sum." }, "mainModule": { - "type": "string" + "type": "string", + "description": "MainModule is the main module path for the binary (e.g., \"github.com/anchore/syft\")." }, "goCryptoSettings": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "GoCryptoSettings contains FIPS and cryptographic configuration settings if present." }, "goExperiments": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "GoExperiments lists experimental Go features enabled during compilation (e.g., \"arenas\", \"cgocheck2\")." } }, "type": "object", "required": [ "goCompiledVersion", "architecture" - ] + ], + "description": "GolangBinaryBuildinfoEntry represents all captured data for a Golang binary" }, "GoModuleEntry": { "properties": { "h1Digest": { - "type": "string" + "type": "string", + "description": "H1Digest is the Go module hash in h1: format from go.sum for verifying module contents." } }, - "type": "object" + "type": "object", + "description": "GolangModuleEntry represents all captured data for a Golang source scan with go.mod/go.sum" + }, + "GoSourceEntry": { + "properties": { + "h1Digest": { + "type": "string", + "description": "H1Digest is the Go module hash in h1: format from go.sum for verifying module contents." + }, + "os": { + "type": "string", + "description": "OperatingSystem is the target OS for build constraints (e.g., \"linux\", \"darwin\", \"windows\")." + }, + "architecture": { + "type": "string", + "description": "Architecture is the target CPU architecture for build constraints (e.g., \"amd64\", \"arm64\")." + }, + "buildTags": { + "type": "string", + "description": "BuildTags are the build tags used to conditionally compile code (e.g., \"integration,debug\")." + }, + "cgoEnabled": { + "type": "boolean", + "description": "CgoEnabled indicates whether CGO was enabled for this package." + } + }, + "type": "object", + "required": [ + "cgoEnabled" + ], + "description": "GolangSourceEntry represents all captured data for a Golang package found through source analysis" }, "HaskellHackageStackEntry": { "properties": { "pkgHash": { - "type": "string" + "type": "string", + "description": "PkgHash is the package content hash for verification" } }, - "type": "object" + "type": "object", + "description": "HackageStackYamlEntry represents a single entry from the \"extra-deps\" section of a stack.yaml file." }, "HaskellHackageStackLockEntry": { "properties": { "pkgHash": { - "type": "string" + "type": "string", + "description": "PkgHash is the package content hash for verification" }, "snapshotURL": { - "type": "string" + "type": "string", + "description": "SnapshotURL is the URL to the Stack snapshot this package came from" } }, - "type": "object" + "type": "object", + "description": "HackageStackYamlLockEntry represents a single entry from the \"packages\" section of a stack.yaml.lock file." }, "HomebrewFormula": { "properties": { "tap": { - "type": "string" + "type": "string", + "description": "Tap is Homebrew tap this formula belongs to (e.g. \"homebrew/core\")" }, "homepage": { - "type": "string" + "type": "string", + "description": "Homepage is the upstream project homepage URL" }, "description": { - "type": "string" + "type": "string", + "description": "Description is a human-readable formula description" } }, - "type": "object" + "type": "object", + "description": "HomebrewFormula represents metadata about a Homebrew formula package extracted from formula JSON files." }, "IDLikes": { "items": { @@ -1138,71 +1550,86 @@ "JavaArchive": { "properties": { "virtualPath": { - "type": "string" + "type": "string", + "description": "VirtualPath is path within the archive hierarchy, where nested entries are delimited with ':' (for nested JARs)" }, "manifest": { - "$ref": "#/$defs/JavaManifest" + "$ref": "#/$defs/JavaManifest", + "description": "Manifest is parsed META-INF/MANIFEST.MF contents" }, "pomProperties": { - "$ref": "#/$defs/JavaPomProperties" + "$ref": "#/$defs/JavaPomProperties", + "description": "PomProperties is parsed pom.properties file contents" }, "pomProject": { - "$ref": "#/$defs/JavaPomProject" + "$ref": "#/$defs/JavaPomProject", + "description": "PomProject is parsed pom.xml file contents" }, "digest": { "items": { "$ref": "#/$defs/Digest" }, - "type": "array" + "type": "array", + "description": "ArchiveDigests is cryptographic hashes of the archive file" } }, "type": "object", "required": [ "virtualPath" - ] + ], + "description": "JavaArchive encapsulates all Java ecosystem metadata for a package as well as an (optional) parent relationship." }, "JavaJvmInstallation": { "properties": { "release": { - "$ref": "#/$defs/JavaVMRelease" + "$ref": "#/$defs/JavaVMRelease", + "description": "Release is JVM release information and version details" }, "files": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Files are the list of files that are part of this JVM installation" } }, "type": "object", "required": [ "release", "files" - ] + ], + "description": "JavaVMInstallation represents a Java Virtual Machine installation discovered on the system with its release information and file list." }, "JavaManifest": { "properties": { "main": { - "$ref": "#/$defs/KeyValues" + "$ref": "#/$defs/KeyValues", + "description": "Main is main manifest attributes as key-value pairs" }, "sections": { "items": { "$ref": "#/$defs/KeyValues" }, - "type": "array" + "type": "array", + "description": "Sections are the named sections from the manifest (e.g. per-entry attributes)" } }, - "type": "object" + "type": "object", + "description": "JavaManifest represents the fields of interest extracted from a Java archive's META-INF/MANIFEST.MF file." }, "JavaPomParent": { "properties": { "groupId": { - "type": "string" + "type": "string", + "description": "GroupID is the parent Maven group identifier" }, "artifactId": { - "type": "string" + "type": "string", + "description": "ArtifactID is the parent Maven artifact identifier" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the parent version (child inherits configuration from this specific version of parent POM)" } }, "type": "object", @@ -1210,33 +1637,42 @@ "groupId", "artifactId", "version" - ] + ], + "description": "JavaPomParent contains the fields within the \u003cparent\u003e tag in a pom.xml file" }, "JavaPomProject": { "properties": { "path": { - "type": "string" + "type": "string", + "description": "Path is path to the pom.xml file within the archive" }, "parent": { - "$ref": "#/$defs/JavaPomParent" + "$ref": "#/$defs/JavaPomParent", + "description": "Parent is the parent POM reference for inheritance (child POMs inherit configuration from parent)" }, "groupId": { - "type": "string" + "type": "string", + "description": "GroupID is Maven group identifier (reversed domain name like org.apache.maven)" }, "artifactId": { - "type": "string" + "type": "string", + "description": "ArtifactID is Maven artifact identifier (project name)" }, "version": { - "type": "string" + "type": "string", + "description": "Version is project version (together with groupId and artifactId forms Maven coordinates groupId:artifactId:version)" }, "name": { - "type": "string" + "type": "string", + "description": "Name is a human-readable project name (displayed in Maven-generated documentation)" }, "description": { - "type": "string" + "type": "string", + "description": "Description is detailed project description" }, "url": { - "type": "string" + "type": "string", + "description": "URL is the project URL (typically project website or repository)" } }, "type": "object", @@ -1246,27 +1682,34 @@ "artifactId", "version", "name" - ] + ], + "description": "JavaPomProject represents fields of interest extracted from a Java archive's pom.xml file." }, "JavaPomProperties": { "properties": { "path": { - "type": "string" + "type": "string", + "description": "Path is path to the pom.properties file within the archive" }, "name": { - "type": "string" + "type": "string", + "description": "Name is the project name" }, "groupId": { - "type": "string" + "type": "string", + "description": "GroupID is Maven group identifier uniquely identifying the project across all projects (follows reversed domain name convention like com.company.project)" }, "artifactId": { - "type": "string" + "type": "string", + "description": "ArtifactID is Maven artifact identifier, the name of the jar/artifact (unique within the groupId scope)" }, "version": { - "type": "string" + "type": "string", + "description": "Version is artifact version" }, "scope": { - "type": "string" + "type": "string", + "description": "Scope is dependency scope determining when dependency is available (compile=default all phases, test=test compilation/execution only, runtime=runtime and test not compile, provided=expected from JDK or container)" }, "extraFields": { "patternProperties": { @@ -1274,7 +1717,8 @@ "type": "string" } }, - "type": "object" + "type": "object", + "description": "Extra is additional custom properties not in standard Maven coordinates" } }, "type": "object", @@ -1284,101 +1728,131 @@ "groupId", "artifactId", "version" - ] + ], + "description": "JavaPomProperties represents the fields of interest extracted from a Java archive's pom.properties file." }, "JavaVMRelease": { "properties": { "implementor": { - "type": "string" + "type": "string", + "description": "Implementor is extracted with the `java.vendor` JVM property" }, "implementorVersion": { - "type": "string" + "type": "string", + "description": "ImplementorVersion is extracted with the `java.vendor.version` JVM property" }, "javaRuntimeVersion": { - "type": "string" + "type": "string", + "description": "JavaRuntimeVersion is extracted from the 'java.runtime.version' JVM property" }, "javaVersion": { - "type": "string" + "type": "string", + "description": "JavaVersion matches that from `java -version` command output" }, "javaVersionDate": { - "type": "string" + "type": "string", + "description": "JavaVersionDate is extracted from the 'java.version.date' JVM property" }, "libc": { - "type": "string" + "type": "string", + "description": "Libc can either be 'glibc' or 'musl'" }, "modules": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Modules is a list of JVM modules that are packaged" }, "osArch": { - "type": "string" + "type": "string", + "description": "OsArch is the target CPU architecture" }, "osName": { - "type": "string" + "type": "string", + "description": "OsName is the name of the target runtime operating system environment" }, "osVersion": { - "type": "string" + "type": "string", + "description": "OsVersion is the version of the target runtime operating system environment" }, "source": { - "type": "string" + "type": "string", + "description": "Source refers to the origin repository of OpenJDK source" }, "buildSource": { - "type": "string" + "type": "string", + "description": "BuildSource Git SHA of the build repository" }, "buildSourceRepo": { - "type": "string" + "type": "string", + "description": "BuildSourceRepo refers to rhe repository URL for the build source" }, "sourceRepo": { - "type": "string" + "type": "string", + "description": "SourceRepo refers to the OpenJDK repository URL" }, "fullVersion": { - "type": "string" + "type": "string", + "description": "FullVersion is extracted from the 'java.runtime.version' JVM property" }, "semanticVersion": { - "type": "string" + "type": "string", + "description": "SemanticVersion is derived from the OpenJDK version" }, "buildInfo": { - "type": "string" + "type": "string", + "description": "BuildInfo contains additional build information" }, "jvmVariant": { - "type": "string" + "type": "string", + "description": "JvmVariant specifies the JVM variant (e.g., Hotspot or OpenJ9)" }, "jvmVersion": { - "type": "string" + "type": "string", + "description": "JvmVersion is extracted from the 'java.vm.version' JVM property" }, "imageType": { - "type": "string" + "type": "string", + "description": "ImageType can be 'JDK' or 'JRE'" }, "buildType": { - "type": "string" + "type": "string", + "description": "BuildType can be 'commercial' (used in some older oracle JDK distributions)" } }, - "type": "object" + "type": "object", + "description": "JavaVMRelease represents JVM version and build information extracted from the release file in a Java installation." }, "JavascriptNpmPackage": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the package name as found in package.json" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version as found in package.json" }, "author": { - "type": "string" + "type": "string", + "description": "Author is package author name" }, "homepage": { - "type": "string" + "type": "string", + "description": "Homepage is project homepage URL" }, "description": { - "type": "string" + "type": "string", + "description": "Description is a human-readable package description" }, "url": { - "type": "string" + "type": "string", + "description": "URL is repository or project URL" }, "private": { - "type": "boolean" + "type": "boolean", + "description": "Private is whether this is a private package" } }, "type": "object", @@ -1390,58 +1864,69 @@ "description", "url", "private" - ] + ], + "description": "NpmPackage represents the contents of a javascript package.json file." }, "JavascriptNpmPackageLockEntry": { "properties": { "resolved": { - "type": "string" + "type": "string", + "description": "Resolved is URL where this package was downloaded from (registry source)" }, "integrity": { - "type": "string" + "type": "string", + "description": "Integrity is Subresource Integrity hash for verification using standard SRI format (sha512-... or sha1-...). npm changed from SHA-1 to SHA-512 in newer versions. For registry sources this is the integrity from registry, for remote tarballs it's SHA-512 of the file. npm verifies tarball matches this hash before unpacking, throwing EINTEGRITY error if mismatch detected." } }, "type": "object", "required": [ "resolved", "integrity" - ] + ], + "description": "NpmPackageLockEntry represents a single entry within the \"packages\" section of a package-lock.json file." }, "JavascriptYarnLockEntry": { "properties": { "resolved": { - "type": "string" + "type": "string", + "description": "Resolved is URL where this package was downloaded from" }, "integrity": { - "type": "string" + "type": "string", + "description": "Integrity is Subresource Integrity hash for verification (SRI format)" } }, "type": "object", "required": [ "resolved", "integrity" - ] + ], + "description": "YarnLockEntry represents a single entry section of a yarn.lock file." }, "KeyValue": { "properties": { "key": { - "type": "string" + "type": "string", + "description": "Key is the key name" }, "value": { - "type": "string" + "type": "string", + "description": "Value is the value associated with the key" } }, "type": "object", "required": [ "key", "value" - ] + ], + "description": "KeyValue represents a single key-value pair." }, "KeyValues": { "items": { "$ref": "#/$defs/KeyValue" }, - "type": "array" + "type": "array", + "description": "KeyValues represents an ordered collection of key-value pairs that preserves insertion order." }, "License": { "properties": { @@ -1482,37 +1967,48 @@ "LinuxKernelArchive": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is kernel name (typically \"Linux\")" }, "architecture": { - "type": "string" + "type": "string", + "description": "Architecture is the target CPU architecture" }, "version": { - "type": "string" + "type": "string", + "description": "Version is kernel version string" }, "extendedVersion": { - "type": "string" + "type": "string", + "description": "ExtendedVersion is additional version information" }, "buildTime": { - "type": "string" + "type": "string", + "description": "BuildTime is when the kernel was built" }, "author": { - "type": "string" + "type": "string", + "description": "Author is who built the kernel" }, "format": { - "type": "string" + "type": "string", + "description": "Format is kernel image format (e.g. bzImage, zImage)" }, "rwRootFS": { - "type": "boolean" + "type": "boolean", + "description": "RWRootFS is whether root filesystem is mounted read-write" }, "swapDevice": { - "type": "integer" + "type": "integer", + "description": "SwapDevice is swap device number" }, "rootDevice": { - "type": "integer" + "type": "integer", + "description": "RootDevice is root device number" }, "videoMode": { - "type": "string" + "type": "string", + "description": "VideoMode is default video mode setting" } }, "type": "object", @@ -1520,36 +2016,46 @@ "name", "architecture", "version" - ] + ], + "description": "LinuxKernel represents all captured data for a Linux kernel" }, "LinuxKernelModule": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is module name" }, "version": { - "type": "string" + "type": "string", + "description": "Version is module version string" }, "sourceVersion": { - "type": "string" + "type": "string", + "description": "SourceVersion is the source code version identifier" }, "path": { - "type": "string" + "type": "string", + "description": "Path is the filesystem path to the .ko kernel object file (absolute path)" }, "description": { - "type": "string" + "type": "string", + "description": "Description is a human-readable module description" }, "author": { - "type": "string" + "type": "string", + "description": "Author is module author name and email" }, "license": { - "type": "string" + "type": "string", + "description": "License is module license (e.g. GPL, BSD) which must be compatible with kernel" }, "kernelVersion": { - "type": "string" + "type": "string", + "description": "KernelVersion is kernel version this module was built for" }, "versionMagic": { - "type": "string" + "type": "string", + "description": "VersionMagic is version magic string for compatibility checking (includes kernel version, SMP status, module loading capabilities like \"3.17.4-302.fc21.x86_64 SMP mod_unload modversions\"). Module will NOT load if vermagic doesn't match running kernel." }, "parameters": { "patternProperties": { @@ -1557,21 +2063,26 @@ "$ref": "#/$defs/LinuxKernelModuleParameter" } }, - "type": "object" + "type": "object", + "description": "Parameters are the module parameters that can be configured at load time (user-settable values like module options)" } }, - "type": "object" + "type": "object", + "description": "LinuxKernelModule represents a loadable kernel module (.ko file) with its metadata, parameters, and dependencies." }, "LinuxKernelModuleParameter": { "properties": { "type": { - "type": "string" + "type": "string", + "description": "Type is parameter data type (e.g. int, string, bool, array types)" }, "description": { - "type": "string" + "type": "string", + "description": "Description is a human-readable parameter description explaining what the parameter controls" } }, - "type": "object" + "type": "object", + "description": "LinuxKernelModuleParameter represents a configurable parameter for a kernel module with its type and description." }, "LinuxRelease": { "properties": { @@ -1628,6 +2139,9 @@ }, "supportEnd": { "type": "string" + }, + "extendedSupport": { + "type": "boolean" } }, "type": "object" @@ -1635,13 +2149,16 @@ "Location": { "properties": { "path": { - "type": "string" + "type": "string", + "description": "RealPath is the canonical absolute form of the path accessed (all symbolic links have been followed and relative path components like '.' and '..' have been removed)." }, "layerID": { - "type": "string" + "type": "string", + "description": "FileSystemID is an ID representing and entire filesystem. For container images, this is a layer digest. For directories or a root filesystem, this is blank." }, "accessPath": { - "type": "string" + "type": "string", + "description": "AccessPath is the path used to retrieve file contents (which may or may not have hardlinks / symlinks in the path)" }, "annotations": { "patternProperties": { @@ -1656,27 +2173,34 @@ "required": [ "path", "accessPath" - ] + ], + "description": "Location represents a path relative to a particular filesystem resolved to a specific file.Reference." }, "LuarocksPackage": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the package name as found in the .rockspec file" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version as found in the .rockspec file" }, "license": { - "type": "string" + "type": "string", + "description": "License is license identifier" }, "homepage": { - "type": "string" + "type": "string", + "description": "Homepage is project homepage URL" }, "description": { - "type": "string" + "type": "string", + "description": "Description is a human-readable package description" }, "url": { - "type": "string" + "type": "string", + "description": "URL is the source download URL" }, "dependencies": { "patternProperties": { @@ -1684,7 +2208,8 @@ "type": "string" } }, - "type": "object" + "type": "object", + "description": "Dependencies are the map of dependency names to version constraints" } }, "type": "object", @@ -1696,117 +2221,142 @@ "description", "url", "dependencies" - ] + ], + "description": "LuaRocksPackage represents a Lua package managed by the LuaRocks package manager with metadata from .rockspec files." }, "MicrosoftKbPatch": { "properties": { "product_id": { - "type": "string" + "type": "string", + "description": "ProductID is MSRC Product ID (e.g. \"Windows 10 Version 1703 for 32-bit Systems\")" }, "kb": { - "type": "string" + "type": "string", + "description": "Kb is Knowledge Base article number (e.g. \"5001028\")" } }, "type": "object", "required": [ "product_id", "kb" - ] + ], + "description": "MicrosoftKbPatch is slightly odd in how it is expected to map onto data." }, "NixDerivation": { "properties": { "path": { - "type": "string" + "type": "string", + "description": "Path is path to the .drv file in Nix store" }, "system": { - "type": "string" + "type": "string", + "description": "System is target system string indicating where derivation can be built (e.g. \"x86_64-linux\", \"aarch64-darwin\"). Must match current system for local builds." }, "inputDerivations": { "items": { "$ref": "#/$defs/NixDerivationReference" }, - "type": "array" + "type": "array", + "description": "InputDerivations are the list of other derivations that were inputs to this build (dependencies)" }, "inputSources": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "InputSources are the list of source file paths that were inputs to this build" } }, - "type": "object" + "type": "object", + "description": "NixDerivation represents a Nix .drv file that describes how to build a package including inputs, outputs, and build instructions." }, "NixDerivationReference": { "properties": { "path": { - "type": "string" + "type": "string", + "description": "Path is path to the referenced .drv file" }, "outputs": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Outputs are which outputs of the referenced derivation were used (e.g. [\"out\"], [\"bin\", \"dev\"])" } }, - "type": "object" + "type": "object", + "description": "NixDerivationReference represents a reference to another derivation used as a build input or runtime dependency." }, "NixStoreEntry": { "properties": { "path": { - "type": "string" + "type": "string", + "description": "Path is full store path for this output (e.g. /nix/store/abc123...-package-1.0)" }, "output": { - "type": "string" + "type": "string", + "description": "Output is the specific output name for multi-output packages (empty string for default \"out\" output, can be \"bin\", \"dev\", \"doc\", etc.)" }, "outputHash": { - "type": "string" + "type": "string", + "description": "OutputHash is hash prefix of the store path basename (first part before the dash)" }, "derivation": { - "$ref": "#/$defs/NixDerivation" + "$ref": "#/$defs/NixDerivation", + "description": "Derivation is information about the .drv file that describes how this package was built" }, "files": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Files are the list of files under the nix/store path for this package" } }, "type": "object", "required": [ "outputHash" - ] + ], + "description": "NixStoreEntry represents a package in the Nix store (/nix/store) with its derivation information and metadata." }, "OpamPackage": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the package name as found in the .opam file" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version as found in the .opam file" }, "licenses": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Licenses are the list of applicable licenses" }, "url": { - "type": "string" + "type": "string", + "description": "URL is download URL for the package source" }, "checksum": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Checksums are the list of checksums for verification" }, "homepage": { - "type": "string" + "type": "string", + "description": "Homepage is project homepage URL" }, "dependencies": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Dependencies are the list of required dependencies" } }, "type": "object", @@ -1818,7 +2368,8 @@ "checksum", "homepage", "dependencies" - ] + ], + "description": "OpamPackage represents an OCaml package managed by the OPAM package manager with metadata from .opam files." }, "Package": { "properties": { @@ -1890,6 +2441,9 @@ { "$ref": "#/$defs/CocoaPodfileLockEntry" }, + { + "$ref": "#/$defs/CondaMetadataEntry" + }, { "$ref": "#/$defs/DartPubspec" }, @@ -1929,6 +2483,9 @@ { "$ref": "#/$defs/GoModuleEntry" }, + { + "$ref": "#/$defs/GoSourceEntry" + }, { "$ref": "#/$defs/HaskellHackageStackEntry" }, @@ -2001,6 +2558,9 @@ { "$ref": "#/$defs/PythonPoetryLockEntry" }, + { + "$ref": "#/$defs/PythonUvLockEntry" + }, { "$ref": "#/$defs/RDescription" }, @@ -2019,6 +2579,9 @@ { "$ref": "#/$defs/RustCargoLockEntry" }, + { + "$ref": "#/$defs/SnapEntry" + }, { "$ref": "#/$defs/SwiftPackageManagerLockEntry" }, @@ -2046,49 +2609,60 @@ "language", "cpes", "purl" - ] + ], + "description": "Package represents a pkg.Package object specialized for JSON marshaling and unmarshalling." }, "PeBinary": { "properties": { "VersionResources": { - "$ref": "#/$defs/KeyValues" + "$ref": "#/$defs/KeyValues", + "description": "VersionResources contains key-value pairs extracted from the PE file's version resource section (e.g., FileVersion, ProductName, CompanyName)." } }, "type": "object", "required": [ "VersionResources" - ] + ], + "description": "PEBinary represents metadata captured from a Portable Executable formatted binary (dll, exe, etc.)" }, "PhpComposerAuthors": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is author's full name" }, "email": { - "type": "string" + "type": "string", + "description": "Email is author's email address" }, "homepage": { - "type": "string" + "type": "string", + "description": "Homepage is author's personal or company website" } }, "type": "object", "required": [ "name" - ] + ], + "description": "PhpComposerAuthors represents author information for a PHP Composer package from the authors field in composer.json." }, "PhpComposerExternalReference": { "properties": { "type": { - "type": "string" + "type": "string", + "description": "Type is reference type (git for source VCS, zip/tar for dist archives)" }, "url": { - "type": "string" + "type": "string", + "description": "URL is the URL to the resource (git repository URL or archive download URL)" }, "reference": { - "type": "string" + "type": "string", + "description": "Reference is git commit hash or version tag for source, or archive version for dist" }, "shasum": { - "type": "string" + "type": "string", + "description": "Shasum is SHA hash of the archive file for integrity verification (dist only)" } }, "type": "object", @@ -2096,21 +2670,26 @@ "type", "url", "reference" - ] + ], + "description": "PhpComposerExternalReference represents source or distribution information for a PHP package, indicating where the package code is retrieved from." }, "PhpComposerInstalledEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is package name in vendor/package format (e.g. symfony/console)" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version" }, "source": { - "$ref": "#/$defs/PhpComposerExternalReference" + "$ref": "#/$defs/PhpComposerExternalReference", + "description": "Source is the source repository information for development (typically git repo, used when passing --prefer-source). Originates from source code repository." }, "dist": { - "$ref": "#/$defs/PhpComposerExternalReference" + "$ref": "#/$defs/PhpComposerExternalReference", + "description": "Dist is distribution archive information for production (typically zip/tar, default install method). Packaged version of released code." }, "require": { "patternProperties": { @@ -2118,7 +2697,8 @@ "type": "string" } }, - "type": "object" + "type": "object", + "description": "Require is runtime dependencies with version constraints (package will not install unless these requirements can be met)" }, "provide": { "patternProperties": { @@ -2126,7 +2706,8 @@ "type": "string" } }, - "type": "object" + "type": "object", + "description": "Provide is virtual packages/functionality provided by this package (allows other packages to depend on capabilities)" }, "require-dev": { "patternProperties": { @@ -2134,7 +2715,8 @@ "type": "string" } }, - "type": "object" + "type": "object", + "description": "RequireDev is development-only dependencies (not installed in production, only when developing this package or running tests)" }, "suggest": { "patternProperties": { @@ -2142,46 +2724,56 @@ "type": "string" } }, - "type": "object" + "type": "object", + "description": "Suggest is optional but recommended dependencies (suggestions for packages that would extend functionality)" }, "license": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "License is the list of license identifiers (SPDX format)" }, "type": { - "type": "string" + "type": "string", + "description": "Type is package type indicating purpose (library=reusable code, project=application, metapackage=aggregates dependencies, etc.)" }, "notification-url": { - "type": "string" + "type": "string", + "description": "NotificationURL is the URL to notify when package is installed (for tracking/statistics)" }, "bin": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Bin is the list of binary/executable files that should be added to PATH" }, "authors": { "items": { "$ref": "#/$defs/PhpComposerAuthors" }, - "type": "array" + "type": "array", + "description": "Authors are the list of package authors with name/email/homepage" }, "description": { - "type": "string" + "type": "string", + "description": "Description is a human-readable package description" }, "homepage": { - "type": "string" + "type": "string", + "description": "Homepage is project homepage URL" }, "keywords": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Keywords are the list of keywords for package discovery/search" }, "time": { - "type": "string" + "type": "string", + "description": "Time is timestamp when this package version was released" } }, "type": "object", @@ -2190,21 +2782,26 @@ "version", "source", "dist" - ] + ], + "description": "PhpComposerInstalledEntry represents a single package entry from a composer v1/v2 \"installed.json\" files (very similar to composer.lock files)." }, "PhpComposerLockEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is package name in vendor/package format (e.g. symfony/console)" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version" }, "source": { - "$ref": "#/$defs/PhpComposerExternalReference" + "$ref": "#/$defs/PhpComposerExternalReference", + "description": "Source is the source repository information for development (typically git repo, used when passing --prefer-source). Originates from source code repository." }, "dist": { - "$ref": "#/$defs/PhpComposerExternalReference" + "$ref": "#/$defs/PhpComposerExternalReference", + "description": "Dist is distribution archive information for production (typically zip/tar, default install method). Packaged version of released code." }, "require": { "patternProperties": { @@ -2212,7 +2809,8 @@ "type": "string" } }, - "type": "object" + "type": "object", + "description": "Require is runtime dependencies with version constraints (package will not install unless these requirements can be met)" }, "provide": { "patternProperties": { @@ -2220,7 +2818,8 @@ "type": "string" } }, - "type": "object" + "type": "object", + "description": "Provide is virtual packages/functionality provided by this package (allows other packages to depend on capabilities)" }, "require-dev": { "patternProperties": { @@ -2228,7 +2827,8 @@ "type": "string" } }, - "type": "object" + "type": "object", + "description": "RequireDev is development-only dependencies (not installed in production, only when developing this package or running tests)" }, "suggest": { "patternProperties": { @@ -2236,46 +2836,56 @@ "type": "string" } }, - "type": "object" + "type": "object", + "description": "Suggest is optional but recommended dependencies (suggestions for packages that would extend functionality)" }, "license": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "License is the list of license identifiers (SPDX format)" }, "type": { - "type": "string" + "type": "string", + "description": "Type is package type indicating purpose (library=reusable code, project=application, metapackage=aggregates dependencies, etc.)" }, "notification-url": { - "type": "string" + "type": "string", + "description": "NotificationURL is the URL to notify when package is installed (for tracking/statistics)" }, "bin": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Bin is the list of binary/executable files that should be added to PATH" }, "authors": { "items": { "$ref": "#/$defs/PhpComposerAuthors" }, - "type": "array" + "type": "array", + "description": "Authors are the list of package authors with name/email/homepage" }, "description": { - "type": "string" + "type": "string", + "description": "Description is a human-readable package description" }, "homepage": { - "type": "string" + "type": "string", + "description": "Homepage is project homepage URL" }, "keywords": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Keywords are the list of keywords for package discovery/search" }, "time": { - "type": "string" + "type": "string", + "description": "Time is timestamp when this package version was released" } }, "type": "object", @@ -2284,189 +2894,230 @@ "version", "source", "dist" - ] + ], + "description": "PhpComposerLockEntry represents a single package entry found from a composer.lock file." }, "PhpPearEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the package name" }, "channel": { - "type": "string" + "type": "string", + "description": "Channel is PEAR channel this package is from" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version" }, "license": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "License is the list of applicable licenses" } }, "type": "object", "required": [ "name", "version" - ] + ], + "description": "PhpPearEntry represents a single package entry found within php pear metadata files." }, "PhpPeclEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the package name" }, "channel": { - "type": "string" + "type": "string", + "description": "Channel is PEAR channel this package is from" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version" }, "license": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "License is the list of applicable licenses" } }, "type": "object", "required": [ "name", "version" - ] + ], + "description": "PhpPeclEntry represents a single package entry found within php pecl metadata files." }, "PortageDbEntry": { "properties": { "installedSize": { - "type": "integer" + "type": "integer", + "description": "InstalledSize is total size of installed files in bytes" }, "licenses": { - "type": "string" + "type": "string", + "description": "Licenses is license string which may be an expression (e.g. \"GPL-2 OR Apache-2.0\")" }, "files": { "items": { "$ref": "#/$defs/PortageFileRecord" }, - "type": "array" + "type": "array", + "description": "Files are the files installed by this package (tracked in CONTENTS file)" } }, "type": "object", "required": [ "installedSize", "files" - ] + ], + "description": "PortageEntry represents a single package entry in the portage DB flat-file store." }, "PortageFileRecord": { "properties": { "path": { - "type": "string" + "type": "string", + "description": "Path is the file path relative to the filesystem root" }, "digest": { - "$ref": "#/$defs/Digest" + "$ref": "#/$defs/Digest", + "description": "Digest is file content hash (MD5 for regular files in CONTENTS format: \"obj filename md5hash mtime\")" } }, "type": "object", "required": [ "path" - ] + ], + "description": "PortageFileRecord represents a single file attributed to a portage package." }, "PythonDirectURLOriginInfo": { "properties": { "url": { - "type": "string" + "type": "string", + "description": "URL is the source URL from which the package was installed." }, "commitId": { - "type": "string" + "type": "string", + "description": "CommitID is the VCS commit hash if installed from version control." }, "vcs": { - "type": "string" + "type": "string", + "description": "VCS is the version control system type (e.g., \"git\", \"hg\")." } }, "type": "object", "required": [ "url" - ] + ], + "description": "PythonDirectURLOriginInfo represents installation source metadata from direct_url.json for packages installed from VCS or direct URLs." }, "PythonFileDigest": { "properties": { "algorithm": { - "type": "string" + "type": "string", + "description": "Algorithm is the hash algorithm used (e.g., \"sha256\")." }, "value": { - "type": "string" + "type": "string", + "description": "Value is the hex-encoded hash digest value." } }, "type": "object", "required": [ "algorithm", "value" - ] + ], + "description": "PythonFileDigest represents the file metadata for a single file attributed to a python package." }, "PythonFileRecord": { "properties": { "path": { - "type": "string" + "type": "string", + "description": "Path is the installed file path from the RECORD file." }, "digest": { - "$ref": "#/$defs/PythonFileDigest" + "$ref": "#/$defs/PythonFileDigest", + "description": "Digest contains the hash algorithm and value for file integrity verification." }, "size": { - "type": "string" + "type": "string", + "description": "Size is the file size in bytes as a string." } }, "type": "object", "required": [ "path" - ] + ], + "description": "PythonFileRecord represents a single entry within a RECORD file for a python wheel or egg package" }, "PythonPackage": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the package name from the Name field in PKG-INFO or METADATA." }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version from the Version field in PKG-INFO or METADATA." }, "author": { - "type": "string" + "type": "string", + "description": "Author is the package author name from the Author field." }, "authorEmail": { - "type": "string" + "type": "string", + "description": "AuthorEmail is the package author's email address from the Author-Email field." }, "platform": { - "type": "string" + "type": "string", + "description": "Platform indicates the target platform for the package (e.g., \"any\", \"linux\", \"win32\")." }, "files": { "items": { "$ref": "#/$defs/PythonFileRecord" }, - "type": "array" + "type": "array", + "description": "Files are the installed files listed in the RECORD file for wheels or installed-files.txt for eggs." }, "sitePackagesRootPath": { - "type": "string" + "type": "string", + "description": "SitePackagesRootPath is the root directory path containing the package (e.g., \"/usr/lib/python3.9/site-packages\")." }, "topLevelPackages": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "TopLevelPackages are the top-level Python module names from top_level.txt file." }, "directUrlOrigin": { - "$ref": "#/$defs/PythonDirectURLOriginInfo" + "$ref": "#/$defs/PythonDirectURLOriginInfo", + "description": "DirectURLOrigin contains VCS or direct URL installation information from direct_url.json." }, "requiresPython": { - "type": "string" + "type": "string", + "description": "RequiresPython specifies the Python version requirement (e.g., \"\u003e=3.6\")." }, "requiresDist": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "RequiresDist lists the package dependencies with version specifiers from Requires-Dist fields." }, "providesExtra": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "ProvidesExtra lists optional feature names that can be installed via extras (e.g., \"dev\", \"test\")." } }, "type": "object", @@ -2477,34 +3128,41 @@ "authorEmail", "platform", "sitePackagesRootPath" - ] + ], + "description": "PythonPackage represents all captured data for a python egg or wheel package (specifically as outlined in the PyPA core metadata specification https://packaging.python.org/en/latest/specifications/core-metadata/)." }, "PythonPipRequirementsEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the package name from the requirements file." }, "extras": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Extras are the optional features to install from the package (e.g., package[dev,test])." }, "versionConstraint": { - "type": "string" + "type": "string", + "description": "VersionConstraint specifies version requirements (e.g., \"\u003e=1.0,\u003c2.0\")." }, "url": { - "type": "string" + "type": "string", + "description": "URL is the direct download URL or VCS URL if specified instead of a PyPI package." }, "markers": { - "type": "string" + "type": "string", + "description": "Markers are environment marker expressions for conditional installation (e.g., \"python_version \u003e= '3.8'\")." } }, "type": "object", "required": [ "name", "versionConstraint" - ] + ], + "description": "PythonRequirementsEntry represents a single entry within a [*-]requirements.txt file." }, "PythonPipfileLockEntry": { "properties": { @@ -2512,37 +3170,45 @@ "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Hashes are the package file hash values in the format \"algorithm:digest\" for integrity verification." }, "index": { - "type": "string" + "type": "string", + "description": "Index is the PyPI index name where the package should be fetched from." } }, "type": "object", "required": [ "hashes", "index" - ] + ], + "description": "PythonPipfileLockEntry represents a single package entry within a Pipfile.lock file." }, "PythonPoetryLockDependencyEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the dependency package name." }, "version": { - "type": "string" + "type": "string", + "description": "Version is the locked version or version constraint for the dependency." }, "optional": { - "type": "boolean" + "type": "boolean", + "description": "Optional indicates whether this dependency is optional (only needed for certain extras)." }, "markers": { - "type": "string" + "type": "string", + "description": "Markers are environment marker expressions that conditionally enable the dependency (e.g., \"python_version \u003e= '3.8'\")." }, "extras": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Extras are the optional feature names from the dependency that should be installed." } }, "type": "object", @@ -2550,99 +3216,197 @@ "name", "version", "optional" - ] + ], + "description": "PythonPoetryLockDependencyEntry represents a single dependency entry within a Poetry lock file." }, "PythonPoetryLockEntry": { "properties": { "index": { - "type": "string" + "type": "string", + "description": "Index is the package repository name where the package should be fetched from." }, "dependencies": { "items": { "$ref": "#/$defs/PythonPoetryLockDependencyEntry" }, - "type": "array" + "type": "array", + "description": "Dependencies are the package's runtime dependencies with version constraints." }, "extras": { "items": { "$ref": "#/$defs/PythonPoetryLockExtraEntry" }, - "type": "array" + "type": "array", + "description": "Extras are optional feature groups that include additional dependencies." } }, "type": "object", "required": [ "index", "dependencies" - ] + ], + "description": "PythonPoetryLockEntry represents a single package entry within a Pipfile.lock file." }, "PythonPoetryLockExtraEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the optional feature name (e.g., \"dev\", \"test\")." }, "dependencies": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Dependencies are the package names required when this extra is installed." } }, "type": "object", "required": [ "name", "dependencies" - ] + ], + "description": "PythonPoetryLockExtraEntry represents an optional feature group in a Poetry lock file." + }, + "PythonUvLockDependencyEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the dependency package name." + }, + "optional": { + "type": "boolean", + "description": "Optional indicates whether this dependency is optional (only needed for certain extras)." + }, + "markers": { + "type": "string", + "description": "Markers are environment marker expressions that conditionally enable the dependency (e.g., \"python_version \u003e= '3.8'\")." + }, + "extras": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Extras are the optional feature names from the dependency that should be installed." + } + }, + "type": "object", + "required": [ + "name", + "optional" + ], + "description": "PythonUvLockDependencyEntry represents a single dependency entry within a uv lock file." + }, + "PythonUvLockEntry": { + "properties": { + "index": { + "type": "string", + "description": "Index is the package repository name where the package should be fetched from." + }, + "dependencies": { + "items": { + "$ref": "#/$defs/PythonUvLockDependencyEntry" + }, + "type": "array", + "description": "Dependencies are the package's runtime dependencies with version constraints." + }, + "extras": { + "items": { + "$ref": "#/$defs/PythonUvLockExtraEntry" + }, + "type": "array", + "description": "Extras are optional feature groups that include additional dependencies." + } + }, + "type": "object", + "required": [ + "index", + "dependencies" + ], + "description": "PythonUvLockEntry represents a single package entry within a uv.lock file." + }, + "PythonUvLockExtraEntry": { + "properties": { + "name": { + "type": "string", + "description": "Name is the optional feature name (e.g., \"dev\", \"test\")." + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array", + "description": "Dependencies are the package names required when this extra is installed." + } + }, + "type": "object", + "required": [ + "name", + "dependencies" + ], + "description": "PythonUvLockExtraEntry represents an optional feature group in a uv lock file." }, "RDescription": { "properties": { "title": { - "type": "string" + "type": "string", + "description": "Title is short one-line package title" }, "description": { - "type": "string" + "type": "string", + "description": "Description is detailed package description" }, "author": { - "type": "string" + "type": "string", + "description": "Author is package author(s)" }, "maintainer": { - "type": "string" + "type": "string", + "description": "Maintainer is current package maintainer" }, "url": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "URL is the list of related URLs" }, "repository": { - "type": "string" + "type": "string", + "description": "Repository is CRAN or other repository name" }, "built": { - "type": "string" + "type": "string", + "description": "Built is R version and platform this was built with" }, "needsCompilation": { - "type": "boolean" + "type": "boolean", + "description": "NeedsCompilation is whether this package requires compilation" }, "imports": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Imports are the packages imported in the NAMESPACE" }, "depends": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Depends are the packages this package depends on" }, "suggests": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Suggests are the optional packages that extend functionality" } }, - "type": "object" + "type": "object", + "description": "RDescription represents metadata from an R package DESCRIPTION file containing package information, dependencies, and author details." }, "Relationship": { "properties": { @@ -2667,15 +3431,18 @@ "RpmArchive": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the RPM package name as found in the RPM database." }, "version": { - "type": "string" + "type": "string", + "description": "Version is the upstream version of the package." }, "epoch": { "oneOf": [ { - "type": "integer" + "type": "integer", + "description": "Epoch is the version epoch used to force upgrade ordering (null if not set)." }, { "type": "null" @@ -2683,46 +3450,56 @@ ] }, "architecture": { - "type": "string" + "type": "string", + "description": "Arch is the target CPU architecture (e.g., \"x86_64\", \"aarch64\", \"noarch\")." }, "release": { - "type": "string" + "type": "string", + "description": "Release is the package release number or distribution-specific version suffix." }, "sourceRpm": { - "type": "string" + "type": "string", + "description": "SourceRpm is the source RPM filename that was used to build this package." }, "signatures": { "items": { "$ref": "#/$defs/RpmSignature" }, - "type": "array" + "type": "array", + "description": "Signatures contains GPG signature metadata for package verification." }, "size": { - "type": "integer" + "type": "integer", + "description": "Size is the total installed size of the package in bytes." }, "vendor": { - "type": "string" + "type": "string", + "description": "Vendor is the organization that packaged the software." }, "modularityLabel": { - "type": "string" + "type": "string", + "description": "ModularityLabel identifies the module stream for modular RPM packages (e.g., \"nodejs:12:20200101\")." }, "provides": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Provides lists the virtual packages and capabilities this package provides." }, "requires": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Requires lists the dependencies required by this package." }, "files": { "items": { "$ref": "#/$defs/RpmFileRecord" }, - "type": "array" + "type": "array", + "description": "Files are the file records for all files owned by this package." } }, "type": "object", @@ -2736,20 +3513,24 @@ "size", "vendor", "files" - ] + ], + "description": "RpmArchive represents package metadata extracted directly from a .rpm archive file, containing the same information as an RPM database entry." }, "RpmDbEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the RPM package name as found in the RPM database." }, "version": { - "type": "string" + "type": "string", + "description": "Version is the upstream version of the package." }, "epoch": { "oneOf": [ { - "type": "integer" + "type": "integer", + "description": "Epoch is the version epoch used to force upgrade ordering (null if not set)." }, { "type": "null" @@ -2757,46 +3538,56 @@ ] }, "architecture": { - "type": "string" + "type": "string", + "description": "Arch is the target CPU architecture (e.g., \"x86_64\", \"aarch64\", \"noarch\")." }, "release": { - "type": "string" + "type": "string", + "description": "Release is the package release number or distribution-specific version suffix." }, "sourceRpm": { - "type": "string" + "type": "string", + "description": "SourceRpm is the source RPM filename that was used to build this package." }, "signatures": { "items": { "$ref": "#/$defs/RpmSignature" }, - "type": "array" + "type": "array", + "description": "Signatures contains GPG signature metadata for package verification." }, "size": { - "type": "integer" + "type": "integer", + "description": "Size is the total installed size of the package in bytes." }, "vendor": { - "type": "string" + "type": "string", + "description": "Vendor is the organization that packaged the software." }, "modularityLabel": { - "type": "string" + "type": "string", + "description": "ModularityLabel identifies the module stream for modular RPM packages (e.g., \"nodejs:12:20200101\")." }, "provides": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Provides lists the virtual packages and capabilities this package provides." }, "requires": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Requires lists the dependencies required by this package." }, "files": { "items": { "$ref": "#/$defs/RpmFileRecord" }, - "type": "array" + "type": "array", + "description": "Files are the file records for all files owned by this package." } }, "type": "object", @@ -2810,30 +3601,38 @@ "size", "vendor", "files" - ] + ], + "description": "RpmDBEntry represents all captured data from a RPM DB package entry." }, "RpmFileRecord": { "properties": { "path": { - "type": "string" + "type": "string", + "description": "Path is the absolute file path where the file is installed." }, "mode": { - "type": "integer" + "type": "integer", + "description": "Mode is the file permission mode bits following Unix stat.h conventions." }, "size": { - "type": "integer" + "type": "integer", + "description": "Size is the file size in bytes." }, "digest": { - "$ref": "#/$defs/Digest" + "$ref": "#/$defs/Digest", + "description": "Digest contains the hash algorithm and value for file integrity verification." }, "userName": { - "type": "string" + "type": "string", + "description": "UserName is the owner username for the file." }, "groupName": { - "type": "string" + "type": "string", + "description": "GroupName is the group name for the file." }, "flags": { - "type": "string" + "type": "string", + "description": "Flags indicates the file type (e.g., \"%config\", \"%doc\", \"%ghost\")." } }, "type": "object", @@ -2845,21 +3644,26 @@ "userName", "groupName", "flags" - ] + ], + "description": "RpmFileRecord represents the file metadata for a single file attributed to a RPM package." }, "RpmSignature": { "properties": { "algo": { - "type": "string" + "type": "string", + "description": "PublicKeyAlgorithm is the public key algorithm used for signing (e.g., \"RSA\")." }, "hash": { - "type": "string" + "type": "string", + "description": "HashAlgorithm is the hash algorithm used for the signature (e.g., \"SHA256\")." }, "created": { - "type": "string" + "type": "string", + "description": "Created is the timestamp when the signature was created." }, "issuer": { - "type": "string" + "type": "string", + "description": "IssuerKeyID is the GPG key ID that created the signature." } }, "type": "object", @@ -2868,48 +3672,58 @@ "hash", "created", "issuer" - ] + ], + "description": "RpmSignature represents a GPG signature for an RPM package used for authenticity verification." }, "RubyGemspec": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is gem name as specified in the gemspec" }, "version": { - "type": "string" + "type": "string", + "description": "Version is gem version as specified in the gemspec" }, "files": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Files is logical list of files in the gem (NOT directly usable as filesystem paths. Example: bundler gem lists \"lib/bundler/vendor/uri/lib/uri/ldap.rb\" but actual path is \"/usr/local/lib/ruby/3.2.0/bundler/vendor/uri/lib/uri/ldap.rb\". Would need gem installation path, ruby version, and env vars like GEM_HOME to resolve actual paths.)" }, "authors": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Authors are the list of gem authors (stored as array regardless of using `author` or `authors` method in gemspec)" }, "homepage": { - "type": "string" + "type": "string", + "description": "Homepage is project homepage URL" } }, "type": "object", "required": [ "name", "version" - ] + ], + "description": "RubyGemspec represents all metadata parsed from the *.gemspec file" }, "RustCargoAuditEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is crate name as specified in audit section of the build binary" }, "version": { - "type": "string" + "type": "string", + "description": "Version is crate version as specified in audit section of the build binary" }, "source": { - "type": "string" + "type": "string", + "description": "Source is the source registry or repository where this crate came from" } }, "type": "object", @@ -2917,27 +3731,33 @@ "name", "version", "source" - ] + ], + "description": "RustBinaryAuditEntry represents Rust crate metadata extracted from a compiled binary using cargo-auditable format." }, "RustCargoLockEntry": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is crate name as specified in Cargo.toml" }, "version": { - "type": "string" + "type": "string", + "description": "Version is crate version as specified in Cargo.toml" }, "source": { - "type": "string" + "type": "string", + "description": "Source is the source registry or repository URL in format \"registry+https://github.com/rust-lang/crates.io-index\" for registry packages" }, "checksum": { - "type": "string" + "type": "string", + "description": "Checksum is content checksum for registry packages only (hexadecimal string). Cargo doesn't require or include checksums for git dependencies. Used to detect MITM attacks by verifying downloaded crate matches lockfile checksum." }, "dependencies": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Dependencies are the list of dependencies with version constraints" } }, "type": "object", @@ -2947,7 +3767,8 @@ "source", "checksum", "dependencies" - ] + ], + "description": "RustCargoLockEntry represents a locked dependency from a Cargo.lock file with precise version and checksum information." }, "Schema": { "properties": { @@ -2964,6 +3785,39 @@ "url" ] }, + "SnapEntry": { + "properties": { + "snapType": { + "type": "string", + "description": "SnapType indicates the snap type (base, kernel, app, gadget, or snapd)." + }, + "base": { + "type": "string", + "description": "Base is the base snap name that this snap depends on (e.g., \"core20\", \"core22\")." + }, + "snapName": { + "type": "string", + "description": "SnapName is the snap package name." + }, + "snapVersion": { + "type": "string", + "description": "SnapVersion is the snap package version." + }, + "architecture": { + "type": "string", + "description": "Architecture is the target CPU architecture (e.g., \"amd64\", \"arm64\")." + } + }, + "type": "object", + "required": [ + "snapType", + "base", + "snapName", + "snapVersion", + "architecture" + ], + "description": "SnapEntry represents metadata for a Snap package extracted from snap.yaml or snapcraft.yaml files." + }, "Source": { "properties": { "id": { @@ -2975,6 +3829,9 @@ "version": { "type": "string" }, + "supplier": { + "type": "string" + }, "type": { "type": "string" }, @@ -2987,47 +3844,58 @@ "version", "type", "metadata" - ] + ], + "description": "Instead, the Supplier can be determined by the user of syft and passed as a config or flag to help fulfill the NTIA minimum elements." }, "SwiftPackageManagerLockEntry": { "properties": { "revision": { - "type": "string" + "type": "string", + "description": "Revision is git commit hash of the resolved package" } }, "type": "object", "required": [ "revision" - ] + ], + "description": "SwiftPackageManagerResolvedEntry represents a resolved dependency from a Package.resolved file with its locked version and source location." }, "SwiplpackPackage": { "properties": { "name": { - "type": "string" + "type": "string", + "description": "Name is the package name as found in the .toml file" }, "version": { - "type": "string" + "type": "string", + "description": "Version is the package version as found in the .toml file" }, "author": { - "type": "string" + "type": "string", + "description": "Author is author name" }, "authorEmail": { - "type": "string" + "type": "string", + "description": "AuthorEmail is author email address" }, "packager": { - "type": "string" + "type": "string", + "description": "Packager is packager name (if different from author)" }, "packagerEmail": { - "type": "string" + "type": "string", + "description": "PackagerEmail is packager email address" }, "homepage": { - "type": "string" + "type": "string", + "description": "Homepage is project homepage URL" }, "dependencies": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Dependencies are the list of required dependencies" } }, "type": "object", @@ -3040,24 +3908,29 @@ "packagerEmail", "homepage", "dependencies" - ] + ], + "description": "SwiplPackEntry represents a SWI-Prolog package from the pack system with metadata about the package and its dependencies." }, "TerraformLockProviderEntry": { "properties": { "url": { - "type": "string" + "type": "string", + "description": "URL is the provider source address (e.g., \"registry.terraform.io/hashicorp/aws\")." }, "constraints": { - "type": "string" + "type": "string", + "description": "Constraints specifies the version constraints for the provider (e.g., \"~\u003e 4.0\")." }, "version": { - "type": "string" + "type": "string", + "description": "Version is the locked provider version selected during terraform init." }, "hashes": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "Hashes are cryptographic checksums for the provider plugin archives across different platforms." } }, "type": "object", @@ -3066,24 +3939,29 @@ "constraints", "version", "hashes" - ] + ], + "description": "TerraformLockProviderEntry represents a single provider entry in a Terraform dependency lock file (.terraform.lock.hcl)." }, "WordpressPluginEntry": { "properties": { "pluginInstallDirectory": { - "type": "string" + "type": "string", + "description": "PluginInstallDirectory is directory name where the plugin is installed" }, "author": { - "type": "string" + "type": "string", + "description": "Author is plugin author name" }, "authorUri": { - "type": "string" + "type": "string", + "description": "AuthorURI is author's website URL" } }, "type": "object", "required": [ "pluginInstallDirectory" - ] + ], + "description": "WordpressPluginEntry represents all metadata parsed from the wordpress plugin file" }, "cpes": { "items": { diff --git a/syft/create_sbom_config.go b/syft/create_sbom_config.go index 4eb323f548a..f75113f17ea 100644 --- a/syft/create_sbom_config.go +++ b/syft/create_sbom_config.go @@ -191,6 +191,7 @@ func (c *CreateSBOMConfig) makeTaskGroups(src source.Description) ([][]task.Task scopeTasks := c.scopeTasks() relationshipsTasks := c.relationshipTasks(src) unknownTasks := c.unknownsTasks() + osFeatureDetectionTasks := c.osFeatureDetectionTasks() pkgTasks, fileTasks, selectionEvidence, err := c.selectTasks(src) if err != nil { @@ -220,6 +221,11 @@ func (c *CreateSBOMConfig) makeTaskGroups(src source.Description) ([][]task.Task taskGroups = append(taskGroups, unknownTasks) } + // osFeatureDetectionTasks should happen after package scanning is complete + if len(osFeatureDetectionTasks) > 0 { + taskGroups = append(taskGroups, osFeatureDetectionTasks) + } + // identifying the environment (i.e. the linux release) must be done first as this is required for package cataloging taskGroups = append( [][]task.Task{ @@ -444,6 +450,17 @@ func (c *CreateSBOMConfig) unknownsTasks() []task.Task { return tasks } +// osFeatureDetectionTasks returns a set of tasks that perform post-processing feature detection and update the SBOM accordingly +func (c *CreateSBOMConfig) osFeatureDetectionTasks() []task.Task { + var tasks []task.Task + + if t := task.NewOSFeatureDetectionTask(); t != nil { + tasks = append(tasks, t) + } + + return tasks +} + func (c *CreateSBOMConfig) validate() error { if c.Relationships.ExcludeBinaryPackagesWithFileOwnershipOverlap { if !c.Relationships.PackageFileOwnershipOverlap { diff --git a/syft/create_sbom_config_test.go b/syft/create_sbom_config_test.go index b4fbc61e4d1..0c12922f716 100644 --- a/syft/create_sbom_config_test.go +++ b/syft/create_sbom_config_test.go @@ -91,6 +91,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { fileCatalogerNames(), relationshipCatalogerNames(), unknownsTaskNames(), + osFeatureDetectionTaskNames(), }, wantManifest: &catalogerManifest{ Requested: cataloging.SelectionRequest{ @@ -110,6 +111,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { fileCatalogerNames(), relationshipCatalogerNames(), unknownsTaskNames(), + osFeatureDetectionTaskNames(), }, wantManifest: &catalogerManifest{ Requested: cataloging.SelectionRequest{ @@ -130,6 +132,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { fileCatalogerNames(), relationshipCatalogerNames(), unknownsTaskNames(), + osFeatureDetectionTaskNames(), }, wantManifest: &catalogerManifest{ Requested: cataloging.SelectionRequest{ @@ -149,6 +152,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { fileCatalogerNames("file-metadata", "content", "binary-metadata"), relationshipCatalogerNames(), unknownsTaskNames(), + osFeatureDetectionTaskNames(), }, wantManifest: &catalogerManifest{ Requested: cataloging.SelectionRequest{ @@ -169,6 +173,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { nil, // note: there is a file cataloging group, with no items in it relationshipCatalogerNames(), unknownsTaskNames(), + osFeatureDetectionTaskNames(), }, wantManifest: &catalogerManifest{ Requested: cataloging.SelectionRequest{ @@ -192,6 +197,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { ), relationshipCatalogerNames(), unknownsTaskNames(), + osFeatureDetectionTaskNames(), }, wantManifest: &catalogerManifest{ Requested: cataloging.SelectionRequest{ @@ -213,6 +219,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { fileCatalogerNames(), relationshipCatalogerNames(), unknownsTaskNames(), + osFeatureDetectionTaskNames(), }, wantManifest: &catalogerManifest{ Requested: cataloging.SelectionRequest{ @@ -234,6 +241,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { fileCatalogerNames(), relationshipCatalogerNames(), unknownsTaskNames(), + osFeatureDetectionTaskNames(), }, wantManifest: &catalogerManifest{ Requested: cataloging.SelectionRequest{ @@ -255,6 +263,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { fileCatalogerNames(), relationshipCatalogerNames(), unknownsTaskNames(), + osFeatureDetectionTaskNames(), }, wantManifest: &catalogerManifest{ Requested: cataloging.SelectionRequest{ @@ -277,6 +286,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { fileCatalogerNames(), relationshipCatalogerNames(), unknownsTaskNames(), + osFeatureDetectionTaskNames(), }, wantManifest: &catalogerManifest{ Requested: cataloging.SelectionRequest{ @@ -298,6 +308,7 @@ func TestCreateSBOMConfig_makeTaskGroups(t *testing.T) { fileCatalogerNames(), relationshipCatalogerNames(), unknownsTaskNames(), + osFeatureDetectionTaskNames(), }, wantManifest: &catalogerManifest{ Requested: cataloging.SelectionRequest{ @@ -430,6 +441,10 @@ func unknownsTaskNames() []string { return []string{"unknowns-labeler"} } +func osFeatureDetectionTaskNames() []string { + return []string{"os-feature-detection"} +} + func environmentCatalogerNames() []string { return []string{"environment-cataloger"} } diff --git a/syft/file/coordinate_set.go b/syft/file/coordinate_set.go index c5ea0be94a1..5342f6de215 100644 --- a/syft/file/coordinate_set.go +++ b/syft/file/coordinate_set.go @@ -7,6 +7,7 @@ import ( "github.com/scylladb/go-set/strset" ) +// CoordinateSet provides a unique collection of Coordinates with set operations. type CoordinateSet struct { set map[Coordinates]struct{} } diff --git a/syft/file/coordinates.go b/syft/file/coordinates.go index 0f76a71c1f8..afeda5b13b6 100644 --- a/syft/file/coordinates.go +++ b/syft/file/coordinates.go @@ -9,8 +9,11 @@ import ( // Coordinates contains the minimal information needed to describe how to find a file within any possible source object (e.g. image and directory sources) type Coordinates struct { - RealPath string `json:"path" cyclonedx:"path"` // The path where all path ancestors have no hardlinks / symlinks - FileSystemID string `json:"layerID,omitempty" cyclonedx:"layerID"` // An ID representing the filesystem. For container images, this is a layer digest. For directories or a root filesystem, this is blank. + // RealPath is the canonical absolute form of the path accessed (all symbolic links have been followed and relative path components like '.' and '..' have been removed). + RealPath string `json:"path" cyclonedx:"path"` + + // FileSystemID is an ID representing and entire filesystem. For container images, this is a layer digest. For directories or a root filesystem, this is blank. + FileSystemID string `json:"layerID,omitempty" cyclonedx:"layerID"` } func NewCoordinates(realPath, fsID string) Coordinates { diff --git a/syft/file/digest.go b/syft/file/digest.go index 87b53dbb833..93150443477 100644 --- a/syft/file/digest.go +++ b/syft/file/digest.go @@ -1,6 +1,10 @@ package file +// Digest represents a cryptographic hash of file contents. type Digest struct { + // Algorithm specifies the hash algorithm used (e.g., "sha256", "md5"). Algorithm string `json:"algorithm"` - Value string `json:"value"` + + // Value is the hexadecimal string representation of the hash. + Value string `json:"value"` } diff --git a/syft/file/executable.go b/syft/file/executable.go index dc0990b5d05..454b1bf9f39 100644 --- a/syft/file/executable.go +++ b/syft/file/executable.go @@ -1,40 +1,60 @@ package file type ( - ExecutableFormat string + // ExecutableFormat represents the binary executable format type. + ExecutableFormat string + + // RelocationReadOnly indicates the RELRO security protection level applied to an ELF binary. RelocationReadOnly string ) const ( - ELF ExecutableFormat = "elf" - MachO ExecutableFormat = "macho" - PE ExecutableFormat = "pe" + ELF ExecutableFormat = "elf" // Executable and Linkable Format used on Unix-like systems + MachO ExecutableFormat = "macho" // Mach object file format used on macOS and iOS + PE ExecutableFormat = "pe" // Portable Executable format used on Windows - RelocationReadOnlyNone RelocationReadOnly = "none" - RelocationReadOnlyPartial RelocationReadOnly = "partial" - RelocationReadOnlyFull RelocationReadOnly = "full" + RelocationReadOnlyNone RelocationReadOnly = "none" // no RELRO protection + RelocationReadOnlyPartial RelocationReadOnly = "partial" // partial RELRO protection + RelocationReadOnlyFull RelocationReadOnly = "full" // full RELRO protection ) +// Executable contains metadata about binary files and their security features. type Executable struct { // Format denotes either ELF, Mach-O, or PE Format ExecutableFormat `json:"format" yaml:"format" mapstructure:"format"` - HasExports bool `json:"hasExports" yaml:"hasExports" mapstructure:"hasExports"` - HasEntrypoint bool `json:"hasEntrypoint" yaml:"hasEntrypoint" mapstructure:"hasEntrypoint"` - ImportedLibraries []string `json:"importedLibraries" yaml:"importedLibraries" mapstructure:"importedLibraries"` + // HasExports indicates whether the binary exports symbols. + HasExports bool `json:"hasExports" yaml:"hasExports" mapstructure:"hasExports"` + + // HasEntrypoint indicates whether the binary has an entry point function. + HasEntrypoint bool `json:"hasEntrypoint" yaml:"hasEntrypoint" mapstructure:"hasEntrypoint"` + + // ImportedLibraries lists the shared libraries required by this executable. + ImportedLibraries []string `json:"importedLibraries" yaml:"importedLibraries" mapstructure:"importedLibraries"` + + // ELFSecurityFeatures contains ELF-specific security hardening information when Format is ELF. ELFSecurityFeatures *ELFSecurityFeatures `json:"elfSecurityFeatures,omitempty" yaml:"elfSecurityFeatures" mapstructure:"elfSecurityFeatures"` } +// ELFSecurityFeatures captures security hardening and protection mechanisms in ELF binaries. type ELFSecurityFeatures struct { + // SymbolTableStripped indicates whether debugging symbols have been removed. SymbolTableStripped bool `json:"symbolTableStripped" yaml:"symbolTableStripped" mapstructure:"symbolTableStripped"` - // classic protections + // StackCanary indicates whether stack smashing protection is enabled. + StackCanary *bool `json:"stackCanary,omitempty" yaml:"stackCanary" mapstructure:"stackCanary"` + + // NoExecutable indicates whether NX (no-execute) protection is enabled for the stack. + NoExecutable bool `json:"nx" yaml:"nx" mapstructure:"nx"` + + // RelocationReadOnly indicates the RELRO protection level. + RelocationReadOnly RelocationReadOnly `json:"relRO" yaml:"relRO" mapstructure:"relRO"` + + // PositionIndependentExecutable indicates whether the binary is compiled as PIE. + PositionIndependentExecutable bool `json:"pie" yaml:"pie" mapstructure:"pie"` - StackCanary *bool `json:"stackCanary,omitempty" yaml:"stackCanary" mapstructure:"stackCanary"` - NoExecutable bool `json:"nx" yaml:"nx" mapstructure:"nx"` - RelocationReadOnly RelocationReadOnly `json:"relRO" yaml:"relRO" mapstructure:"relRO"` - PositionIndependentExecutable bool `json:"pie" yaml:"pie" mapstructure:"pie"` - DynamicSharedObject bool `json:"dso" yaml:"dso" mapstructure:"dso"` + // DynamicSharedObject indicates whether the binary is a shared library. + DynamicSharedObject bool `json:"dso" yaml:"dso" mapstructure:"dso"` // LlvmSafeStack represents a compiler-based security mechanism that separates the stack into a safe stack for storing return addresses and other critical data, and an unsafe stack for everything else, to mitigate stack-based memory corruption errors // see https://clang.llvm.org/docs/SafeStack.html diff --git a/syft/file/license.go b/syft/file/license.go index ea0dc6e9ae3..43b4690d587 100644 --- a/syft/file/license.go +++ b/syft/file/license.go @@ -5,18 +5,33 @@ import ( "github.com/anchore/syft/syft/license" ) +// License represents license information discovered within a file. type License struct { - Value string - SPDXExpression string - Type license.Type - LicenseEvidence *LicenseEvidence // evidence from license classifier - Contents string `hash:"ignore"` + // Value is the raw license string as found in the file. + Value string + + // SPDXExpression is the parsed SPDX license expression if available. + SPDXExpression string + + // Type categorizes how the license was determined (e.g., declared, concluded -- following the same semantics as SPDX). + Type license.Type + + LicenseEvidence *LicenseEvidence + + // Contents optionally stores the full license text. + Contents string `hash:"ignore"` } +// LicenseEvidence contains details from license classifier analysis. type LicenseEvidence struct { + // Confidence is a score indicating certainty of the license match. Confidence int - Offset int - Extent int + + // Offset is the byte position where the license text begins in the file. + Offset int + + // Extent is the length in bytes of the matched license text. + Extent int } func NewLicense(value string) License { diff --git a/syft/file/location.go b/syft/file/location.go index a70fe5d7298..910ad5d1ecc 100644 --- a/syft/file/location.go +++ b/syft/file/location.go @@ -27,18 +27,24 @@ type Location struct { LocationMetadata `cyclonedx:""` } +// LocationData contains the core identifying information for a file location. type LocationData struct { Coordinates `cyclonedx:""` // Empty string here means there is no intermediate property name, e.g. syft:locations:0:path without "coordinates" // note: it is IMPORTANT to ignore anything but the coordinates for a Location when considering the ID (hash value) // since the coordinates are the minimally correct ID for a location (symlinks should not come into play) - AccessPath string `hash:"ignore" json:"accessPath"` // The path to the file which may or may not have hardlinks / symlinks - ref file.Reference `hash:"ignore"` // The file reference relative to the stereoscope.FileCatalog that has more information about this location. + + // AccessPath is the path used to retrieve file contents (which may or may not have hardlinks / symlinks in the path) + AccessPath string `hash:"ignore" json:"accessPath"` + + // ref is the stereoscope file reference relative to the stereoscope.FileCatalog that has more information about this location. + ref file.Reference `hash:"ignore"` } func (l LocationData) Reference() file.Reference { return l.ref } +// LocationMetadata provides additional contextual information about a file location. type LocationMetadata struct { Annotations map[string]string `json:"annotations,omitempty"` // Arbitrary key-value pairs that can be used to annotate a location } diff --git a/syft/file/location_read_closer.go b/syft/file/location_read_closer.go index 480a0b50fe1..2f1ac5e4995 100644 --- a/syft/file/location_read_closer.go +++ b/syft/file/location_read_closer.go @@ -2,6 +2,7 @@ package file import "io" +// LocationReadCloser combines a Location with a ReadCloser for accessing file content with location metadata. type LocationReadCloser struct { Location io.ReadCloser diff --git a/syft/file/location_set.go b/syft/file/location_set.go index 9ee3a236a40..52beb9e517d 100644 --- a/syft/file/location_set.go +++ b/syft/file/location_set.go @@ -9,6 +9,7 @@ import ( "github.com/anchore/syft/internal/log" ) +// LocationSet provides a unique collection of Locations with metadata and set operations. type LocationSet struct { set map[LocationData]LocationMetadata } diff --git a/syft/file/locations.go b/syft/file/locations.go index f7836b5ea56..3f7be072d6d 100644 --- a/syft/file/locations.go +++ b/syft/file/locations.go @@ -8,6 +8,7 @@ import ( var locationSorterWithoutLayers = LocationSorter(nil) +// Locations is a sortable slice of Location values. type Locations []Location func (l Locations) Len() int { diff --git a/syft/file/resolver.go b/syft/file/resolver.go index c3c94235166..ac4652fcf2a 100644 --- a/syft/file/resolver.go +++ b/syft/file/resolver.go @@ -18,6 +18,7 @@ type ContentResolver interface { FileContentsByLocation(Location) (io.ReadCloser, error) } +// MetadataResolver provides file metadata lookup by location. type MetadataResolver interface { FileMetadataByLocation(Location) (Metadata, error) } @@ -51,6 +52,7 @@ type PathResolver interface { RelativeFileByPath(_ Location, path string) *Location } +// LocationResolver provides iteration over all file locations in a source. type LocationResolver interface { // AllLocations returns a channel of all file references from the underlying source. // The implementation for this may vary, however, generally the following considerations should be made: @@ -59,6 +61,7 @@ type LocationResolver interface { AllLocations(ctx context.Context) <-chan Location } +// WritableResolver extends Resolver with the ability to write file content. type WritableResolver interface { Resolver diff --git a/syft/file/search_result.go b/syft/file/search_result.go index dc12d14df20..ff80a4368ce 100644 --- a/syft/file/search_result.go +++ b/syft/file/search_result.go @@ -4,13 +4,25 @@ import ( "fmt" ) +// SearchResult represents a match found during content scanning, such as secret detection. type SearchResult struct { + // Classification identifies the type or category of the matched content. Classification string `json:"classification"` - LineNumber int64 `json:"lineNumber"` - LineOffset int64 `json:"lineOffset"` - SeekPosition int64 `json:"seekPosition"` - Length int64 `json:"length"` - Value string `json:"value,omitempty"` + + // LineNumber is the 1-indexed line number where the match was found. + LineNumber int64 `json:"lineNumber"` + + // LineOffset is the character offset from the start of the line where the match begins. + LineOffset int64 `json:"lineOffset"` + + // SeekPosition is the absolute byte offset from the start of the file. + SeekPosition int64 `json:"seekPosition"` + + // Length is the size in bytes of the matched content. + Length int64 `json:"length"` + + // Value optionally contains the actual matched content. + Value string `json:"value,omitempty"` } func (s SearchResult) String() string { diff --git a/syft/file/selection.go b/syft/file/selection.go index fb7f46f9907..86e323d5257 100644 --- a/syft/file/selection.go +++ b/syft/file/selection.go @@ -1,9 +1,10 @@ package file const ( - NoFilesSelection Selection = "none" - FilesOwnedByPackageSelection Selection = "owned-by-package" - AllFilesSelection Selection = "all" + NoFilesSelection Selection = "none" // no files are selected + FilesOwnedByPackageSelection Selection = "owned-by-package" // only files owned by packages are selected + AllFilesSelection Selection = "all" // all files are selected ) +// Selection defines which files should be included during cataloging operations. type Selection string diff --git a/syft/format/common/cyclonedxhelpers/to_format_model.go b/syft/format/common/cyclonedxhelpers/to_format_model.go index 32986608f5e..7cae828c64b 100644 --- a/syft/format/common/cyclonedxhelpers/to_format_model.go +++ b/syft/format/common/cyclonedxhelpers/to_format_model.go @@ -48,7 +48,7 @@ func ToFormatModel(s sbom.SBOM) *cyclonedx.BOM { packages := s.Artifacts.Packages.Sorted() components := make([]cyclonedx.Component, len(packages)) for i, p := range packages { - components[i] = helpers.EncodeComponent(p, locationSorter) + components[i] = helpers.EncodeComponent(p, s.Source.Supplier, locationSorter) } components = append(components, toOSComponent(s.Artifacts.LinuxDistribution)...) @@ -220,11 +220,22 @@ func toBomDescriptor(name, version string, srcMetadata source.Description) *cycl }, }, }, + Supplier: toBomSupplier(srcMetadata), Properties: toBomProperties(srcMetadata), Component: toBomDescriptorComponent(srcMetadata), } } +func toBomSupplier(srcMetadata source.Description) *cyclonedx.OrganizationalEntity { + if srcMetadata.Supplier != "" { + return &cyclonedx.OrganizationalEntity{ + Name: srcMetadata.Supplier, + } + } + + return nil +} + // used to indicate that a relationship listed under the syft artifact package can be represented as a cyclonedx dependency. // NOTE: CycloneDX provides the ability to describe components and their dependency on other components. // The dependency graph is capable of representing both direct and transitive relationships. @@ -321,10 +332,11 @@ func toBomDescriptorComponent(srcMetadata source.Description) *cyclonedx.Compone log.Debugf("unable to get fingerprint of source image metadata=%s: %+v", metadata.ID, err) } return &cyclonedx.Component{ - BOMRef: string(bomRef), - Type: cyclonedx.ComponentTypeContainer, - Name: name, - Version: version, + BOMRef: string(bomRef), + Type: cyclonedx.ComponentTypeContainer, + Name: name, + Version: version, + Supplier: toBomSupplier(srcMetadata), } case source.DirectoryMetadata: if name == "" { @@ -337,9 +349,10 @@ func toBomDescriptorComponent(srcMetadata source.Description) *cyclonedx.Compone return &cyclonedx.Component{ BOMRef: string(bomRef), // TODO: this is lossy... we can't know if this is a file or a directory - Type: cyclonedx.ComponentTypeFile, - Name: name, - Version: version, + Type: cyclonedx.ComponentTypeFile, + Name: name, + Version: version, + Supplier: toBomSupplier(srcMetadata), } case source.FileMetadata: if name == "" { @@ -352,9 +365,10 @@ func toBomDescriptorComponent(srcMetadata source.Description) *cyclonedx.Compone return &cyclonedx.Component{ BOMRef: string(bomRef), // TODO: this is lossy... we can't know if this is a file or a directory - Type: cyclonedx.ComponentTypeFile, - Name: name, - Version: version, + Type: cyclonedx.ComponentTypeFile, + Name: name, + Version: version, + Supplier: toBomSupplier(srcMetadata), } } diff --git a/syft/format/common/cyclonedxhelpers/to_format_model_test.go b/syft/format/common/cyclonedxhelpers/to_format_model_test.go index 74f0ffbf3c0..5f94b9b5711 100644 --- a/syft/format/common/cyclonedxhelpers/to_format_model_test.go +++ b/syft/format/common/cyclonedxhelpers/to_format_model_test.go @@ -389,7 +389,69 @@ func Test_toBomDescriptor(t *testing.T) { Name: "syft:image:labels:key1", Value: "value1", }, - }}, + }, + }, + }, + { + name: "with optional supplier is on the root component and bom metadata", + args: args{ + name: "test-image", + version: "1.0.0", + srcMetadata: source.Description{ + Name: "test-image", + Version: "1.0.0", + Supplier: "optional-supplier", + Metadata: source.ImageMetadata{}, + }, + }, + want: &cyclonedx.Metadata{ + Timestamp: "", + Lifecycles: nil, + Tools: &cyclonedx.ToolsChoice{ + Components: &[]cyclonedx.Component{ + { + Type: cyclonedx.ComponentTypeApplication, + Author: "anchore", + Name: "test-image", + Version: "1.0.0", + }, + }, + }, + Authors: nil, + Component: &cyclonedx.Component{ + BOMRef: "", + MIMEType: "", + Type: "container", + Supplier: &cyclonedx.OrganizationalEntity{ + Name: "optional-supplier", + }, + Author: "", + Publisher: "", + Group: "", + Name: "test-image", + Version: "1.0.0", + Description: "", + Scope: "", + Hashes: nil, + Licenses: nil, + Copyright: "", + CPE: "", + PackageURL: "", + SWID: nil, + Modified: nil, + Pedigree: nil, + ExternalReferences: nil, + Properties: nil, + Components: nil, + Evidence: nil, + ReleaseNotes: nil, + }, + Manufacture: nil, + Supplier: &cyclonedx.OrganizationalEntity{ + Name: "optional-supplier", + }, + Licenses: nil, + }, }, } for _, tt := range tests { @@ -480,6 +542,10 @@ func Test_toOsComponent(t *testing.T) { Version: "myVersion", }, Properties: &[]cyclonedx.Property{ + { + Name: "syft:distro:extendedSupport", + Value: "false", + }, { Name: "syft:distro:id", Value: "myLinux", diff --git a/syft/format/common/spdxhelpers/to_format_model.go b/syft/format/common/spdxhelpers/to_format_model.go index 4e214edc179..c51fc087c7f 100644 --- a/syft/format/common/spdxhelpers/to_format_model.go +++ b/syft/format/common/spdxhelpers/to_format_model.go @@ -257,13 +257,11 @@ func toRootPackage(s source.Description) *spdx.Package { PackageChecksums: checksums, PackageExternalReferences: nil, PrimaryPackagePurpose: purpose, - PackageSupplier: &spdx.Supplier{ - Supplier: helpers.NOASSERTION, - }, - PackageCopyrightText: helpers.NOASSERTION, - PackageDownloadLocation: helpers.NOASSERTION, - PackageLicenseConcluded: helpers.NOASSERTION, - PackageLicenseDeclared: helpers.NOASSERTION, + PackageSupplier: toSPDXSupplier(s), + PackageCopyrightText: helpers.NOASSERTION, + PackageDownloadLocation: helpers.NOASSERTION, + PackageLicenseConcluded: helpers.NOASSERTION, + PackageLicenseDeclared: helpers.NOASSERTION, } if purl != nil { @@ -327,6 +325,23 @@ func toSPDXID(identifiable artifact.Identifiable) spdx.ElementID { return spdx.ElementID(helpers.SanitizeElementID(id)) } +func toSPDXSupplier(s source.Description) *spdx.Supplier { + supplier := helpers.NOASSERTION + if s.Supplier != "" { + supplier = s.Supplier + } + + supplierType := "" + if supplier != helpers.NOASSERTION { + supplierType = helpers.SUPPLIERORG + } + + return &spdx.Supplier{ + Supplier: supplier, + SupplierType: supplierType, + } +} + // packages populates all Package Information from the package Collection (see https://spdx.github.io/spdx-spec/3-package-information/) // //nolint:funlen @@ -391,7 +406,7 @@ func toPackages(rels *relationship.Index, catalog *pkg.Collection, sbom sbom.SBO // 7.6: Package Originator: may have single result for either Person or Organization, // or NOASSERTION // Cardinality: optional, one - PackageSupplier: toPackageSupplier(p), + PackageSupplier: toPackageSupplier(p, sbom.Source.Supplier), PackageOriginator: toPackageOriginator(p), @@ -556,11 +571,18 @@ func toPackageOriginator(p pkg.Package) *spdx.Originator { } } -func toPackageSupplier(p pkg.Package) *spdx.Supplier { +func toPackageSupplier(p pkg.Package, sbomSupplier string) *spdx.Supplier { kind, supplier := helpers.Supplier(p) if kind == "" || supplier == "" { + supplier := helpers.NOASSERTION + supplierType := "" + if sbomSupplier != "" { + supplier = sbomSupplier + supplierType = helpers.SUPPLIERORG + } return &spdx.Supplier{ - Supplier: helpers.NOASSERTION, + Supplier: supplier, + SupplierType: supplierType, } } return &spdx.Supplier{ diff --git a/syft/format/common/spdxhelpers/to_format_model_test.go b/syft/format/common/spdxhelpers/to_format_model_test.go index b6bf7fff709..ae4bc9e7bfd 100644 --- a/syft/format/common/spdxhelpers/to_format_model_test.go +++ b/syft/format/common/spdxhelpers/to_format_model_test.go @@ -7,6 +7,7 @@ import ( "strings" "testing" + "github.com/anchore/syft/internal/sourcemetadata" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/spdx/tools-golang/spdx" @@ -18,7 +19,6 @@ import ( "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/format/internal/spdxutil/helpers" - "github.com/anchore/syft/syft/internal/sourcemetadata" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/sbom" "github.com/anchore/syft/syft/source" @@ -36,8 +36,9 @@ func Test_toFormatModel(t *testing.T) { name: "container", in: sbom.SBOM{ Source: source.Description{ - Name: "alpine", - Version: "sha256:d34db33f", + Name: "alpine", + Version: "sha256:d34db33f", + Supplier: "Alpine Linux", Metadata: source.ImageMetadata{ UserInput: "alpine:latest", ManifestDigest: "sha256:d34db33f", @@ -61,7 +62,8 @@ func Test_toFormatModel(t *testing.T) { PackageName: "pkg-1", PackageVersion: "version-1", PackageSupplier: &spdx.Supplier{ - Supplier: "NOASSERTION", + Supplier: "Alpine Linux", + SupplierType: "Organization", }, }, { @@ -78,7 +80,8 @@ func Test_toFormatModel(t *testing.T) { }, }, PackageSupplier: &spdx.Supplier{ - Supplier: "NOASSERTION", + Supplier: "Alpine Linux", + SupplierType: "Organization", }, }, }, diff --git a/syft/format/common/spdxhelpers/to_syft_model.go b/syft/format/common/spdxhelpers/to_syft_model.go index 572e978d338..e1bf640a7af 100644 --- a/syft/format/common/spdxhelpers/to_syft_model.go +++ b/syft/format/common/spdxhelpers/to_syft_model.go @@ -145,10 +145,21 @@ func containerSource(p *spdx.Package) source.Description { c := p.PackageChecksums[0] digest = fmt.Sprintf("%s:%s", fromChecksumAlgorithm(c.Algorithm), c.Value) } + + supplier := "" + if p.PackageSupplier != nil { + // we also don't want NOASSERTION transferred to the syft format + // NOASSERTION == "" + if p.PackageSupplier.Supplier != helpers.NOASSERTION && p.PackageSupplier.SupplierType == helpers.SUPPLIERORG { + supplier = p.PackageSupplier.Supplier + } + } + return source.Description{ - ID: id, - Name: p.PackageName, - Version: p.PackageVersion, + ID: id, + Name: p.PackageName, + Version: p.PackageVersion, + Supplier: supplier, Metadata: source.ImageMetadata{ UserInput: container, ID: id, @@ -179,10 +190,16 @@ func fileSource(p *spdx.Package) source.Description { metadata, version = fileSourceMetadata(p) } + supplier := "" + if p.PackageSupplier.Supplier != helpers.NOASSERTION { + supplier = p.PackageSupplier.Supplier + } + return source.Description{ ID: string(p.PackageSPDXIdentifier), Name: p.PackageName, Version: version, + Supplier: supplier, Metadata: metadata, } } diff --git a/syft/format/common/spdxhelpers/to_syft_model_test.go b/syft/format/common/spdxhelpers/to_syft_model_test.go index dd09271d1df..e07bcca5bac 100644 --- a/syft/format/common/spdxhelpers/to_syft_model_test.go +++ b/syft/format/common/spdxhelpers/to_syft_model_test.go @@ -525,17 +525,19 @@ func Test_convertToAndFromFormat(t *testing.T) { UserInput: "some-image:some-tag", ManifestDigest: "sha256:ab8b83234bc28f28d8e", }, - Name: "some-image", - Version: "some-tag", + Name: "some-image", + Version: "some-tag", + Supplier: "some-supplier", }, packages: packages, relationships: relationships, }, { - name: ". directory source", + name: ". directory source with supplier", source: source.Description{ - ID: "DocumentRoot-Directory-.", - Name: ".", + ID: "DocumentRoot-Directory-.", + Name: ".", + Supplier: "some-supplier", Metadata: source.DirectoryMetadata{ Path: ".", }, @@ -544,7 +546,7 @@ func Test_convertToAndFromFormat(t *testing.T) { relationships: relationships, }, { - name: "directory source", + name: "directory source without supplier", source: source.Description{ ID: "DocumentRoot-Directory-my-app", Name: "my-app", diff --git a/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden b/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden index 8c376f1a660..7bdb196b982 100644 --- a/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden +++ b/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden @@ -102,6 +102,10 @@ "version": "1.2.3" }, "properties": [ + { + "name": "syft:distro:extendedSupport", + "value": "false" + }, { "name": "syft:distro:id", "value": "debian" diff --git a/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden b/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden index 93ee86aec12..fab1acd75cc 100644 --- a/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden +++ b/syft/format/cyclonedxjson/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden @@ -111,6 +111,10 @@ "version": "1.2.3" }, "properties": [ + { + "name": "syft:distro:extendedSupport", + "value": "false" + }, { "name": "syft:distro:id", "value": "debian" diff --git a/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden b/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden index c66aaec7a31..6d4345882a9 100644 --- a/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden +++ b/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxDirectoryEncoder.golden @@ -53,6 +53,7 @@ debian + false debian like! debian diff --git a/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden b/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden index bab78abd0d7..7680d294dae 100644 --- a/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden +++ b/syft/format/cyclonedxxml/test-fixtures/snapshot/TestCycloneDxImageEncoder.golden @@ -11,7 +11,7 @@ - + user-image-input sha256:redacted @@ -56,6 +56,7 @@ debian + false debian like! debian diff --git a/syft/format/github/internal/model/model_test.go b/syft/format/github/internal/model/model_test.go index 4d0c2dcce2f..de6f30a6dfb 100644 --- a/syft/format/github/internal/model/model_test.go +++ b/syft/format/github/internal/model/model_test.go @@ -3,13 +3,13 @@ package model import ( "testing" + "github.com/anchore/syft/internal/sourcemetadata" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/stretchr/testify/assert" "github.com/anchore/packageurl-go" "github.com/anchore/syft/syft/file" - "github.com/anchore/syft/syft/internal/sourcemetadata" "github.com/anchore/syft/syft/linux" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/sbom" diff --git a/syft/format/internal/cyclonedxutil/helpers/component.go b/syft/format/internal/cyclonedxutil/helpers/component.go index b4b686fb9b8..e0e9ab7745a 100644 --- a/syft/format/internal/cyclonedxutil/helpers/component.go +++ b/syft/format/internal/cyclonedxutil/helpers/component.go @@ -6,15 +6,15 @@ import ( "strings" "github.com/CycloneDX/cyclonedx-go" + "github.com/anchore/syft/internal/packagemetadata" "github.com/anchore/packageurl-go" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/format/internal" - "github.com/anchore/syft/syft/internal/packagemetadata" "github.com/anchore/syft/syft/pkg" ) -func EncodeComponent(p pkg.Package, locationSorter func(a, b file.Location) int) cyclonedx.Component { +func EncodeComponent(p pkg.Package, supplier string, locationSorter func(a, b file.Location) int) cyclonedx.Component { props := EncodeProperties(p, "syft:package") if p.Metadata != nil { @@ -49,6 +49,7 @@ func EncodeComponent(p pkg.Package, locationSorter func(a, b file.Location) int) Name: p.Name, Group: encodeGroup(p), Version: p.Version, + Supplier: encodeSupplier(p, supplier), PackageURL: p.PURL, Licenses: encodeLicenses(p), CPE: encodeSingleCPE(p), @@ -61,6 +62,16 @@ func EncodeComponent(p pkg.Package, locationSorter func(a, b file.Location) int) } } +// TODO: we eventually want to update this so that we can read "supplier" from different syft metadata +func encodeSupplier(_ pkg.Package, sbomSupplier string) *cyclonedx.OrganizationalEntity { + if sbomSupplier != "" { + return &cyclonedx.OrganizationalEntity{ + Name: sbomSupplier, + } + } + return nil +} + func DeriveBomRef(p pkg.Package) string { // try and parse the PURL if possible and append syft id to it, to make // the purl unique in the BOM. diff --git a/syft/format/internal/cyclonedxutil/helpers/component_test.go b/syft/format/internal/cyclonedxutil/helpers/component_test.go index 1ed91214066..474ff47ff87 100644 --- a/syft/format/internal/cyclonedxutil/helpers/component_test.go +++ b/syft/format/internal/cyclonedxutil/helpers/component_test.go @@ -152,7 +152,8 @@ func Test_encodeComponentProperties(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - c := EncodeComponent(test.input, file.LocationSorter(nil)) + sbomSupplier := "" + c := EncodeComponent(test.input, sbomSupplier, file.LocationSorter(nil)) if test.expected == nil { if c.Properties != nil { t.Fatalf("expected no properties, got: %+v", *c.Properties) @@ -212,7 +213,8 @@ func Test_encodeCompomentType(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.pkg.ID() - p := EncodeComponent(tt.pkg, file.LocationSorter(nil)) + sbomSupplier := "" + p := EncodeComponent(tt.pkg, sbomSupplier, file.LocationSorter(nil)) assert.Equal(t, tt.want, p) }) } diff --git a/syft/format/internal/cyclonedxutil/helpers/decoder.go b/syft/format/internal/cyclonedxutil/helpers/decoder.go index 83845e061ce..3dca5d5fc13 100644 --- a/syft/format/internal/cyclonedxutil/helpers/decoder.go +++ b/syft/format/internal/cyclonedxutil/helpers/decoder.go @@ -211,6 +211,16 @@ func extractComponents(meta *cyclonedx.Metadata) source.Description { } c := meta.Component + supplier := "" + // First check component-level supplier + if c.Supplier != nil && c.Supplier.Name != "" { + supplier = c.Supplier.Name + } + // Fall back to metadata-level supplier if component supplier is not set + if supplier == "" && meta.Supplier != nil && meta.Supplier.Name != "" { + supplier = meta.Supplier.Name + } + switch c.Type { case cyclonedx.ComponentTypeContainer: var labels map[string]string @@ -220,7 +230,8 @@ func extractComponents(meta *cyclonedx.Metadata) source.Description { } return source.Description{ - ID: "", + ID: "", + Supplier: supplier, // TODO: can we decode alias name-version somehow? (it isn't be encoded in the first place yet) Metadata: source.ImageMetadata{ @@ -236,6 +247,7 @@ func extractComponents(meta *cyclonedx.Metadata) source.Description { // TODO: this is lossy... we can't know if this is a file or a directory return source.Description{ ID: "", + Supplier: supplier, Metadata: source.FileMetadata{Path: c.Name}, } } diff --git a/syft/format/internal/cyclonedxutil/helpers/licenses.go b/syft/format/internal/cyclonedxutil/helpers/licenses.go index 37cbd53f093..3330c86a7f4 100644 --- a/syft/format/internal/cyclonedxutil/helpers/licenses.go +++ b/syft/format/internal/cyclonedxutil/helpers/licenses.go @@ -62,6 +62,9 @@ func decodeLicenses(c *cyclonedx.Component) []pkg.License { licenses = append(licenses, pkg.NewLicenseFromURLsWithContext(context.TODO(), l.License.ID, l.License.URL)) case l.License != nil && l.License.Name != "": licenses = append(licenses, pkg.NewLicenseFromURLsWithContext(context.TODO(), l.License.Name, l.License.URL)) + case l.License != nil && l.License.URL != "": + // Try to enrich license from URL when ID and Name are empty + licenses = append(licenses, pkg.NewLicenseFromURLsWithContext(context.TODO(), "", l.License.URL)) case l.Expression != "": licenses = append(licenses, pkg.NewLicenseWithContext(context.TODO(), l.Expression)) default: @@ -163,10 +166,18 @@ func processCustomLicense(l pkg.License) cyclonedx.Licenses { func processLicenseURLs(l pkg.License, spdxID string, populate *cyclonedx.Licenses) { for _, url := range l.URLs { if spdxID == "" { + // CycloneDX requires either an id or name to be present for a license + // If l.Value is empty, use the URL as the name to ensure schema compliance + // at this point we've already tried to enrich the license we just don't want the format + // conversion to be lossy here + name := l.Value + if name == "" { + name = url + } *populate = append(*populate, cyclonedx.LicenseChoice{ License: &cyclonedx.License{ URL: url, - Name: l.Value, + Name: name, }, }) } else { diff --git a/syft/format/internal/cyclonedxutil/helpers/licenses_test.go b/syft/format/internal/cyclonedxutil/helpers/licenses_test.go index d330f5d17d5..257e96acb47 100644 --- a/syft/format/internal/cyclonedxutil/helpers/licenses_test.go +++ b/syft/format/internal/cyclonedxutil/helpers/licenses_test.go @@ -121,6 +121,22 @@ func Test_encodeLicense(t *testing.T) { }, }, }, + { + name: "with URL only and no name or SPDX ID", + input: pkg.Package{ + Licenses: pkg.NewLicenseSet( + pkg.NewLicenseFromURLsWithContext(ctx, "", "http://jaxen.codehaus.org/license.html"), + ), + }, + expected: &cyclonedx.Licenses{ + { + License: &cyclonedx.License{ + Name: "http://jaxen.codehaus.org/license.html", + URL: "http://jaxen.codehaus.org/license.html", + }, + }, + }, + }, { name: "with multiple values licenses are deduplicated", input: pkg.Package{ diff --git a/syft/format/internal/spdxutil/helpers/document_name_test.go b/syft/format/internal/spdxutil/helpers/document_name_test.go index 1d73ecf383a..cd6f5b4f765 100644 --- a/syft/format/internal/spdxutil/helpers/document_name_test.go +++ b/syft/format/internal/spdxutil/helpers/document_name_test.go @@ -5,9 +5,9 @@ import ( "strings" "testing" + "github.com/anchore/syft/internal/sourcemetadata" "github.com/stretchr/testify/assert" - "github.com/anchore/syft/syft/internal/sourcemetadata" "github.com/anchore/syft/syft/source" ) diff --git a/syft/format/internal/spdxutil/helpers/document_namespace_test.go b/syft/format/internal/spdxutil/helpers/document_namespace_test.go index 3deeb807a33..c39723ae361 100644 --- a/syft/format/internal/spdxutil/helpers/document_namespace_test.go +++ b/syft/format/internal/spdxutil/helpers/document_namespace_test.go @@ -5,9 +5,9 @@ import ( "strings" "testing" + "github.com/anchore/syft/internal/sourcemetadata" "github.com/stretchr/testify/assert" - "github.com/anchore/syft/syft/internal/sourcemetadata" "github.com/anchore/syft/syft/sbom" "github.com/anchore/syft/syft/source" ) diff --git a/syft/format/internal/spdxutil/helpers/download_location.go b/syft/format/internal/spdxutil/helpers/download_location.go index f0576db3967..93fd6d69db1 100644 --- a/syft/format/internal/spdxutil/helpers/download_location.go +++ b/syft/format/internal/spdxutil/helpers/download_location.go @@ -10,6 +10,7 @@ import ( const NONE = "NONE" const NOASSERTION = "NOASSERTION" +const SUPPLIERORG = "Organization" func DownloadLocation(p pkg.Package) string { // 3.7: Package Download Location diff --git a/syft/format/internal/spdxutil/helpers/originator_supplier_test.go b/syft/format/internal/spdxutil/helpers/originator_supplier_test.go index 83f0bfd5932..b7ee3d6f76b 100644 --- a/syft/format/internal/spdxutil/helpers/originator_supplier_test.go +++ b/syft/format/internal/spdxutil/helpers/originator_supplier_test.go @@ -3,9 +3,9 @@ package helpers import ( "testing" + "github.com/anchore/syft/internal/packagemetadata" "github.com/stretchr/testify/assert" - "github.com/anchore/syft/syft/internal/packagemetadata" "github.com/anchore/syft/syft/pkg" ) @@ -18,6 +18,7 @@ func Test_OriginatorSupplier(t *testing.T) { pkg.ConanV2LockEntry{}, // the field Username might be the username of either the package originator or the supplier (unclear currently) pkg.ConanfileEntry{}, pkg.ConaninfoEntry{}, + pkg.CondaMetaPackage{}, pkg.DartPubspecLockEntry{}, pkg.DartPubspec{}, pkg.DotnetDepsEntry{}, @@ -27,6 +28,7 @@ func Test_OriginatorSupplier(t *testing.T) { pkg.ErlangRebarLockEntry{}, pkg.GolangBinaryBuildinfoEntry{}, pkg.GolangModuleEntry{}, + pkg.GolangSourceEntry{}, pkg.HomebrewFormula{}, pkg.HackageStackYamlLockEntry{}, pkg.HackageStackYamlEntry{}, @@ -42,8 +44,10 @@ func Test_OriginatorSupplier(t *testing.T) { pkg.PythonPipfileLockEntry{}, pkg.PythonRequirementsEntry{}, pkg.PythonPoetryLockEntry{}, + pkg.PythonUvLockEntry{}, pkg.RustBinaryAuditEntry{}, pkg.RustCargoLockEntry{}, + pkg.SnapEntry{}, pkg.SwiftPackageManagerResolvedEntry{}, pkg.SwiplPackEntry{}, pkg.OpamPackage{}, diff --git a/syft/format/internal/spdxutil/helpers/source_info.go b/syft/format/internal/spdxutil/helpers/source_info.go index 5232acbc3bb..5d36a600df4 100644 --- a/syft/format/internal/spdxutil/helpers/source_info.go +++ b/syft/format/internal/spdxutil/helpers/source_info.go @@ -48,6 +48,8 @@ func SourceInfo(p pkg.Package) string { answer = "acquired package info from installed cocoapods manifest file" case pkg.ConanPkg: answer = "acquired package info from conan manifest" + case pkg.CondaPkg: + answer = "acquired package info from conda metadata" case pkg.PortagePkg: answer = "acquired package info from portage DB" case pkg.HackagePkg: diff --git a/syft/format/internal/spdxutil/helpers/source_info_test.go b/syft/format/internal/spdxutil/helpers/source_info_test.go index 726ebcb61cd..2502dfe8c9a 100644 --- a/syft/format/internal/spdxutil/helpers/source_info_test.go +++ b/syft/format/internal/spdxutil/helpers/source_info_test.go @@ -191,6 +191,14 @@ func Test_SourceInfo(t *testing.T) { "from conan manifest", }, }, + { + input: pkg.Package{ + Type: pkg.CondaPkg, + }, + expected: []string{ + "from conda metadata", + }, + }, { input: pkg.Package{ Type: pkg.PortagePkg, diff --git a/syft/format/syftjson/model/linux_release.go b/syft/format/syftjson/model/linux_release.go index ec4780676a9..a544c250c1b 100644 --- a/syft/format/syftjson/model/linux_release.go +++ b/syft/format/syftjson/model/linux_release.go @@ -25,6 +25,7 @@ type LinuxRelease struct { PrivacyPolicyURL string `json:"privacyPolicyURL,omitempty"` CPEName string `json:"cpeName,omitempty"` SupportEnd string `json:"supportEnd,omitempty"` + ExtendedSupport bool `json:"extendedSupport,omitempty"` } func (s *IDLikes) UnmarshalJSON(data []byte) error { diff --git a/syft/format/syftjson/model/package.go b/syft/format/syftjson/model/package.go index 1f3d1833af9..420376e2940 100644 --- a/syft/format/syftjson/model/package.go +++ b/syft/format/syftjson/model/package.go @@ -8,8 +8,8 @@ import ( "strings" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/packagemetadata" "github.com/anchore/syft/syft/file" - "github.com/anchore/syft/syft/internal/packagemetadata" "github.com/anchore/syft/syft/license" "github.com/anchore/syft/syft/pkg" ) @@ -204,5 +204,6 @@ func unpackPkgMetadata(p *Package, unpacker packageMetadataUnpacker) error { } } p.Metadata = reflect.ValueOf(val).Elem().Interface() + p.MetadataType = ty return nil } diff --git a/syft/format/syftjson/model/source.go b/syft/format/syftjson/model/source.go index 46ae00f93ef..750e3195636 100644 --- a/syft/format/syftjson/model/source.go +++ b/syft/format/syftjson/model/source.go @@ -7,15 +7,21 @@ import ( "strconv" "strings" - "github.com/anchore/syft/syft/internal/sourcemetadata" + "github.com/anchore/syft/internal/sourcemetadata" "github.com/anchore/syft/syft/source" ) // Source object represents the thing that was cataloged +// Note: syft currently makes no claims or runs any logic to determine the Supplier field below + +// Instead, the Supplier can be determined by the user of syft and passed as a config or flag to help fulfill +// the NTIA minimum elements. For mor information see the NTIA framing document below +// https://www.ntia.gov/files/ntia/publications/framingsbom_20191112.pdf type Source struct { ID string `json:"id"` Name string `json:"name"` Version string `json:"version"` + Supplier string `json:"supplier,omitempty"` Type string `json:"type"` Metadata interface{} `json:"metadata"` } @@ -25,6 +31,7 @@ type sourceUnpacker struct { ID string `json:"id,omitempty"` Name string `json:"name"` Version string `json:"version"` + Supplier string `json:"supplier,omitempty"` Type string `json:"type"` Metadata json.RawMessage `json:"metadata"` Target json.RawMessage `json:"target"` // pre-v9 schema support @@ -40,6 +47,7 @@ func (s *Source) UnmarshalJSON(b []byte) error { s.Name = unpacker.Name s.Version = unpacker.Version + s.Supplier = unpacker.Supplier s.Type = unpacker.Type s.ID = unpacker.ID diff --git a/syft/format/syftjson/model/source_test.go b/syft/format/syftjson/model/source_test.go index bd2b7034fe2..ec45166a7ab 100644 --- a/syft/format/syftjson/model/source_test.go +++ b/syft/format/syftjson/model/source_test.go @@ -4,12 +4,12 @@ import ( "encoding/json" "testing" + "github.com/anchore/syft/internal/sourcemetadata" "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/anchore/syft/syft/file" - "github.com/anchore/syft/syft/internal/sourcemetadata" "github.com/anchore/syft/syft/source" ) diff --git a/syft/format/syftjson/schema_test.go b/syft/format/syftjson/schema_test.go index b38c98ce357..fafbc9c20ef 100644 --- a/syft/format/syftjson/schema_test.go +++ b/syft/format/syftjson/schema_test.go @@ -6,10 +6,9 @@ import ( "path/filepath" "testing" + "github.com/anchore/syft/internal/packagemetadata" "github.com/iancoleman/strcase" "github.com/stretchr/testify/require" - - "github.com/anchore/syft/syft/internal/packagemetadata" ) type schema struct { diff --git a/syft/format/syftjson/to_format_model.go b/syft/format/syftjson/to_format_model.go index 79a9a57e1df..fa205c5b6a1 100644 --- a/syft/format/syftjson/to_format_model.go +++ b/syft/format/syftjson/to_format_model.go @@ -8,12 +8,12 @@ import ( stereoscopeFile "github.com/anchore/stereoscope/pkg/file" "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/packagemetadata" + "github.com/anchore/syft/internal/sourcemetadata" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" formatInternal "github.com/anchore/syft/syft/format/internal" "github.com/anchore/syft/syft/format/syftjson/model" - "github.com/anchore/syft/syft/internal/packagemetadata" - "github.com/anchore/syft/syft/internal/sourcemetadata" "github.com/anchore/syft/syft/linux" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/sbom" @@ -41,7 +41,7 @@ func ToFormatModel(s sbom.SBOM, cfg EncoderConfig) model.Document { ArtifactRelationships: toRelationshipModel(s.Relationships), Files: toFile(s, coordinateSorter), Source: toSourceModel(s.Source), - Distro: toLinuxReleaser(s.Artifacts.LinuxDistribution), + Distro: toLinuxRelease(s.Artifacts.LinuxDistribution), Descriptor: toDescriptor(s.Descriptor), Schema: model.Schema{ Version: internal.JSONSchemaVersion, @@ -50,7 +50,7 @@ func ToFormatModel(s sbom.SBOM, cfg EncoderConfig) model.Document { } } -func toLinuxReleaser(d *linux.Release) model.LinuxRelease { +func toLinuxRelease(d *linux.Release) model.LinuxRelease { if d == nil { return model.LinuxRelease{} } @@ -73,6 +73,7 @@ func toLinuxReleaser(d *linux.Release) model.LinuxRelease { PrivacyPolicyURL: d.PrivacyPolicyURL, CPEName: d.CPEName, SupportEnd: d.SupportEnd, + ExtendedSupport: d.ExtendedSupport, } } @@ -319,6 +320,7 @@ func toSourceModel(src source.Description) model.Source { ID: src.ID, Name: src.Name, Version: src.Version, + Supplier: src.Supplier, Type: sourcemetadata.JSONName(src.Metadata), Metadata: src.Metadata, } diff --git a/syft/format/syftjson/to_format_model_test.go b/syft/format/syftjson/to_format_model_test.go index 9b40e36c688..83f8f526bbd 100644 --- a/syft/format/syftjson/to_format_model_test.go +++ b/syft/format/syftjson/to_format_model_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "testing" + "github.com/anchore/syft/internal/sourcemetadata" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/stretchr/testify/assert" @@ -12,7 +13,6 @@ import ( stereoscopeFile "github.com/anchore/stereoscope/pkg/file" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/format/syftjson/model" - "github.com/anchore/syft/syft/internal/sourcemetadata" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/source" ) @@ -56,19 +56,21 @@ func Test_toSourceModel(t *testing.T) { { name: "directory", src: source.Description{ - ID: "test-id", - Name: "some-name", - Version: "some-version", + ID: "test-id", + Name: "some-name", + Version: "some-version", + Supplier: "optional-supplier", Metadata: source.DirectoryMetadata{ Path: "some/path", Base: "some/base", }, }, expected: model.Source{ - ID: "test-id", - Name: "some-name", - Version: "some-version", - Type: "directory", + ID: "test-id", + Name: "some-name", + Version: "some-version", + Supplier: "optional-supplier", + Type: "directory", Metadata: source.DirectoryMetadata{ Path: "some/path", Base: "some/base", @@ -78,9 +80,10 @@ func Test_toSourceModel(t *testing.T) { { name: "file", src: source.Description{ - ID: "test-id", - Name: "some-name", - Version: "some-version", + ID: "test-id", + Name: "some-name", + Version: "some-version", + Supplier: "optional-supplier", Metadata: source.FileMetadata{ Path: "some/path", Digests: []file.Digest{{Algorithm: "sha256", Value: "some-digest"}}, @@ -88,10 +91,11 @@ func Test_toSourceModel(t *testing.T) { }, }, expected: model.Source{ - ID: "test-id", - Name: "some-name", - Version: "some-version", - Type: "file", + ID: "test-id", + Name: "some-name", + Version: "some-version", + Supplier: "optional-supplier", + Type: "file", Metadata: source.FileMetadata{ Path: "some/path", Digests: []file.Digest{{Algorithm: "sha256", Value: "some-digest"}}, diff --git a/syft/format/syftjson/to_syft_model.go b/syft/format/syftjson/to_syft_model.go index 143a639a66f..e7266b9340e 100644 --- a/syft/format/syftjson/to_syft_model.go +++ b/syft/format/syftjson/to_syft_model.go @@ -40,7 +40,7 @@ func toSyftModel(doc model.Document) *sbom.SBOM { FileLicenses: fileArtifacts.FileLicenses, Executables: fileArtifacts.Executables, Unknowns: fileArtifacts.Unknowns, - LinuxDistribution: toSyftLinuxRelease(doc.Distro), + LinuxDistribution: toInternalLinuxRelease(doc.Distro), }, Source: *toSyftSourceData(doc.Source), Descriptor: toSyftDescriptor(doc.Descriptor), @@ -195,7 +195,7 @@ func toSyftFileType(ty string) stereoscopeFile.Type { } } -func toSyftLinuxRelease(d model.LinuxRelease) *linux.Release { +func toInternalLinuxRelease(d model.LinuxRelease) *linux.Release { if cmp.Equal(d, model.LinuxRelease{}) { return nil } @@ -218,6 +218,7 @@ func toSyftLinuxRelease(d model.LinuxRelease) *linux.Release { PrivacyPolicyURL: d.PrivacyPolicyURL, CPEName: d.CPEName, SupportEnd: d.SupportEnd, + ExtendedSupport: d.ExtendedSupport, } } @@ -314,6 +315,7 @@ func toSyftSourceData(s model.Source) *source.Description { ID: s.ID, Name: s.Name, Version: s.Version, + Supplier: s.Supplier, Metadata: s.Metadata, } } diff --git a/syft/format/syftjson/to_syft_model_test.go b/syft/format/syftjson/to_syft_model_test.go index 3aed50c0db1..dfba66d5de7 100644 --- a/syft/format/syftjson/to_syft_model_test.go +++ b/syft/format/syftjson/to_syft_model_test.go @@ -7,6 +7,7 @@ import ( "os" "testing" + "github.com/anchore/syft/internal/sourcemetadata" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -14,7 +15,6 @@ import ( "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/format/syftjson/model" - "github.com/anchore/syft/syft/internal/sourcemetadata" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/sbom" "github.com/anchore/syft/syft/source" diff --git a/syft/get_source_test.go b/syft/get_source_test.go index dcef0edcc66..a5b17e89931 100644 --- a/syft/get_source_test.go +++ b/syft/get_source_test.go @@ -3,10 +3,10 @@ package syft import ( "testing" + "github.com/anchore/syft/internal/sourcemetadata" "github.com/stretchr/testify/require" "github.com/anchore/stereoscope/pkg/image" - "github.com/anchore/syft/syft/internal/sourcemetadata" "github.com/anchore/syft/syft/source" "github.com/anchore/syft/syft/source/sourceproviders" ) diff --git a/syft/internal/fileresolver/test-fixtures/symlinks-loop/README.md b/syft/internal/fileresolver/test-fixtures/symlinks-loop/README.md index 71967bddd96..8ea49d314f3 100644 --- a/syft/internal/fileresolver/test-fixtures/symlinks-loop/README.md +++ b/syft/internal/fileresolver/test-fixtures/symlinks-loop/README.md @@ -1 +1 @@ -this mimics a partial layout on a linux system within /sys/devices/virtual to help with ensuring globbing for files does not end up in a infinite loop +This mimics a partial layout on a Linux system within /sys/devices/virtual to help ensure globbing for files does not end up in an infinite loop. diff --git a/syft/internal/jsonschema/README.md b/syft/internal/jsonschema/README.md deleted file mode 100644 index dc7b76c91ff..00000000000 --- a/syft/internal/jsonschema/README.md +++ /dev/null @@ -1 +0,0 @@ -Please see [schema/json/README.md](../../../schema/json/README.md) for more information on the JSON schema files in this directory. \ No newline at end of file diff --git a/syft/license/license.go b/syft/license/license.go index c2b9d260295..9485ca7e5d5 100644 --- a/syft/license/license.go +++ b/syft/license/license.go @@ -4,6 +4,7 @@ package license import ( "fmt" "runtime/debug" + "strings" "github.com/github/go-spdx/v2/spdxexp" @@ -17,6 +18,18 @@ const ( Concluded Type = "concluded" ) +// trimFileSuffix removes common file extensions from the end of a string +func trimFileSuffix(s string) string { + suffixes := []string{".txt", ".pdf", ".html", ".htm", ".md", ".markdown", ".rst", ".doc", ".docx", ".rtf", ".tex", ".xml", ".json"} + lower := strings.ToLower(s) + for _, suffix := range suffixes { + if strings.HasSuffix(lower, suffix) { + return s[:len(s)-len(suffix)] + } + } + return s +} + func ParseExpression(expression string) (ex string, err error) { // https://github.com/anchore/syft/issues/1837 // The current spdx library can panic when parsing some expressions @@ -28,10 +41,26 @@ func ParseExpression(expression string) (ex string, err error) { } }() + // Try with the original expression first licenseID, exists := spdxlicense.ID(expression) if exists { return licenseID, nil } + + // Check if the expression is a URL and try to look it up + if info, found := spdxlicense.LicenseByURL(expression); found { + return info.ID, nil + } + + // Try with trimmed file suffix + trimmed := trimFileSuffix(expression) + if trimmed != expression { + // Try as a URL with the trimmed version + if info, found := spdxlicense.LicenseByURL(trimmed); found { + return info.ID, nil + } + } + // If it doesn't exist initially in the SPDX list it might be a more complex expression // ignored variable is any invalid expressions // TODO: contribute to spdxexp to expose deprecated license IDs diff --git a/syft/linux/release.go b/syft/linux/release.go index a17f32ad49a..0555acda661 100644 --- a/syft/linux/release.go +++ b/syft/linux/release.go @@ -20,6 +20,7 @@ type Release struct { PrivacyPolicyURL string CPEName string // A CPE name for the operating system, in URI binding syntax SupportEnd string // The date at which support for this version of the OS ends. + ExtendedSupport bool `cyclonedx:"extendedSupport"` // indicates there was some evidence of extended support found } func (r *Release) String() string { diff --git a/syft/pkg/alpm.go b/syft/pkg/alpm.go index 3a8cf8b16ad..e716c26c2cc 100644 --- a/syft/pkg/alpm.go +++ b/syft/pkg/alpm.go @@ -13,32 +13,74 @@ var _ FileOwner = (*AlpmDBEntry)(nil) const AlpmDBGlob = "**/var/lib/pacman/local/**/desc" -// AlpmDBEntry is a struct that represents the package data stored in the pacman fla-filet stores for arch linux. +// AlpmDBEntry is a struct that represents the package data stored in the pacman flat-file stores for arch linux. type AlpmDBEntry struct { - BasePackage string `mapstructure:"base" json:"basepackage" cyclonedx:"basepackage"` - Package string `mapstructure:"name" json:"package" cyclonedx:"package"` - Version string `mapstructure:"version" json:"version" cyclonedx:"version"` - Description string `mapstructure:"desc" json:"description" cyclonedx:"description"` - Architecture string `mapstructure:"arch" json:"architecture" cyclonedx:"architecture"` - Size int `mapstructure:"size" json:"size" cyclonedx:"size"` - Packager string `mapstructure:"packager" json:"packager"` - URL string `mapstructure:"url" json:"url"` - Validation string `mapstructure:"validation" json:"validation"` - Reason int `mapstructure:"reason" json:"reason"` - Files []AlpmFileRecord `mapstructure:"files" json:"files"` - Backup []AlpmFileRecord `mapstructure:"backup" json:"backup"` - Provides []string `mapstructure:"provides" json:"provides,omitempty"` - Depends []string `mapstructure:"depends" json:"depends,omitempty"` + // BasePackage is the base package name this package was built from (source package in Arch build system) + BasePackage string `mapstructure:"base" json:"basepackage" cyclonedx:"basepackage"` + + // Package is the package name as found in the desc file + Package string `mapstructure:"name" json:"package" cyclonedx:"package"` + + // Version is the package version as found in the desc file + Version string `mapstructure:"version" json:"version" cyclonedx:"version"` + + // Description is a human-readable package description + Description string `mapstructure:"desc" json:"description" cyclonedx:"description"` + + // Architecture is the target CPU architecture as defined in Arch architecture spec (e.g. x86_64, aarch64, or "any" for arch-independent packages) + Architecture string `mapstructure:"arch" json:"architecture" cyclonedx:"architecture"` + + // Size is the installed size in bytes + Size int `mapstructure:"size" json:"size" cyclonedx:"size"` + + // Packager is the name and email of the person who packaged this (RFC822 format) + Packager string `mapstructure:"packager" json:"packager"` + + // URL is the upstream project URL + URL string `mapstructure:"url" json:"url"` + + // Validation is the validation method used for package integrity (e.g. pgp signature, sha256 checksum) + Validation string `mapstructure:"validation" json:"validation"` + + // Reason is the installation reason tracked by pacman (0=explicitly installed by user, 1=installed as dependency) + Reason int `mapstructure:"reason" json:"reason"` + + // Files are the files installed by this package + Files []AlpmFileRecord `mapstructure:"files" json:"files"` + + // Backup is the list of configuration files that pacman backs up before upgrades + Backup []AlpmFileRecord `mapstructure:"backup" json:"backup"` + + // Provides are virtual packages provided by this package (allows other packages to depend on capabilities rather than specific packages) + Provides []string `mapstructure:"provides" json:"provides,omitempty"` + + // Depends are the runtime dependencies required by this package + Depends []string `mapstructure:"depends" json:"depends,omitempty"` } type AlpmFileRecord struct { - Path string `mapstruture:"path" json:"path,omitempty"` - Type string `mapstructure:"type" json:"type,omitempty"` - UID string `mapstructure:"uid" json:"uid,omitempty"` - GID string `mapstructure:"gid" json:"gid,omitempty"` - Time time.Time `mapstructure:"time" json:"time,omitempty"` - Size string `mapstructure:"size" json:"size,omitempty"` - Link string `mapstructure:"link" json:"link,omitempty"` + // Path is the file path relative to the filesystem root + Path string `mapstruture:"path" json:"path,omitempty"` + + // Type is the file type (e.g. regular file, directory, symlink) + Type string `mapstructure:"type" json:"type,omitempty"` + + // UID is the file owner user ID as recorded by pacman + UID string `mapstructure:"uid" json:"uid,omitempty"` + + // GID is the file owner group ID as recorded by pacman + GID string `mapstructure:"gid" json:"gid,omitempty"` + + // Time is the file modification timestamp + Time time.Time `mapstructure:"time" json:"time,omitempty"` + + // Size is the file size in bytes + Size string `mapstructure:"size" json:"size,omitempty"` + + // Link is the symlink target path if this is a symlink + Link string `mapstructure:"link" json:"link,omitempty"` + + // Digests contains file content hashes for integrity verification Digests []file.Digest `mapstructure:"digests" json:"digest,omitempty"` } diff --git a/syft/pkg/apk.go b/syft/pkg/apk.go index 8d2aea12c13..6fe2a923c05 100644 --- a/syft/pkg/apk.go +++ b/syft/pkg/apk.go @@ -23,22 +23,50 @@ var _ FileOwner = (*ApkDBEntry)(nil) // - https://git.alpinelinux.org/apk-tools/tree/src/package.c // - https://git.alpinelinux.org/apk-tools/tree/src/database.c type ApkDBEntry struct { - Package string `mapstructure:"P" json:"package"` - OriginPackage string `mapstructure:"o" json:"originPackage" cyclonedx:"originPackage"` - Maintainer string `mapstructure:"m" json:"maintainer"` - Version string `mapstructure:"V" json:"version"` - Architecture string `mapstructure:"A" json:"architecture"` - URL string `mapstructure:"U" json:"url"` - Description string `mapstructure:"T" json:"description"` - Size int `mapstructure:"S" json:"size" cyclonedx:"size"` - InstalledSize int `mapstructure:"I" json:"installedSize" cyclonedx:"installedSize"` - Dependencies []string `mapstructure:"D" json:"pullDependencies" cyclonedx:"pullDependencies"` - Provides []string `mapstructure:"p" json:"provides" cyclonedx:"provides"` - Checksum string `mapstructure:"C" json:"pullChecksum" cyclonedx:"pullChecksum"` - GitCommit string `mapstructure:"c" json:"gitCommitOfApkPort" cyclonedx:"gitCommitOfApkPort"` - Files []ApkFileRecord `json:"files"` + // Package is the package name as found in the installed file + Package string `mapstructure:"P" json:"package"` + + // OriginPackage is the original source package name this binary was built from (used to track which aport/source built this) + OriginPackage string `mapstructure:"o" json:"originPackage" cyclonedx:"originPackage"` + + // Maintainer is the package maintainer name and email + Maintainer string `mapstructure:"m" json:"maintainer"` + + // Version is the package version as found in the installed file + Version string `mapstructure:"V" json:"version"` + + // Architecture is the target CPU architecture + Architecture string `mapstructure:"A" json:"architecture"` + + // URL is the upstream project URL + URL string `mapstructure:"U" json:"url"` + + // Description is a human-readable package description + Description string `mapstructure:"T" json:"description"` + + // Size is the package archive size in bytes (.apk file size) + Size int `mapstructure:"S" json:"size" cyclonedx:"size"` + + // InstalledSize is the total size of installed files in bytes + InstalledSize int `mapstructure:"I" json:"installedSize" cyclonedx:"installedSize"` + + // Dependencies are the runtime dependencies required by this package + Dependencies []string `mapstructure:"D" json:"pullDependencies" cyclonedx:"pullDependencies"` + + // Provides are virtual packages provided by this package (for capability-based dependencies) + Provides []string `mapstructure:"p" json:"provides" cyclonedx:"provides"` + + // Checksum is the package content checksum for integrity verification + Checksum string `mapstructure:"C" json:"pullChecksum" cyclonedx:"pullChecksum"` + + // GitCommit is the git commit hash of the APK port definition in Alpine's aports repository + GitCommit string `mapstructure:"c" json:"gitCommitOfApkPort" cyclonedx:"gitCommitOfApkPort"` + + // Files are the files installed by this package + Files []ApkFileRecord `json:"files"` } +// spaceDelimitedStringSlice is an internal helper type for unmarshaling space-delimited strings from JSON into a string slice. type spaceDelimitedStringSlice []string func (m *ApkDBEntry) UnmarshalJSON(data []byte) error { @@ -95,11 +123,20 @@ func (a *spaceDelimitedStringSlice) UnmarshalJSON(data []byte) error { // ApkFileRecord represents a single file listing and metadata from a APK DB entry (which may have many of these file records). type ApkFileRecord struct { - Path string `json:"path"` - OwnerUID string `json:"ownerUid,omitempty"` - OwnerGID string `json:"ownerGid,omitempty"` - Permissions string `json:"permissions,omitempty"` - Digest *file.Digest `json:"digest,omitempty"` + // Path is the file path relative to the filesystem root + Path string `json:"path"` + + // OwnerUID is the file owner user ID + OwnerUID string `json:"ownerUid,omitempty"` + + // OwnerGID is the file owner group ID + OwnerGID string `json:"ownerGid,omitempty"` + + // Permissions is the file permission mode string (e.g. "0755", "0644") + Permissions string `json:"permissions,omitempty"` + + // Digest is the file content hash for integrity verification + Digest *file.Digest `json:"digest,omitempty"` } func (m ApkDBEntry) OwnedFiles() (result []string) { diff --git a/syft/pkg/binary.go b/syft/pkg/binary.go index bdfafe1ae08..b16c9a4b62a 100644 --- a/syft/pkg/binary.go +++ b/syft/pkg/binary.go @@ -13,9 +13,9 @@ type ClassifierMatch struct { Location file.Location `mapstructure:"Location" json:"location"` } -// ELFBinaryPackageNoteJSONPayload Represents metadata captured from the .note.package section of the binary +// ELFBinaryPackageNoteJSONPayload Represents metadata captured from the .note.package section of an ELF-formatted binary type ELFBinaryPackageNoteJSONPayload struct { - // these are well-known fields as defined by systemd ELF package metadata "spec" https://systemd.io/ELF_PACKAGE_METADATA/ + // (these are well-known fields as defined by systemd ELF package metadata "spec" https://systemd.io/ELF_PACKAGE_METADATA/) // Type is the type of the package (e.g. "rpm", "deb", "apk", etc.) Type string `json:"type,omitempty"` @@ -23,7 +23,7 @@ type ELFBinaryPackageNoteJSONPayload struct { // Architecture of the binary package (e.g. "amd64", "arm", etc.) Architecture string `json:"architecture,omitempty"` - // OS CPE is a CPE name for the OS, typically corresponding to CPE_NAME in os-release (e.g. cpe:/o:fedoraproject:fedora:33) + // OSCPE is a CPE name for the OS, typically corresponding to CPE_NAME in os-release (e.g. cpe:/o:fedoraproject:fedora:33) OSCPE string `json:"osCPE,omitempty"` // OS is the OS name, typically corresponding to ID in os-release (e.g. "fedora") @@ -32,7 +32,8 @@ type ELFBinaryPackageNoteJSONPayload struct { // osVersion is the version of the OS, typically corresponding to VERSION_ID in os-release (e.g. "33") OSVersion string `json:"osVersion,omitempty"` - // these are additional fields that are not part of the systemd spec + ///////////////////////////////////////////////////////////////////////////////// + // (these are additional fields that are not part of the systemd spec) // System is a context-specific name for the system that the binary package is intended to run on or a part of System string `json:"system,omitempty"` @@ -49,5 +50,6 @@ type ELFBinaryPackageNoteJSONPayload struct { // PEBinary represents metadata captured from a Portable Executable formatted binary (dll, exe, etc.) type PEBinary struct { + // VersionResources contains key-value pairs extracted from the PE file's version resource section (e.g., FileVersion, ProductName, CompanyName). VersionResources KeyValues } diff --git a/syft/pkg/bitnami.go b/syft/pkg/bitnami.go index 195a4ba50aa..e1517196fc1 100644 --- a/syft/pkg/bitnami.go +++ b/syft/pkg/bitnami.go @@ -3,13 +3,26 @@ package pkg // BitnamiSBOMEntry represents all captured data from Bitnami packages // described in Bitnami' SPDX files. type BitnamiSBOMEntry struct { - Name string `mapstructure:"name" json:"name"` - Architecture string `mapstructure:"arch" json:"arch"` - Distro string `mapstructure:"distro" json:"distro"` - Revision string `mapstructure:"revision" json:"revision"` - Version string `mapstructure:"version" json:"version"` - Path string `mapstructure:"path" json:"path"` - Files []string `mapstructure:"files" json:"files"` + // Name is the package name as found in the Bitnami SPDX file + Name string `mapstructure:"name" json:"name"` + + // Architecture is the target CPU architecture (amd64 or arm64 in Bitnami images) + Architecture string `mapstructure:"arch" json:"arch"` + + // Distro is the distribution name this package is for (base OS like debian, ubuntu, etc.) + Distro string `mapstructure:"distro" json:"distro"` + + // Revision is the Bitnami-specific package revision number (incremented for Bitnami rebuilds of same upstream version) + Revision string `mapstructure:"revision" json:"revision"` + + // Version is the package version as found in the Bitnami SPDX file + Version string `mapstructure:"version" json:"version"` + + // Path is the installation path in the filesystem where the package is located + Path string `mapstructure:"path" json:"path"` + + // Files are the file paths owned by this package (tracked via SPDX relationships) + Files []string `mapstructure:"files" json:"files"` } func (b BitnamiSBOMEntry) OwnedFiles() (result []string) { diff --git a/syft/pkg/cataloger/binary/classifier_cataloger.go b/syft/pkg/cataloger/binary/classifier_cataloger.go index c39b3c6bb49..4587a338c7a 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger.go @@ -75,6 +75,12 @@ func (c cataloger) Catalog(_ context.Context, resolver file.Resolver) ([]pkg.Pac newPackages: for i := range newPkgs { newPkg := &newPkgs[i] + purlType := pkg.TypeFromPURL(newPkg.PURL) + // for certain results, such as hashicorp vault we are returning a golang PURL, so we can use Golang package type, + // despite not having the known metadata, this should result in downstream grype matching to use the golang matcher + if purlType != pkg.UnknownPkg { + newPkg.Type = purlType + } for j := range packages { p := &packages[j] // consolidate identical packages found in different locations or by different classifiers @@ -92,6 +98,9 @@ func (c cataloger) Catalog(_ context.Context, resolver file.Resolver) ([]pkg.Pac // mergePackages merges information from the extra package into the target package func mergePackages(target *pkg.Package, extra *pkg.Package) { + if extra.Type != pkg.BinaryPkg && target.Type == pkg.BinaryPkg { + target.Type = extra.Type + } // add the locations target.Locations.Add(extra.Locations.ToSlice()...) // update the metadata to indicate which classifiers were used diff --git a/syft/pkg/cataloger/binary/classifier_cataloger_test.go b/syft/pkg/cataloger/binary/classifier_cataloger_test.go index 79b2c295c42..055672b2551 100644 --- a/syft/pkg/cataloger/binary/classifier_cataloger_test.go +++ b/syft/pkg/cataloger/binary/classifier_cataloger_test.go @@ -697,21 +697,21 @@ func Test_Cataloger_PositiveCases(t *testing.T) { { logicalFixture: "java-jre-openjdk/1.8.0_352-b08/linux-amd64", expected: pkg.Package{ - Name: "java/jre", + Name: "openjdk", Version: "1.8.0_352-b08", Type: "binary", - PURL: "pkg:generic/java/jre@1.8.0_352-b08", + PURL: "pkg:generic/oracle/openjdk@1.8.0_352-b08", Locations: locations("java"), - Metadata: metadata("java-binary-openjdk", "java"), + Metadata: metadata("java-binary-openjdk-with-update", "java"), }, }, { logicalFixture: "java-jre-openjdk/11.0.17/linux-amd64", expected: pkg.Package{ - Name: "java/jre", + Name: "openjdk", Version: "11.0.17+8-LTS", Type: "binary", - PURL: "pkg:generic/java/jre@11.0.17%2B8-LTS", + PURL: "pkg:generic/oracle/openjdk@11.0.17%2B8-LTS", Locations: locations("java"), Metadata: metadata("java-binary-openjdk", "java"), }, @@ -719,10 +719,10 @@ func Test_Cataloger_PositiveCases(t *testing.T) { { logicalFixture: "java-jre-openjdk-eclipse/11.0.22/linux-amd64", expected: pkg.Package{ - Name: "java/jre", + Name: "openjdk", Version: "11.0.22+7", Type: "binary", - PURL: "pkg:generic/java/jre@11.0.22%2B7", + PURL: "pkg:generic/oracle/openjdk@11.0.22%2B7", Locations: locations("java"), Metadata: metadata("java-binary-openjdk", "java"), }, @@ -730,10 +730,10 @@ func Test_Cataloger_PositiveCases(t *testing.T) { { logicalFixture: "java-jre-openjdk-arm64-eclipse/11.0.22/linux-arm64", expected: pkg.Package{ - Name: "java/jre", + Name: "openjdk", Version: "11.0.22+7", Type: "binary", - PURL: "pkg:generic/java/jre@11.0.22%2B7", + PURL: "pkg:generic/oracle/openjdk@11.0.22%2B7", Locations: locations("java"), Metadata: metadata("java-binary-openjdk", "java"), }, @@ -741,10 +741,10 @@ func Test_Cataloger_PositiveCases(t *testing.T) { { logicalFixture: "java-graal-openjdk/17.0.3+7-jvmci-22.1-b06/linux-amd64", expected: pkg.Package{ - Name: "java/graalvm", + Name: "graalvm", Version: "17.0.3+7-jvmci-22.1-b06", Type: "binary", - PURL: "pkg:generic/java/graalvm@17.0.3%2B7-jvmci-22.1-b06", + PURL: "pkg:generic/oracle/graalvm@17.0.3%2B7-jvmci-22.1-b06", Locations: locations("java"), Metadata: metadata("java-binary-graalvm", "java"), }, @@ -754,10 +754,10 @@ func Test_Cataloger_PositiveCases(t *testing.T) { // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo logicalFixture: "java-jre-oracle/19.0.1/linux-amd64", expected: pkg.Package{ - Name: "java/jre", + Name: "jre", Version: "19.0.1+10-21", Type: "binary", - PURL: "pkg:generic/java/jre@19.0.1%2B10-21", + PURL: "pkg:generic/oracle/jre@19.0.1%2B10-21", Locations: locations("java"), Metadata: metadata("java-binary-oracle", "java"), }, @@ -767,34 +767,23 @@ func Test_Cataloger_PositiveCases(t *testing.T) { // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo logicalFixture: "java-jre-oracle/19.0.1/darwin", expected: pkg.Package{ - Name: "java/jre", + Name: "jre", Version: "19.0.1+10-21", Type: "binary", - PURL: "pkg:generic/java/jre@19.0.1%2B10-21", + PURL: "pkg:generic/oracle/jre@19.0.1%2B10-21", Locations: locations("java"), Metadata: metadata("java-binary-oracle", "java"), }, }, - { - logicalFixture: "java-jre-ibm/1.8.0_391/linux-amd64", - expected: pkg.Package{ - Name: "java/jre", - Version: "1.8.0-foreman_2023_10_12_13_27-b00", - Type: "binary", - PURL: "pkg:generic/java/jre@1.8.0-foreman_2023_10_12_13_27-b00", - Locations: locations("java"), - Metadata: metadata("java-binary-ibm", "java"), - }, - }, { logicalFixture: "java-jdk-openjdk/21.0.2+13-LTS/linux-amd64", expected: pkg.Package{ - Name: "java/jdk", + Name: "openjdk", Version: "21.0.2+13-LTS", Type: "binary", - PURL: "pkg:generic/java/jdk@21.0.2%2B13-LTS", + PURL: "pkg:generic/oracle/openjdk@21.0.2%2B13-LTS", Locations: locations("jdb"), - Metadata: metadata("java-binary-jdk", "java"), + Metadata: metadata("java-binary-openjdk-fallthrough", "jdb"), }, }, { @@ -985,6 +974,28 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("consul-binary"), }, }, + { + logicalFixture: "vault/1.20.2/linux-amd64", + expected: pkg.Package{ + Name: "github.com/hashicorp/vault", + Version: "1.20.2", + Type: "golang", + PURL: "pkg:golang/github.com/hashicorp/vault@1.20.2", + Locations: locations("vault"), + Metadata: metadata("hashicorp-vault-binary"), + }, + }, + { + logicalFixture: "vault/1.19.4/linux-arm64", + expected: pkg.Package{ + Name: "github.com/hashicorp/vault", + Version: "1.19.4", + Type: "golang", + PURL: "pkg:golang/github.com/hashicorp/vault@1.19.4", + Locations: locations("vault"), + Metadata: metadata("hashicorp-vault-binary"), + }, + }, { logicalFixture: "erlang/25.3.2.6/linux-amd64", expected: pkg.Package{ @@ -1172,6 +1183,17 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("openssl-binary"), }, }, + { + logicalFixture: "openssl/1.1.1zb/linux-arm64", + expected: pkg.Package{ + Name: "openssl", + Version: "1.1.1zb", + Type: "binary", + PURL: "pkg:generic/openssl@1.1.1zb", + Locations: locations("openssl"), + Metadata: metadata("openssl-binary"), + }, + }, { logicalFixture: "gcc/12.3.0/linux-amd64", expected: pkg.Package{ @@ -1348,6 +1370,39 @@ func Test_Cataloger_PositiveCases(t *testing.T) { Metadata: metadata("chrome-binary"), }, }, + { + logicalFixture: "ffmpeg/7.1.1/darwin-arm64", + expected: pkg.Package{ + Name: "ffmpeg", + Version: "7.1.1", + Type: "binary", + PURL: "pkg:generic/ffmpeg@7.1.1", + Locations: locations("ffmpeg"), + Metadata: metadata("ffmpeg-binary"), + }, + }, + { + logicalFixture: "ffmpeg/6.1.1/linux-amd64", + expected: pkg.Package{ + Name: "ffmpeg", + Version: "6.1.1", + Type: "binary", + PURL: "pkg:generic/ffmpeg@6.1.1", + Locations: locations("ffmpeg"), + Metadata: metadata("ffmpeg-binary"), + }, + }, + { + logicalFixture: "ffmpeg-shared-libs/5.1.4/linux-amd64", + expected: pkg.Package{ + Name: "ffmpeg", + Version: "5.1.4", + Type: "binary", + PURL: "pkg:generic/ffmpeg@5.1.4", + Locations: locations("libavcodec-9aae324f.so.59.37.100"), + Metadata: metadata("ffmpeg-library"), + }, + }, } for _, test := range tests { @@ -1463,8 +1518,8 @@ func Test_Cataloger_CustomClassifiers(t *testing.T) { Class: "foo-binary", FileGlob: "**/foo", EvidenceMatcher: binutils.FileContentsVersionMatcher( - `(?m)foobar\s(?P[0-9]+\.[0-9]+\.[0-9]+)`, catalogerName, + `(?m)foobar\s(?P[0-9]+\.[0-9]+\.[0-9]+)`, ), Package: "foo", PURL: mustPURL("pkg:generic/foo@version"), @@ -1521,7 +1576,7 @@ func Test_Cataloger_CustomClassifiers(t *testing.T) { binutils.Classifier{ Class: "foo-binary", FileGlob: "**/foo", - EvidenceMatcher: binutils.FileContentsVersionMatcher(`(?m)not there`, catalogerName), + EvidenceMatcher: binutils.FileContentsVersionMatcher(catalogerName, `(?m)not there`), Package: "foo", PURL: mustPURL("pkg:generic/foo@version"), CPEs: singleCPE("cpe:2.3:a:foo:foo:*:*:*:*:*:*:*:*"), @@ -1739,7 +1794,7 @@ func TestCatalogerConfig_MarshalJSON(t *testing.T) { { Class: "class", FileGlob: "glob", - EvidenceMatcher: binutils.FileContentsVersionMatcher(".thing", catalogerName), + EvidenceMatcher: binutils.FileContentsVersionMatcher(catalogerName, ".thing"), Package: "pkg", PURL: packageurl.PackageURL{ Type: "type", diff --git a/syft/pkg/cataloger/binary/classifiers.go b/syft/pkg/cataloger/binary/classifiers.go index 90b403e6c28..a58091c6b13 100644 --- a/syft/pkg/cataloger/binary/classifiers.go +++ b/syft/pkg/cataloger/binary/classifiers.go @@ -28,11 +28,11 @@ func DefaultClassifiers() []binutils.Classifier { // ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5) [x86_64-linux] `(?m)ruby (?P[0-9]+\.[0-9]+\.[0-9]+((p|preview|rc|dev)[0-9]*)?) `) - return []binutils.Classifier{ + classifiers := []binutils.Classifier{ { Class: "python-binary", FileGlob: "**/python*", - EvidenceMatcher: binutils.EvidenceMatchers( + EvidenceMatcher: binutils.MatchAny( // try to find version information from libpython shared libraries binutils.SharedLibraryLookup( `^libpython[0-9]+(?:\.[0-9]+)+[a-z]?\.so.*$`, @@ -98,7 +98,7 @@ func DefaultClassifiers() []binutils.Classifier { { Class: "redis-binary", FileGlob: "**/redis-server", - EvidenceMatcher: binutils.EvidenceMatchers( + EvidenceMatcher: binutils.MatchAny( // matches most recent versions of redis (~v7), e.g. "7.0.14buildkitsandbox-1702957741000000000" m.FileContentsVersionMatcher(`[^\d](?P\d+.\d+\.\d+)buildkitsandbox-\d+`), // matches against older versions of redis (~v3 - v6), e.g. "4.0.11841ce7054bd9-1542359302000000000" @@ -113,73 +113,10 @@ func DefaultClassifiers() []binutils.Classifier { cpe.Must("cpe:2.3:a:redis:redis:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, }, - { - Class: "java-binary-openjdk", - FileGlob: "**/java", - EvidenceMatcher: binutils.MatchExcluding( - binutils.EvidenceMatchers( - m.FileContentsVersionMatcher( - // [NUL]openjdk[NUL]java[NUL]0.0[NUL]11.0.17+8-LTS[NUL] - // [NUL]openjdk[NUL]java[NUL]1.8[NUL]1.8.0_352-b08[NUL] - `(?m)\x00openjdk\x00java\x00(?P[0-9]+[.0-9]*)\x00(?P[0-9]+[^\x00]+)\x00`), - m.FileContentsVersionMatcher( - // arm64 versions: [NUL]0.0[NUL][NUL][NUL][NUL][NUL]11.0.22+7[NUL][NUL][NUL][NUL][NUL][NUL][NUL]openjdk[NUL]java[NUL] - `(?m)\x00(?P[0-9]+[.0-9]*)\x00+(?P[0-9]+[^\x00]+)\x00+openjdk\x00java`), - ), - // don't match graalvm - "-jvmci-", - ), - Package: "java/jre", - PURL: mustPURL("pkg:generic/java/jre@version"), - // TODO the updates might need to be part of the CPE Attributes, like: 1.8.0:update152 - CPEs: singleCPE("cpe:2.3:a:oracle:openjdk:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), - }, - { - Class: "java-binary-ibm", - FileGlob: "**/java", - EvidenceMatcher: m.FileContentsVersionMatcher( - // [NUL]java[NUL]1.8[NUL][NUL][NUL][NUL]1.8.0-foreman_2022_09_22_15_30-b00[NUL] - `(?m)\x00java\x00(?P[0-9]+[.0-9]+)\x00{4}(?P[0-9]+[-._a-zA-Z0-9]+)\x00`), - Package: "java/jre", - PURL: mustPURL("pkg:generic/java/jre@version"), - CPEs: singleCPE("cpe:2.3:a:ibm:java:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), - }, - { - Class: "java-binary-oracle", - FileGlob: "**/java", - EvidenceMatcher: binutils.MatchExcluding( - m.FileContentsVersionMatcher( - // [NUL]19.0.1+10-21[NUL] - `(?m)\x00(?P[0-9]+[.0-9]+[+][-0-9]+)\x00`), - // don't match openjdk - `\x00openjdk\x00`, - ), - Package: "java/jre", - PURL: mustPURL("pkg:generic/java/jre@version"), - CPEs: singleCPE("cpe:2.3:a:oracle:jre:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), - }, - { - Class: "java-binary-graalvm", - FileGlob: "**/java", - EvidenceMatcher: m.FileContentsVersionMatcher( - `(?m)\x00(?P[0-9]+[.0-9]+[.0-9]+\+[0-9]+-jvmci-[0-9]+[.0-9]+-b[0-9]+)\x00`), - Package: "java/graalvm", - PURL: mustPURL("pkg:generic/java/graalvm@version"), - CPEs: singleCPE("cpe:2.3:a:oracle:graalvm:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), - }, - { - Class: "java-binary-jdk", - FileGlob: "**/jdb", - EvidenceMatcher: m.FileContentsVersionMatcher( - `(?m)\x00(?P[0-9]+\.[0-9]+\.[0-9]+(\+[0-9]+)?([-._a-zA-Z0-9]+)?)\x00`), - Package: "java/jdk", - PURL: mustPURL("pkg:generic/java/jdk@version"), - CPEs: singleCPE("cpe:2.3:a:oracle:jdk:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), - }, { Class: "nodejs-binary", FileGlob: "**/node", - EvidenceMatcher: binutils.EvidenceMatchers( + EvidenceMatcher: binutils.MatchAny( // [NUL]node v0.10.48[NUL] // [NUL]v0.12.18[NUL] // [NUL]v4.9.1[NUL] @@ -221,7 +158,7 @@ func DefaultClassifiers() []binutils.Classifier { { Class: "haproxy-binary", FileGlob: "**/haproxy", - EvidenceMatcher: binutils.EvidenceMatchers( + EvidenceMatcher: binutils.MatchAny( m.FileContentsVersionMatcher(`(?m)version (?P[0-9]+\.[0-9]+(\.|-dev|-rc)[0-9]+)(-[a-z0-9]{7})?, released 20`), m.FileContentsVersionMatcher(`(?m)HA-Proxy version (?P[0-9]+\.[0-9]+(\.|-dev)[0-9]+)`), m.FileContentsVersionMatcher(`(?m)(?P[0-9]+\.[0-9]+(\.|-dev)[0-9]+)-[0-9a-zA-Z]{7}.+HAProxy version`), @@ -303,7 +240,7 @@ func DefaultClassifiers() []binutils.Classifier { { Class: "mysql-binary", FileGlob: "**/mysql", - EvidenceMatcher: binutils.EvidenceMatchers( + EvidenceMatcher: binutils.MatchAny( // shutdown[NUL]8.0.37[NUL][NUL][NUL][NUL][NUL]mysql_real_esc m.FileContentsVersionMatcher(`\x00(?P[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)\x00+mysql`), // /export/home/pb2/build/sb_0-26781090-1516292385.58/release/mysql-8.0.4-rc/mysys_ssl/my_default.cc @@ -380,7 +317,7 @@ func DefaultClassifiers() []binutils.Classifier { { Class: "ruby-binary", FileGlob: "**/ruby", - EvidenceMatcher: binutils.EvidenceMatchers( + EvidenceMatcher: binutils.MatchAny( rubyMatcher, binutils.SharedLibraryLookup( // try to find version information from libruby shared libraries @@ -394,7 +331,7 @@ func DefaultClassifiers() []binutils.Classifier { { Class: "erlang-binary", FileGlob: "**/erlexec", - EvidenceMatcher: binutils.EvidenceMatchers( + EvidenceMatcher: binutils.MatchAny( m.FileContentsVersionMatcher( // [NUL]/usr/src/otp_src_25.3.2.6/erts/ `(?m)/src/otp_src_(?P[0-9]+\.[0-9]+(\.[0-9]+){0,2}(-rc[0-9])?)/erts/`, @@ -411,7 +348,7 @@ func DefaultClassifiers() []binutils.Classifier { { Class: "erlang-alpine-binary", FileGlob: "**/beam.smp", - EvidenceMatcher: binutils.EvidenceMatchers( + EvidenceMatcher: binutils.MatchAny( m.FileContentsVersionMatcher( // [NUL]/usr/src/otp_src_25.3.2.6/erts/ `(?m)/src/otp_src_(?P[0-9]+\.[0-9]+(\.[0-9]+){0,2}(-rc[0-9])?)/erts/`, @@ -432,7 +369,7 @@ func DefaultClassifiers() []binutils.Classifier { { Class: "erlang-library", FileGlob: "**/liberts_internal.a", - EvidenceMatcher: binutils.EvidenceMatchers( + EvidenceMatcher: binutils.MatchAny( m.FileContentsVersionMatcher( // [NUL]/usr/src/otp_src_25.3.2.6/erts/ `(?m)/src/otp_src_(?P[0-9]+\.[0-9]+(\.[0-9]+){0,2}(-rc[0-9])?)/erts/`, @@ -511,6 +448,16 @@ func DefaultClassifiers() []binutils.Classifier { PURL: mustPURL("pkg:golang/github.com/hashicorp/consul@version"), CPEs: singleCPE("cpe:2.3:a:hashicorp:consul:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), }, + { + Class: "hashicorp-vault-binary", + FileGlob: "**/vault", + EvidenceMatcher: m.FileContentsVersionMatcher( + // revoke1.18.0 + `(?m)revoke(?P[0-9]+\.[0-9]+\.[0-9]+)`), + Package: "github.com/hashicorp/vault", + PURL: mustPURL("pkg:golang/github.com/hashicorp/vault@version"), + CPEs: singleCPE("cpe:2.3:a:hashicorp:vault:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, { Class: "nginx-binary", FileGlob: "**/nginx", @@ -546,7 +493,7 @@ func DefaultClassifiers() []binutils.Classifier { EvidenceMatcher: m.FileContentsVersionMatcher( // [NUL]OpenSSL 3.1.4' // [NUL]OpenSSL 1.1.1w' - `\x00OpenSSL (?P[0-9]+\.[0-9]+\.[0-9]+([a-z]|-alpha[0-9]|-beta[0-9]|-rc[0-9])?)`, + `\x00OpenSSL (?P[0-9]+\.[0-9]+\.[0-9]+([a-z]+|-alpha[0-9]|-beta[0-9]|-rc[0-9])?)`, ), Package: "openssl", PURL: mustPURL("pkg:generic/openssl@version"), @@ -680,7 +627,45 @@ func DefaultClassifiers() []binutils.Classifier { PURL: mustPURL("pkg:generic/chrome@version"), CPEs: singleCPE("cpe:2.3:a:google:chrome:*:*:*:*:*:*:*:*"), }, + { + Class: "ffmpeg-binary", + FileGlob: "**/ffmpeg", + EvidenceMatcher: m.FileContentsVersionMatcher( + // Pattern found in the binary: "%s version 7.1.1" or "%s version 6.0" + // When executed outputs: "ffmpeg version 7.1.1" or "ffmpeg version 6.0" + `(?m)%s version (?P[0-9]+\.[0-9]+(\.[0-9]+)?)`, + ), + Package: "ffmpeg", + PURL: mustPURL("pkg:generic/ffmpeg@version"), + CPEs: singleCPE("cpe:2.3:a:ffmpeg:ffmpeg:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "ffmpeg-library", + FileGlob: "**/libav*", + EvidenceMatcher: binutils.MatchAny( + // Primary pattern: FFmpeg version found in most libraries + m.FileContentsVersionMatcher(`(?m)FFmpeg version (?P[0-9]+\.[0-9]+(\.[0-9]+)?)`), + // Fallback: library-specific version patterns for libavcodec and libavformat + m.FileContentsVersionMatcher(`(?m)Lavc(?P[0-9]+\.[0-9]+\.[0-9]+)`), + m.FileContentsVersionMatcher(`(?m)Lavf(?P[0-9]+\.[0-9]+\.[0-9]+)`), + ), + Package: "ffmpeg", + PURL: mustPURL("pkg:generic/ffmpeg@version"), + CPEs: singleCPE("cpe:2.3:a:ffmpeg:ffmpeg:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "ffmpeg-library", + FileGlob: "**/libswresample*", + EvidenceMatcher: m.FileContentsVersionMatcher( + // FFmpeg version pattern for libswresample + `(?m)FFmpeg version (?P[0-9]+\.[0-9]+(\.[0-9]+)?)`), + Package: "ffmpeg", + PURL: mustPURL("pkg:generic/ffmpeg@version"), + CPEs: singleCPE("cpe:2.3:a:ffmpeg:ffmpeg:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, } + + return append(classifiers, defaultJavaClassifiers()...) } // singleCPE returns a []cpe.CPE with Source: Generated based on the cpe string or panics if the diff --git a/syft/pkg/cataloger/binary/classifiers_java.go b/syft/pkg/cataloger/binary/classifiers_java.go new file mode 100644 index 00000000000..376e45e2024 --- /dev/null +++ b/syft/pkg/cataloger/binary/classifiers_java.go @@ -0,0 +1,196 @@ +package binary + +import ( + "github.com/anchore/syft/syft/cpe" + "github.com/anchore/syft/syft/pkg/cataloger/internal/binutils" +) + +//nolint:funlen +func defaultJavaClassifiers() []binutils.Classifier { + m := binutils.ContextualEvidenceMatchers{CatalogerName: catalogerName} + + return []binutils.Classifier{ + { + Class: "java-binary", + FileGlob: "**/java", + EvidenceMatcher: binutils.BranchingEvidenceMatcher([]binutils.Classifier{ + { + Class: "java-binary-graalvm", + EvidenceMatcher: m.FileContentsVersionMatcher( + `(?m)\x00(?P[0-9]+[.0-9]+[.0-9]+\+[0-9]+-jvmci-[0-9]+[.0-9]+-b[0-9]+)\x00`), + Package: "graalvm", + PURL: mustPURL("pkg:generic/oracle/graalvm@version"), + CPEs: singleCPE("cpe:2.3:a:oracle:graalvm:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "java-binary-openjdk-zulu", + EvidenceMatcher: binutils.MatchAll( + binutils.MatchPath(`**/*zulu*/**`), + binutils.MatchAny( + m.FileContentsVersionMatcher( + // [NUL]openjdk[NUL]java[NUL]0.0[NUL]11.0.17+8-LTS[NUL] + `(?m)\x00java\x00(?P[0-9]+[.0-9]*)\x00(?P[0-9]+[^\x00]+)\x00`), + m.FileContentsVersionMatcher( + // arm64 versions: [NUL]0.0[NUL][NUL][NUL][NUL][NUL]11.0.22+7[NUL][NUL][NUL][NUL][NUL][NUL][NUL]openjdk[NUL]java[NUL] + `(?m)\x00(?P[0-9]+[.0-9]*)\x00+(?P[0-9]+[^\x00]+)\x00+(openjdk|java)`), + ), + ), + Package: "zulu", + PURL: mustPURL("pkg:generic/azul/zulu@version"), + CPEs: singleCPE("cpe:2.3:a:azul:zulu:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "java-binary-openjdk-with-update", + EvidenceMatcher: binutils.MatchAny( + m.FileContentsVersionMatcher( + `openjdk`, + // [NUL]openjdk[NUL]java[NUL]1.8[NUL]1.8.0_352-b08[NUL] + `(?m)java\x00(?P[0-9]+[.0-9]*)\x00(?P(?[0-9]+[^\x00]+)_(?[^\x00]+)-[^\x00]+)\x00`), + m.FileContentsVersionMatcher( + `openjdk`, + // arm64 versions: [NUL]0.0[NUL][NUL][NUL][NUL][NUL]1.8.0_352-b08[NUL][NUL][NUL][NUL][NUL][NUL][NUL]openjdk[NUL]java[NUL] + `(?m)\x00(?P[0-9]+[.0-9]*)\x00+(?P(?[0-9]+[^\x00]+)_(?[^\x00]+)-[^\x00]+)\x00+openjdk\x00java`), + ), + Package: "openjdk", + PURL: mustPURL("pkg:generic/oracle/openjdk@version"), + CPEs: singleCPE("cpe:2.3:a:oracle:openjdk:{{.primary}}:update{{.update}}:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "java-binary-openjdk", + EvidenceMatcher: binutils.MatchAny( + m.FileContentsVersionMatcher( + // [NUL]openjdk[NUL]java[NUL]0.0[NUL]11.0.17+8-LTS[NUL] + `(?m)\x00openjdk\x00java\x00(?P[0-9]+[.0-9]*)\x00(?P[0-9]+[^\x00]+)\x00`), + m.FileContentsVersionMatcher( + // arm64 versions: [NUL]0.0[NUL][NUL][NUL][NUL][NUL]11.0.22+7[NUL][NUL][NUL][NUL][NUL][NUL][NUL]openjdk[NUL]java[NUL] + `(?m)\x00(?P[0-9]+[.0-9]*)\x00+(?P[0-9]+[^\x00]+)\x00+openjdk\x00java`), + ), + Package: "openjdk", + PURL: mustPURL("pkg:generic/oracle/openjdk@version"), + CPEs: singleCPE("cpe:2.3:a:oracle:openjdk:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "java-binary-ibm", + EvidenceMatcher: binutils.MatchAll( + binutils.MatchAny( + binutils.MatchPath("**/ibm/**"), + binutils.SharedLibraryLookup( + `^libjli\.so$`, + m.FileContentsVersionMatcher("IBM_JAVA")), + ), + m.FileContentsVersionMatcher( + // [NUL]java[NUL]1.8[NUL][NUL][NUL]1.8.0-foreman_2022_01_20_09_33-b00[NUL] + `(?m)\x00java\x00+(?P[0-9]+[.0-9]+)\x00+(?P[0-9]+[-._a-zA-Z0-9]+)\x00`), + ), + Package: "java", + PURL: mustPURL("pkg:generic/ibm/java@version"), + CPEs: singleCPE("cpe:2.3:a:ibm:java:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "java-binary-openjdk-fallthrough", + EvidenceMatcher: m.FileContentsVersionMatcher( + "openjdk", + // [NUL]19.0.1+10-21[NUL] + `(?m)\x00(?P[0-9]+[.0-9]+[+][-0-9]+)\x00`, + ), + Package: "jre", + PURL: mustPURL("pkg:generic/oracle/jre@version"), + CPEs: singleCPE("cpe:2.3:a:oracle:jre:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "java-binary-oracle", + EvidenceMatcher: m.FileContentsVersionMatcher( + // [NUL]19.0.1+10-21[NUL] + // java[NUL]1.8[NUL]1.8.0_451-b10 + `(?m)\x00(?P[0-9]+\.[0-9]+\.[-._+a-zA-Z0-9]+)\x00`, + ), + Package: "jre", + PURL: mustPURL("pkg:generic/oracle/jre@version"), + CPEs: singleCPE("cpe:2.3:a:oracle:jre:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + }...), + }, + { + Class: "java-jdb-binary", + FileGlob: "**/jdb", + EvidenceMatcher: binutils.BranchingEvidenceMatcher([]binutils.Classifier{ + { + Class: "java-binary-graalvm", + EvidenceMatcher: m.FileContentsVersionMatcher( + `(?m)\x00(?P[0-9]+[.0-9]+[.0-9]+\+[0-9]+-jvmci-[0-9]+[.0-9]+-b[0-9]+)\x00`), + Package: "graalvm", + PURL: mustPURL("pkg:generic/oracle/graalvm@version"), + CPEs: singleCPE("cpe:2.3:a:oracle:graalvm_for_jdk:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "jdb-binary-openjdk-zulu", + EvidenceMatcher: binutils.MatchAll( + binutils.MatchPath("**/*zulu*/**"), + binutils.MatchAny( + m.FileContentsVersionMatcher( + // [NUL]jdb[NUL]0.0[NUL]11.0.17+8-LTS[NUL] + `(?m)(java|jdb)\x00(?P[0-9]+[.0-9]*)\x00(?P[0-9]+[^\x00]+)\x00`), + m.FileContentsVersionMatcher( + // arm64 versions: [NUL]0.0[NUL][NUL][NUL][NUL][NUL]11.0.22+7[NUL][NUL][NUL][NUL][NUL][NUL][NUL]jdb[NUL] + `(?m)\x00(?P[0-9]+[.0-9]*)\x00+(?P[0-9]+[^\x00]+)\x00+(java|jdb)`), + ), + ), + Package: "zulu", + PURL: mustPURL("pkg:generic/azul/zulu@version"), + CPEs: singleCPE("cpe:2.3:a:azul:zulu:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "java-jdb-binary-openjdk", + EvidenceMatcher: binutils.MatchAll( + m.FileContentsVersionMatcher( + // [NUL]openjdk[NUL]java[NUL]0.0[NUL]11.0.17+8-LTS[NUL] + // [NUL]openjdk[NUL]java[NUL]1.8[NUL]1.8.0_352-b08[NUL] + `(?m)\x00openjdk\x00java\x00(?P[0-9]+[.0-9]*)\x00(?P[0-9]+[^\x00]+)\x00`), + m.FileContentsVersionMatcher( + // arm64 versions: [NUL]0.0[NUL][NUL][NUL][NUL][NUL]11.0.22+7[NUL][NUL][NUL][NUL][NUL][NUL][NUL]openjdk[NUL]java[NUL] + `(?m)\x00(?P[0-9]+[.0-9]*)\x00+(?P[0-9]+[^\x00]+)\x00+openjdk\x00java`), + ), + Package: "openjdk", + PURL: mustPURL("pkg:generic/oracle/openjdk@version"), + CPEs: singleCPE("cpe:2.3:a:oracle:openjdk:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "java-sdk-binary-ibm", + EvidenceMatcher: binutils.MatchAll( + binutils.MatchAny( + binutils.MatchPath("**/ibm/**"), + binutils.SharedLibraryLookup( + `^libjli\.so$`, + m.FileContentsVersionMatcher("IBM_JAVA")), + ), + m.FileContentsVersionMatcher( + // [NUL]java[NUL]./lib/tools.jar./lib/sa-jdi.jar./classes.-J-ms8m[NUL][NUL]1.8[NUL][NUL][NUL]1.8.0-foreman_2022_01_20_09_33-b00[NUL] + `(?m)\x00java\x00.+?\x00(?P[0-9]+[-._a-zA-Z0-9]+)\x00`), + ), + Package: "java_sdk", + PURL: mustPURL("pkg:generic/ibm/java_sdk@version"), + CPEs: singleCPE("cpe:2.3:a:ibm:java_sdk:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "java-binary-openjdk-fallthrough", + EvidenceMatcher: binutils.MatchAll( + m.FileContentsVersionMatcher( + "openjdk", + `(?m)\x00(?P[0-9]+\.[0-9]+\.[0-9]+(\+[0-9]+)?([-._a-zA-Z0-9]+)?)\x00`), + ), + Package: "openjdk", + PURL: mustPURL("pkg:generic/oracle/openjdk@version"), + CPEs: singleCPE("cpe:2.3:a:oracle:openjdk:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + { + Class: "java-binary-jdk", + EvidenceMatcher: m.FileContentsVersionMatcher( + `(?m)\x00(?P[0-9]+\.[0-9]+\.[0-9]+(\+[0-9]+)?([-._a-zA-Z0-9]+)?)\x00`), + Package: "jdk", + PURL: mustPURL("pkg:generic/oracle/jdk@version"), + CPEs: singleCPE("cpe:2.3:a:oracle:jdk:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), + }, + }...), + }, + } +} diff --git a/syft/pkg/cataloger/binary/classifiers_java_test.go b/syft/pkg/cataloger/binary/classifiers_java_test.go new file mode 100644 index 00000000000..3d642aab64f --- /dev/null +++ b/syft/pkg/cataloger/binary/classifiers_java_test.go @@ -0,0 +1,66 @@ +package binary + +import ( + "testing" + + "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" +) + +func Test_JavaBinaryImage(t *testing.T) { + tests := []struct { + image string + expected []string + }{ + { + image: "image-java-binary", + expected: []string{ + "java @ 1.8.0-foreman_2022_09_22_15_30-b00 (/staged/positive/ibm/java)", + "jre @ 19.0.1+10-21 (/staged/positive/oracle-macos/java)", + "openjdk @ 1.8.0_352-b08 (/staged/positive/openjdk/java)", + "openjdk @ 11.0.17+8-LTS (/staged/positive/openjdk-lts/java)", + }, + }, + { + image: "image-java-zulu-8", + expected: []string{ + "zulu @ 1.8.0_462-b08 (/usr/lib/jvm/zulu8-ca-amd64/bin/jdb)", + }, + }, + { + image: "image-java-zulu-21", + expected: []string{ + "zulu @ 21.0.8+9-LTS (/usr/lib/jvm/zulu21-ca-amd64/bin/java)", + }, + }, + { + image: "image-java-ibm-8", + expected: []string{ + "java @ 1.8.0-foreman_2023_10_12_13_27-b00 (/opt/ibm/java/jre/bin/java)", + }, + }, + { + image: "image-java-ibm-jre-8", + expected: []string{ + "java @ 1.8.0-_2025_04_14_02_37-b00 (/opt/ibm/java/jre/bin/java)", + }, + }, + { + image: "image-java-ibm-sdk-8", + expected: []string{ + "java_sdk @ 1.8.0-foreman_2022_01_20_09_33-b00 (/opt/ibm/java/bin/jdb)", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.image, func(t *testing.T) { + c := NewClassifierCataloger(ClassifierCatalogerConfig{ + Classifiers: defaultJavaClassifiers(), + }) + pkgtest.NewCatalogTester(). + WithImageResolver(t, tt.image). + ExpectsPackageStrings(tt.expected). + TestCataloger(t, c) + }) + } +} diff --git a/syft/pkg/cataloger/binary/deprecated.go b/syft/pkg/cataloger/binary/deprecated.go index effccbc733d..a8ecbea794d 100644 --- a/syft/pkg/cataloger/binary/deprecated.go +++ b/syft/pkg/cataloger/binary/deprecated.go @@ -14,5 +14,5 @@ type EvidenceMatcher = binutils.EvidenceMatcher func FileContentsVersionMatcher( pattern string, ) EvidenceMatcher { - return binutils.FileContentsVersionMatcher(pattern, catalogerName) + return binutils.FileContentsVersionMatcher(catalogerName, pattern) } diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/ffmpeg-shared-libs/5.1.4/linux-amd64/libavcodec-9aae324f.so.59.37.100 b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/ffmpeg-shared-libs/5.1.4/linux-amd64/libavcodec-9aae324f.so.59.37.100 new file mode 100644 index 00000000000..632d213f72b Binary files /dev/null and b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/ffmpeg-shared-libs/5.1.4/linux-amd64/libavcodec-9aae324f.so.59.37.100 differ diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/ffmpeg/6.1.1/linux-amd64/ffmpeg b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/ffmpeg/6.1.1/linux-amd64/ffmpeg new file mode 100644 index 00000000000..4b2eb96d928 Binary files /dev/null and b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/ffmpeg/6.1.1/linux-amd64/ffmpeg differ diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/ffmpeg/7.1.1/darwin-arm64/ffmpeg b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/ffmpeg/7.1.1/darwin-arm64/ffmpeg new file mode 100644 index 00000000000..b1fd0d965ee Binary files /dev/null and b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/ffmpeg/7.1.1/darwin-arm64/ffmpeg differ diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/java-jdk-oracle/1.8.0_451-b10/linux-amd64/java b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/java-jdk-oracle/1.8.0_451-b10/linux-amd64/java new file mode 100644 index 00000000000..3a2382f6235 Binary files /dev/null and b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/java-jdk-oracle/1.8.0_451-b10/linux-amd64/java differ diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/java-jdk-oracle/1.8.0_451-b10/linux-amd64/jdb b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/java-jdk-oracle/1.8.0_451-b10/linux-amd64/jdb new file mode 100644 index 00000000000..52db5e05b8b Binary files /dev/null and b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/java-jdk-oracle/1.8.0_451-b10/linux-amd64/jdb differ diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/java-jre-ibm/1.8.0_391/linux-amd64/java b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/java-jre-ibm/1.8.0_391/linux-amd64/java deleted file mode 100644 index e555bc20869..00000000000 Binary files a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/java-jre-ibm/1.8.0_391/linux-amd64/java and /dev/null differ diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/java-jre-oracle-sdk/1.8.0_451-b10/linux-amd64/java b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/java-jre-oracle-sdk/1.8.0_451-b10/linux-amd64/java new file mode 100644 index 00000000000..3a2382f6235 Binary files /dev/null and b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/java-jre-oracle-sdk/1.8.0_451-b10/linux-amd64/java differ diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/java-jre-oracle/1.8.0_451-b10/linux-amd64/java b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/java-jre-oracle/1.8.0_451-b10/linux-amd64/java new file mode 100644 index 00000000000..3a2382f6235 Binary files /dev/null and b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/java-jre-oracle/1.8.0_451-b10/linux-amd64/java differ diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/openssl/1.1.1zb/linux-arm64/openssl b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/openssl/1.1.1zb/linux-arm64/openssl new file mode 100644 index 00000000000..2361e4478a9 Binary files /dev/null and b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/openssl/1.1.1zb/linux-arm64/openssl differ diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/vault/1.19.4/linux-arm64/vault b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/vault/1.19.4/linux-arm64/vault new file mode 100644 index 00000000000..1f4ed31597a --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/vault/1.19.4/linux-arm64/vault @@ -0,0 +1,11 @@ +name: vault +offset: 191891817 +length: 420 +snippetSha256: fd8eb7979e1e7bbc254f2f7a26f6a70ecb479cc4f50c804f3b0789bc0e229097 +fileSha256: a4754a343e619adef87a1d7e1368a0709ba29802fefbe8d70105c11085becd43 + +### byte snippet to follow ### +ctstreamPragma. +:httpssocks Locked%s.logCT_LOGLOCAL0@level[INFO][WARN]env:///v1/%sDELETEcreateErrorserrorsclient/data/lookupactualAcceptregionawskmsocikmspkcs11%s%s%scloud:%s.%s:revoke1.19.4)(nil))(%#v) {...}frenchCommonArabicBrahmiCarianChakmaCopticGothicHangulHatranHebrewKaithiKhojkiLepchaLycianLydianRejangSyriacTai_LeTangsaTangutTeluguThaanaWanchoYezidiHyphen\u%04x\U%08xgetentpasswd390625%s +%s +%q: %wnumber\uff \ No newline at end of file diff --git a/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/vault/1.20.2/linux-amd64/vault b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/vault/1.20.2/linux-amd64/vault new file mode 100644 index 00000000000..6aa98543853 --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets/vault/1.20.2/linux-amd64/vault @@ -0,0 +1,9 @@ +name: vault +offset: 213670425 +length: 220 +snippetSha256: d9b23916d00e8085a4066974641ef77962f2e0aae6f4244688d2c4fe4286c92b +fileSha256: fb484f1b458e5d2fd28270b406a8b26b28d040dddcaa1d099aa9ee4ac927b730 + +### byte snippet to follow ### +ctstreamPragma. +:httpssocks Locked%s.logCT_LOGLOCAL0@level[INFO][WARN]env:///v1/%sDELETEcreateErrorserrorsclient/data/lookupactualAcceptregionawskmsocikmspkcs11%s%s%scloud:%s.%s:revoke1.20.2)(nil))(%#v) {...}frenchCo \ No newline at end of file diff --git a/syft/pkg/cataloger/binary/test-fixtures/config.yaml b/syft/pkg/cataloger/binary/test-fixtures/config.yaml index b55527b63b8..c777ff2439e 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/config.yaml +++ b/syft/pkg/cataloger/binary/test-fixtures/config.yaml @@ -187,14 +187,6 @@ from-images: paths: - /usr/local/apache2/bin/httpd - - name: java-jre-ibm - version: 1.8.0_391 - images: - - ref: ibmjava:8@sha256:05ef6b0f754aa3a8cebcec36260a70c234a217b21240a998604f33459037bc08 - platform: linux/amd64 - paths: - - /opt/ibm/java/jre/bin/java - - version: 10.6.15 images: - ref: mariadb:10.6.15@sha256:92d499d9e02e92dc55c8160ef4004aa07f2e835197b18864ed214ca441e0dcfc @@ -320,6 +312,23 @@ from-images: paths: - /usr/local/bin/node + - name: java-jdk-oracle + version: 1.8.0_451-b10 + images: + - ref: container-registry.oracle.com/java/jdk:8u451-oraclelinux8@sha256:f9c980e52853bd0a8815ad908c9a4025ed68cb52f31f3b8cd0cd442ee367bfd1 + platform: linux/amd64 + paths: + - /usr/java/jdk-8/bin/java + - /usr/java/jdk-8/bin/jdb + + - name: java-jre-oracle-sdk + version: 1.8.0_451-b10 + images: + - ref: container-registry.oracle.com/java/serverjre:1.8.0_451@sha256:fe78fe3efd292dceb5685882ce1b13eb78492f383ccfd52a1b88a4f755b9d996 + platform: linux/amd64 + paths: + - /usr/java/jdk-8/bin/java + - name: java-jre-openjdk version: 1.8.0_352-b08 images: @@ -688,6 +697,20 @@ from-images: paths: - /bin/consul + - version: 1.20.2 + images: + - ref: hashicorp/vault@sha256:5cd2003247e0a574a66c66aee1916b1e9e7f99640298f2e61271a8842d2d2a19 + platform: linux/amd64 + paths: + - /bin/vault + + - version: 1.19.4 + images: + - ref: hashicorp/vault@sha256:b5f675b0bf681568cd7354c697fe4ce953024312d6d23ee7216deda60c192bad + platform: linux/arm64 + paths: + - /bin/vault + - version: 3.0.2 images: - ref: fluent/fluent-bit:3.0.2-amd64@sha256:7e6fe8efd51dda0739e355f58bf5e3b1623cbf2d4a23c06c7a365d9553e2d242 @@ -787,3 +810,32 @@ from-images: platform: linux/amd64 paths: - /usr/local/bin/jq + + - name: ffmpeg + version: 8.0 + images: + - ref: linuxserver/ffmpeg:version-8.0-cli@sha256:9d7e80710e7f11a276a4185f07e5e81db26fc7027ea70d1591f93ddf58e36ab4 + platform: linux/amd64 + - ref: linuxserver/ffmpeg:arm64v8-version-8.0-cli@sha256:0b6cf2e15a78094396f23a7cb3afaf7dffcad195573a2b97f190eae1ee1a0420 + platform: linux/arm64 + paths: + - /usr/local/bin/ffmpeg + + - name: ffmpeg + version: 7.1.1 + images: + - ref: linuxserver/ffmpeg:7.1.1@sha256:aea59a11c54291ac456bb2d67000445e5a8994f70bc3d96cdc29f022fbbf89fb + platform: linux/amd64 + - ref: linuxserver/ffmpeg:arm64v8-7.1.1@sha256:b2aa507f205ea2dc32369c55d0f93b5649f1b39e42d9e6cd27bd53def7a63655 + platform: linux/arm64 + paths: + - /usr/local/bin/ffmpeg + + - name: ffmpeg-shared-libs + version: 5.1.4 + images: + - ref: demisto/opencv:1.0.0.111908@sha256:abba3aab213990c666900a93db03420238527b757bf5825543cf7b4c5e11ac65 + platform: linux/amd64 + paths: + - /usr/local/lib/python3.11/site-packages/opencv_contrib_python.libs/libavcodec-9aae324f.so.59.37.100 + diff --git a/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/README.md b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/README.md index 5f31483e16c..e964804055e 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/README.md +++ b/syft/pkg/cataloger/binary/test-fixtures/elf-test-fixtures/README.md @@ -55,7 +55,7 @@ Contents of section .note.package: ``` #### Binaries related to Libraries -The resulting SBOM shoult show the following relationships: +The resulting SBOM should show the following relationships: ``` elfbinwithnestedlib -> libhello_world.so elfwithparallellibbin2 -> libhello_world.so diff --git a/syft/pkg/cataloger/binary/test-fixtures/image-java-binary/Dockerfile b/syft/pkg/cataloger/binary/test-fixtures/image-java-binary/Dockerfile new file mode 100644 index 00000000000..4c04d42a234 --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/image-java-binary/Dockerfile @@ -0,0 +1 @@ +FROM anchore/test_images:syft_bin-cf22714@sha256:c27b02c6322180fd8a7a3097d2b430bfdf9ea52ecf136edf258458e82f2c6f21 diff --git a/syft/pkg/cataloger/binary/test-fixtures/image-java-ibm-8/Dockerfile b/syft/pkg/cataloger/binary/test-fixtures/image-java-ibm-8/Dockerfile new file mode 100644 index 00000000000..ae472ceecec --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/image-java-ibm-8/Dockerfile @@ -0,0 +1,6 @@ +FROM ibmjava:8@sha256:05ef6b0f754aa3a8cebcec36260a70c234a217b21240a998604f33459037bc08 AS builder + +FROM scratch + +COPY --from=builder /opt/ibm/java/jre/bin/java /opt/ibm/java/jre/bin/ +COPY --from=builder /opt/ibm/java/jre/lib/amd64/jli/libjli.so /opt/ibm/java/jre/lib/amd64/jli/ diff --git a/syft/pkg/cataloger/binary/test-fixtures/image-java-ibm-jre-8/Dockerfile b/syft/pkg/cataloger/binary/test-fixtures/image-java-ibm-jre-8/Dockerfile new file mode 100644 index 00000000000..4f99d357e0b --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/image-java-ibm-jre-8/Dockerfile @@ -0,0 +1,6 @@ +FROM ibmjava:8-jre@sha256:3588cd1cc9b8646fe03b3b15210e69b1b520f1321f8518b69c0e7013d702fd23 AS builder + +FROM scratch + +COPY --from=builder /opt/ibm/java/jre/bin/java /opt/ibm/java/jre/bin/ +COPY --from=builder /opt/ibm/java/jre/lib/amd64/jli/libjli.so /opt/ibm/java/jre/lib/amd64/jli/ diff --git a/syft/pkg/cataloger/binary/test-fixtures/image-java-ibm-sdk-8/Dockerfile b/syft/pkg/cataloger/binary/test-fixtures/image-java-ibm-sdk-8/Dockerfile new file mode 100644 index 00000000000..bde055c7d33 --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/image-java-ibm-sdk-8/Dockerfile @@ -0,0 +1,6 @@ +FROM ibmjava:8-sdk-alpine@sha256:4f8ad2029e78f7b91721745a77fc6011a7c0e09b9edeffb6b20b6ec34a6e63cd AS builder + +FROM scratch + +COPY --from=builder /opt/ibm/java/bin/jdb /opt/ibm/java/bin/ +COPY --from=builder /opt/ibm/java/lib/amd64/jli/libjli.so /opt/ibm/java/lib/amd64/jli/ diff --git a/syft/pkg/cataloger/binary/test-fixtures/image-java-zulu-21/Dockerfile b/syft/pkg/cataloger/binary/test-fixtures/image-java-zulu-21/Dockerfile new file mode 100644 index 00000000000..7b887e77782 --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/image-java-zulu-21/Dockerfile @@ -0,0 +1,5 @@ +FROM azul/zulu-openjdk:21-jre-headless@sha256:581ebc852fcd9b52a5979b9b90dbe7cca2736bc1ecf1b9bd08ec41212d6675a4 AS builder + +FROM scratch + +COPY --from=builder /usr/lib/jvm/zulu21-ca-amd64/bin/java /usr/lib/jvm/zulu21-ca-amd64/bin/ diff --git a/syft/pkg/cataloger/binary/test-fixtures/image-java-zulu-8/Dockerfile b/syft/pkg/cataloger/binary/test-fixtures/image-java-zulu-8/Dockerfile new file mode 100644 index 00000000000..09f50c15fbf --- /dev/null +++ b/syft/pkg/cataloger/binary/test-fixtures/image-java-zulu-8/Dockerfile @@ -0,0 +1,5 @@ +FROM azul/zulu-openjdk:8-latest@sha256:7e3116bf36566e046b763b4a33f410f07f591bc84c391aae4f7891f5ecbb6764 AS builder + +FROM scratch + +COPY --from=builder /usr/lib/jvm/zulu8-ca-amd64/bin/jdb /usr/lib/jvm/zulu8-ca-amd64/bin/ diff --git a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/cli/commands/write_snippet.go b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/cli/commands/write_snippet.go index 70915be346a..a00ddec6061 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/cli/commands/write_snippet.go +++ b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/cli/commands/write_snippet.go @@ -11,7 +11,7 @@ import ( "strings" "github.com/spf13/cobra" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" "github.com/anchore/syft/syft/pkg/cataloger/binary/test-fixtures/manager/internal" "github.com/anchore/syft/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config" diff --git a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/application.go b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/application.go index d18663629d9..d758184dd57 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/application.go +++ b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/application.go @@ -8,7 +8,7 @@ import ( "github.com/hashicorp/go-multierror" "github.com/scylladb/go-set/strset" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" ) const Path = "config.yaml" diff --git a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/binary_from_image.go b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/binary_from_image.go index dc558250186..c00eee8a69b 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/binary_from_image.go +++ b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config/binary_from_image.go @@ -6,7 +6,7 @@ import ( "strings" "github.com/OneOfOne/xxhash" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" ) type BinaryFromImage struct { diff --git a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/list_entries.go b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/list_entries.go index 9ecf254401e..dca529b8d5b 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/list_entries.go +++ b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/list_entries.go @@ -2,11 +2,15 @@ package internal import ( "fmt" + "iter" "os" "path/filepath" + "slices" "sort" "strings" + "golang.org/x/exp/maps" + "github.com/anchore/syft/syft/pkg/cataloger/binary/test-fixtures/manager/internal/config" ) @@ -195,3 +199,17 @@ func (e Entries) BinaryFromImageHasSnippet(cfg config.BinaryFromImage) bool { } return true } + +func (e Entries) Sorted() iter.Seq2[LogicalEntryKey, EntryInfo] { + keys := maps.Keys(e) + slices.SortFunc(keys, func(a, b LogicalEntryKey) int { + return strings.Compare(a.Path(), b.Path()) + }) + return func(yield func(LogicalEntryKey, EntryInfo) bool) { + for _, k := range keys { + if !yield(k, e[k]) { + return + } + } + } +} diff --git a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/snippet_metadata.go b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/snippet_metadata.go index d70de3e23b0..b8ef1580cb1 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/manager/internal/snippet_metadata.go +++ b/syft/pkg/cataloger/binary/test-fixtures/manager/internal/snippet_metadata.go @@ -5,7 +5,7 @@ import ( "os" "strings" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" ) type SnippetMetadata struct { diff --git a/syft/pkg/cataloger/binary/test-fixtures/manager/testutil/snippet_or_binary.go b/syft/pkg/cataloger/binary/test-fixtures/manager/testutil/snippet_or_binary.go index d9d1e252e68..b2a18aa4b36 100644 --- a/syft/pkg/cataloger/binary/test-fixtures/manager/testutil/snippet_or_binary.go +++ b/syft/pkg/cataloger/binary/test-fixtures/manager/testutil/snippet_or_binary.go @@ -42,7 +42,7 @@ func SnippetOrBinary(t *testing.T, path string, requireBinary bool) string { require.NoError(t, err) var fixturePath string - for k, v := range entries { + for k, v := range entries.Sorted() { if filepath.Dir(k.Path()) == path { // prefer the snippet over the binary if !requireBinary { diff --git a/syft/pkg/cataloger/conda/cataloger.go b/syft/pkg/cataloger/conda/cataloger.go new file mode 100644 index 00000000000..39667c8c070 --- /dev/null +++ b/syft/pkg/cataloger/conda/cataloger.go @@ -0,0 +1,46 @@ +/* +Package conda provides a concrete Cataloger implementation for packages within the Conda ecosystem. +*/ +package conda + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/generic" +) + +// NewCondaMetaCataloger returns a new cataloger object for Conda environments by parsing the package metadata files in conda-meta. +func NewCondaMetaCataloger() pkg.Cataloger { + return generic.NewCataloger("conda-meta-cataloger"). + WithParserByGlobs(parseCondaMetaJSON, "**/conda-meta/*.json") +} + +func parseCondaMetaJSON(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + dec := json.NewDecoder(reader) + var meta pkg.CondaMetaPackage + if err := dec.Decode(&meta); err != nil { + return nil, nil, fmt.Errorf("failed to parse conda-meta package file at %s: %w", reader.RealPath, err) + } + + p := pkg.Package{ + Name: meta.Name, + Version: meta.Version, + Locations: file.NewLocationSet(reader.Location), + Licenses: pkg.NewLicenseSet( + pkg.NewLicenseFromLocationsWithContext(ctx, meta.License, reader.Location), + ), + Language: pkg.UnknownLanguage, + Type: pkg.CondaPkg, + Metadata: meta, + } + p.SetID() + + return []pkg.Package{ + p, + }, nil, nil +} diff --git a/syft/pkg/cataloger/conda/cataloger_test.go b/syft/pkg/cataloger/conda/cataloger_test.go new file mode 100644 index 00000000000..0c25db32653 --- /dev/null +++ b/syft/pkg/cataloger/conda/cataloger_test.go @@ -0,0 +1,250 @@ +package conda + +import ( + "context" + "strings" + "testing" + + "github.com/go-test/deep" + "github.com/stretchr/testify/require" + + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" +) + +func Test_CondaCataloger(t *testing.T) { + ctx := context.TODO() + + tests := []struct { + name string + fixture string + expectedPackages []pkg.Package + wantErr require.ErrorAssertionFunc + }{ + { + name: "multiple packages in conda meta (python, c binaries, ...)", + fixture: "test-fixtures/conda-meta-python-c-etc", + wantErr: require.NoError, + expectedPackages: []pkg.Package{ + { + Name: "jupyterlab", + Version: "4.4.3", + FoundBy: "conda-meta-cataloger", + Locations: file.NewLocationSet( + file.NewLocation("conda-meta/jupyterlab-4.4.3-pyhd8ed1ab_0.json"), + ), + Language: pkg.UnknownLanguage, + Type: pkg.CondaPkg, + Licenses: pkg.NewLicenseSet( + pkg.NewLicenseFromLocationsWithContext(ctx, "BSD-3-Clause", file.NewLocation("conda-meta/jupyterlab-4.4.3-pyhd8ed1ab_0.json")), + ), + Metadata: pkg.CondaMetaPackage{ + Name: "jupyterlab", + Version: "4.4.3", + Build: "pyhd8ed1ab_0", + BuildNumber: 0, + Channel: "https://conda.anaconda.org/conda-forge/", + Subdir: "noarch", + Noarch: "python", + License: "BSD-3-Clause", + LicenseFamily: "BSD", + MD5: "4861a0c2a5a5d0481a450a9dfaf9febe", + SHA256: "fc0235a71d852734fe92183a78cb91827367573450eba82465ae522c64230736", + Size: 8236973, + Timestamp: 1748273017680, + Filename: "jupyterlab-4.4.3-pyhd8ed1ab_0.conda", + URL: "https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.4.3-pyhd8ed1ab_0.conda", + ExtractedPackageDir: "/Users/example-user/Library/Caches/rattler/cache/pkgs/jupyterlab-4.4.3-pyhd8ed1ab_0", + Depends: []string{ + "async-lru >=1.0.0", + "httpx >=0.25.0", + "importlib-metadata >=4.8.3", + "ipykernel >=6.5.0", + "jinja2 >=3.0.3", + "jupyter-lsp >=2.0.0", + "jupyter_core", + "jupyter_server >=2.4.0,<3", + "jupyterlab_server >=2.27.1,<3", + "notebook-shim >=0.2", + "packaging", + "python >=3.9", + "setuptools >=41.1.0", + "tomli >=1.2.2", + "tornado >=6.2.0", + "traitlets", + }, + Files: []string{ + "lib/python3.13/site-packages/jupyterlab/schemas/@jupyterlab/apputils-extension/kernels-settings.json", + "lib/python3.13/site-packages/jupyterlab/schemas/@jupyterlab/apputils-extension/notification.json", + }, + PathsData: &pkg.CondaPathsData{ + PathsVersion: 1, + Paths: []pkg.CondaPathData{ + { + Path: "lib/python3.13/site-packages/jupyterlab/schemas/@jupyterlab/apputils-extension/kernels-settings.json", + PathType: "hardlink", + SHA256: "081a7e126deffbcd596863f3349a19416fbbe1fd570ab392270315f7cf5a8c27", + SHA256InPrefix: "081a7e126deffbcd596863f3349a19416fbbe1fd570ab392270315f7cf5a8c27", + SizeInBytes: 935, + }, + { + Path: "lib/python3.13/site-packages/jupyterlab/schemas/@jupyterlab/apputils-extension/notification.json", + PathType: "hardlink", + SHA256: "f9f42636592f62cdd03e3d5552b020811e3f8be6fc47c03d5a92396941b8d5d8", + SHA256InPrefix: "f9f42636592f62cdd03e3d5552b020811e3f8be6fc47c03d5a92396941b8d5d8", + SizeInBytes: 1565, + }, + }, + }, + Link: &pkg.CondaLink{ + Source: "/Users/example-user/Library/Caches/rattler/cache/pkgs/jupyterlab-4.4.3-pyhd8ed1ab_0", + Type: 1, + }, + }, + }, + { + Name: "zlib", + Version: "1.2.11", + FoundBy: "conda-meta-cataloger", + Locations: file.NewLocationSet( + file.NewLocation("conda-meta/zlib-1.2.11-h90dfc92_1014.json"), + ), + Language: pkg.UnknownLanguage, + Type: pkg.CondaPkg, + Licenses: pkg.NewLicenseSet( + pkg.NewLicenseFromLocationsWithContext(ctx, "Zlib", file.NewLocation("conda-meta/zlib-1.2.11-h90dfc92_1014.json")), + ), + Metadata: pkg.CondaMetaPackage{ + Arch: "arm64", + Name: "zlib", + Version: "1.2.11", + Build: "h90dfc92_1014", + BuildNumber: 1014, + Channel: "https://conda.anaconda.org/conda-forge/", + Subdir: "osx-arm64", + Noarch: "", + License: "Zlib", + LicenseFamily: "Other", + MD5: "348a30b1350c9d91a4dbf05f5e46e0bb", + SHA256: "a70c028fd3b9af1d7ea3d7099d810f3d2588096237bb472db331a51a36f931c0", + Size: 86757, + Timestamp: 1648307332172, + Filename: "zlib-1.2.11-h90dfc92_1014.tar.bz2", + URL: "https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.11-h90dfc92_1014.tar.bz2", + ExtractedPackageDir: "/Users/example-user/Library/Caches/rattler/cache/pkgs/zlib-1.2.11-h90dfc92_1014", + Depends: []string{ + "libzlib 1.2.11 h90dfc92_1014", + }, + Files: []string{ + "include/zconf.h", + "include/zlib.h", + "lib/pkgconfig/zlib.pc", + "lib/libz.a", + "lib/libz.dylib", + }, + PathsData: &pkg.CondaPathsData{ + PathsVersion: 1, + Paths: []pkg.CondaPathData{ + { + Path: "include/zconf.h", + PathType: "hardlink", + SHA256: "77304005ceb5f0d03ad4c37eb8386a10866e4ceeb204f7c3b6599834c7319541", + SHA256InPrefix: "77304005ceb5f0d03ad4c37eb8386a10866e4ceeb204f7c3b6599834c7319541", + SizeInBytes: 16262, + }, + { + Path: "include/zlib.h", + PathType: "hardlink", + SHA256: "4ddc82b4af931ab55f44d977bde81bfbc4151b5dcdccc03142831a301b5ec3c8", + SHA256InPrefix: "4ddc82b4af931ab55f44d977bde81bfbc4151b5dcdccc03142831a301b5ec3c8", + SizeInBytes: 96239, + }, + { + Path: "lib/pkgconfig/zlib.pc", + PathType: "hardlink", + SHA256: "357773df3c44a5ebd77fdadd0869b5b06394bbf556c2d6c9736dd53e9df3b2c2", + SHA256InPrefix: "5b4eb6062f97875eaadb3b6c7cf8cfeff3808798ecbf2bfc095f18dcecc509bf", + SizeInBytes: 285, + }, + { + Path: "lib/libz.a", + PathType: "hardlink", + SHA256: "40c056a5d8155d9b3f42adfe35f7fc6e5fa15cc6588ffad0f09fe67517feada0", + SHA256InPrefix: "40c056a5d8155d9b3f42adfe35f7fc6e5fa15cc6588ffad0f09fe67517feada0", + SizeInBytes: 107128, + }, + { + Path: "lib/libz.dylib", + PathType: "softlink", + SHA256: "67ed489e2f378880f72fb1c0d1cc916e184b9632eccf2b5c1b34ddf01ed1701c", + SHA256InPrefix: "09e47dbc60aa970e153913fe84551ad7f5aa51c21907591340a0cc999adab859", + SizeInBytes: 122478, + }, + }, + }, + Link: &pkg.CondaLink{ + Source: "/Users/example-user/Library/Caches/rattler/cache/pkgs/zlib-1.2.11-h90dfc92_1014", + Type: 1, + }, + }, + }, + }, + }, + { + name: "badly formatted conda meta json file", + fixture: "test-fixtures/conda-meta-bad-json", + expectedPackages: nil, + wantErr: func(t require.TestingT, err error, msgAndArgs ...interface{}) { + require.Error(t, err) + require.Contains(t, err.Error(), "failed to parse conda-meta package file at conda-meta/package-1.2.3-pyhd8ed1ab_0.json") + require.Contains(t, err.Error(), "invalid character") + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + pkgtest.NewCatalogTester(). + FromDirectory(t, test.fixture). + Expects(test.expectedPackages, nil). + WithErrorAssertion(test.wantErr). + TestCataloger(t, NewCondaMetaCataloger()) + }) + } +} + +func TestCondaMetaPackageMetadata_FileOwner(t *testing.T) { + tests := []struct { + metadata pkg.CondaMetaPackage + expected []string + }{ + { + metadata: pkg.CondaMetaPackage{ + Files: []string{ + "include/zconf.h", + "include/zlib.h", + "lib/pkgconfig/zlib.pc", + "lib/libz.a", + "lib/libz.dylib", + }, + }, + expected: []string{ + "include/zconf.h", + "include/zlib.h", + "lib/libz.a", + "lib/libz.dylib", + "lib/pkgconfig/zlib.pc", + }, + }, + } + + for _, test := range tests { + t.Run(strings.Join(test.expected, ","), func(t *testing.T) { + actual := test.metadata.OwnedFiles() + for _, d := range deep.Equal(test.expected, actual) { + t.Errorf("diff: %+v", d) + } + }) + } +} diff --git a/syft/pkg/cataloger/conda/test-fixtures/conda-meta-bad-json/conda-meta/package-1.2.3-pyhd8ed1ab_0.json b/syft/pkg/cataloger/conda/test-fixtures/conda-meta-bad-json/conda-meta/package-1.2.3-pyhd8ed1ab_0.json new file mode 100644 index 00000000000..d3ec19eb9a7 --- /dev/null +++ b/syft/pkg/cataloger/conda/test-fixtures/conda-meta-bad-json/conda-meta/package-1.2.3-pyhd8ed1ab_0.json @@ -0,0 +1 @@ +not json, will cause a parsing error diff --git a/syft/pkg/cataloger/conda/test-fixtures/conda-meta-python-c-etc/conda-meta/jupyterlab-4.4.3-pyhd8ed1ab_0.json b/syft/pkg/cataloger/conda/test-fixtures/conda-meta-python-c-etc/conda-meta/jupyterlab-4.4.3-pyhd8ed1ab_0.json new file mode 100644 index 00000000000..2c6447d716c --- /dev/null +++ b/syft/pkg/cataloger/conda/test-fixtures/conda-meta-python-c-etc/conda-meta/jupyterlab-4.4.3-pyhd8ed1ab_0.json @@ -0,0 +1,63 @@ +{ + "build": "pyhd8ed1ab_0", + "build_number": 0, + "depends": [ + "async-lru >=1.0.0", + "httpx >=0.25.0", + "importlib-metadata >=4.8.3", + "ipykernel >=6.5.0", + "jinja2 >=3.0.3", + "jupyter-lsp >=2.0.0", + "jupyter_core", + "jupyter_server >=2.4.0,<3", + "jupyterlab_server >=2.27.1,<3", + "notebook-shim >=0.2", + "packaging", + "python >=3.9", + "setuptools >=41.1.0", + "tomli >=1.2.2", + "tornado >=6.2.0", + "traitlets" + ], + "license": "BSD-3-Clause", + "license_family": "BSD", + "md5": "4861a0c2a5a5d0481a450a9dfaf9febe", + "name": "jupyterlab", + "noarch": "python", + "sha256": "fc0235a71d852734fe92183a78cb91827367573450eba82465ae522c64230736", + "size": 8236973, + "subdir": "noarch", + "timestamp": 1748273017680, + "version": "4.4.3", + "fn": "jupyterlab-4.4.3-pyhd8ed1ab_0.conda", + "url": "https://conda.anaconda.org/conda-forge/noarch/jupyterlab-4.4.3-pyhd8ed1ab_0.conda", + "channel": "https://conda.anaconda.org/conda-forge/", + "extracted_package_dir": "/Users/example-user/Library/Caches/rattler/cache/pkgs/jupyterlab-4.4.3-pyhd8ed1ab_0", + "files": [ + "lib/python3.13/site-packages/jupyterlab/schemas/@jupyterlab/apputils-extension/kernels-settings.json", + "lib/python3.13/site-packages/jupyterlab/schemas/@jupyterlab/apputils-extension/notification.json" + ], + "paths_data": { + "paths_version": 1, + "paths": [ + { + "_path": "lib/python3.13/site-packages/jupyterlab/schemas/@jupyterlab/apputils-extension/kernels-settings.json", + "path_type": "hardlink", + "sha256": "081a7e126deffbcd596863f3349a19416fbbe1fd570ab392270315f7cf5a8c27", + "sha256_in_prefix": "081a7e126deffbcd596863f3349a19416fbbe1fd570ab392270315f7cf5a8c27", + "size_in_bytes": 935 + }, + { + "_path": "lib/python3.13/site-packages/jupyterlab/schemas/@jupyterlab/apputils-extension/notification.json", + "path_type": "hardlink", + "sha256": "f9f42636592f62cdd03e3d5552b020811e3f8be6fc47c03d5a92396941b8d5d8", + "sha256_in_prefix": "f9f42636592f62cdd03e3d5552b020811e3f8be6fc47c03d5a92396941b8d5d8", + "size_in_bytes": 1565 + } + ] + }, + "link": { + "source": "/Users/example-user/Library/Caches/rattler/cache/pkgs/jupyterlab-4.4.3-pyhd8ed1ab_0", + "type": 1 + } +} diff --git a/syft/pkg/cataloger/conda/test-fixtures/conda-meta-python-c-etc/conda-meta/zlib-1.2.11-h90dfc92_1014.json b/syft/pkg/cataloger/conda/test-fixtures/conda-meta-python-c-etc/conda-meta/zlib-1.2.11-h90dfc92_1014.json new file mode 100644 index 00000000000..bd85a3d7468 --- /dev/null +++ b/syft/pkg/cataloger/conda/test-fixtures/conda-meta-python-c-etc/conda-meta/zlib-1.2.11-h90dfc92_1014.json @@ -0,0 +1,75 @@ +{ + "arch": "arm64", + "build": "h90dfc92_1014", + "build_number": 1014, + "depends": [ + "libzlib 1.2.11 h90dfc92_1014" + ], + "license": "Zlib", + "license_family": "Other", + "md5": "348a30b1350c9d91a4dbf05f5e46e0bb", + "name": "zlib", + "platform": "osx", + "sha256": "a70c028fd3b9af1d7ea3d7099d810f3d2588096237bb472db331a51a36f931c0", + "size": 86757, + "subdir": "osx-arm64", + "timestamp": 1648307332172, + "version": "1.2.11", + "fn": "zlib-1.2.11-h90dfc92_1014.tar.bz2", + "url": "https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.11-h90dfc92_1014.tar.bz2", + "channel": "https://conda.anaconda.org/conda-forge/", + "extracted_package_dir": "/Users/example-user/Library/Caches/rattler/cache/pkgs/zlib-1.2.11-h90dfc92_1014", + "files": [ + "include/zconf.h", + "include/zlib.h", + "lib/pkgconfig/zlib.pc", + "lib/libz.a", + "lib/libz.dylib" + ], + "paths_data": { + "paths_version": 1, + "paths": [ + { + "_path": "include/zconf.h", + "path_type": "hardlink", + "sha256": "77304005ceb5f0d03ad4c37eb8386a10866e4ceeb204f7c3b6599834c7319541", + "sha256_in_prefix": "77304005ceb5f0d03ad4c37eb8386a10866e4ceeb204f7c3b6599834c7319541", + "size_in_bytes": 16262 + }, + { + "_path": "include/zlib.h", + "path_type": "hardlink", + "sha256": "4ddc82b4af931ab55f44d977bde81bfbc4151b5dcdccc03142831a301b5ec3c8", + "sha256_in_prefix": "4ddc82b4af931ab55f44d977bde81bfbc4151b5dcdccc03142831a301b5ec3c8", + "size_in_bytes": 96239 + }, + { + "_path": "lib/pkgconfig/zlib.pc", + "path_type": "hardlink", + "sha256": "357773df3c44a5ebd77fdadd0869b5b06394bbf556c2d6c9736dd53e9df3b2c2", + "sha256_in_prefix": "5b4eb6062f97875eaadb3b6c7cf8cfeff3808798ecbf2bfc095f18dcecc509bf", + "size_in_bytes": 285, + "file_mode": "text", + "prefix_placeholder": "/Users/runner/miniforge3/conda-bld/zlib-split_1648307175973/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehol" + }, + { + "_path": "lib/libz.a", + "path_type": "hardlink", + "sha256": "40c056a5d8155d9b3f42adfe35f7fc6e5fa15cc6588ffad0f09fe67517feada0", + "sha256_in_prefix": "40c056a5d8155d9b3f42adfe35f7fc6e5fa15cc6588ffad0f09fe67517feada0", + "size_in_bytes": 107128 + }, + { + "_path": "lib/libz.dylib", + "path_type": "softlink", + "sha256": "67ed489e2f378880f72fb1c0d1cc916e184b9632eccf2b5c1b34ddf01ed1701c", + "sha256_in_prefix": "09e47dbc60aa970e153913fe84551ad7f5aa51c21907591340a0cc999adab859", + "size_in_bytes": 122478 + } + ] + }, + "link": { + "source": "/Users/example-user/Library/Caches/rattler/cache/pkgs/zlib-1.2.11-h90dfc92_1014", + "type": 1 + } +} diff --git a/syft/pkg/cataloger/cpp/test-fixtures/README.md b/syft/pkg/cataloger/cpp/test-fixtures/README.md index 3b27033666f..e1311bc2ca9 100644 --- a/syft/pkg/cataloger/cpp/test-fixtures/README.md +++ b/syft/pkg/cataloger/cpp/test-fixtures/README.md @@ -6,7 +6,7 @@ This folder contains the test data for the Conan package manager. The conan lock file is created in the following way. -We explicitly use a package which has dependencies, which in turn also have dependendencies. +We explicitly use a package which has dependencies, which in turn also have dependencies. This is necessary to verify that the dependency tree is properly parsed. 1. Use `conan lock create --reference "mfast/1.2.2#c6f6387c9b99780f0ee05e25f99d0f39"` diff --git a/syft/pkg/cataloger/dart/parse_pubspec.go b/syft/pkg/cataloger/dart/parse_pubspec.go index 03e9bc33618..5a32a2fe202 100644 --- a/syft/pkg/cataloger/dart/parse_pubspec.go +++ b/syft/pkg/cataloger/dart/parse_pubspec.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" diff --git a/syft/pkg/cataloger/dart/parse_pubspec_lock.go b/syft/pkg/cataloger/dart/parse_pubspec_lock.go index 5a49f70d497..d3d5c91c585 100644 --- a/syft/pkg/cataloger/dart/parse_pubspec_lock.go +++ b/syft/pkg/cataloger/dart/parse_pubspec_lock.go @@ -7,7 +7,7 @@ import ( "regexp" "sort" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/unknown" diff --git a/syft/pkg/cataloger/debian/package.go b/syft/pkg/cataloger/debian/package.go index 5dd3c8c178f..88102da6e35 100644 --- a/syft/pkg/cataloger/debian/package.go +++ b/syft/pkg/cataloger/debian/package.go @@ -133,6 +133,7 @@ func addLicenses(ctx context.Context, resolver file.Resolver, dbLocation file.Lo if len(licenseStrs) == 0 { sr, sl := fetchCopyrightContents(resolver, dbLocation, metadata) if sr != nil && sl != nil { + defer internal.CloseAndLogError(sr, sl.AccessPath) p.Licenses.Add(pkg.NewLicensesFromReadCloserWithContext(ctx, file.NewLocationReadCloser(*sl, sr))...) } } @@ -292,11 +293,10 @@ func fetchCopyrightContents(resolver file.Resolver, dbLocation file.Location, m return nil, nil } - reader, err := resolver.FileContentsByLocation(*location) + reader, err := resolver.FileContentsByLocation(*location) //nolint:gocritic // since we're returning the reader, it's up to the caller to close it if err != nil { log.Tracef("failed to fetch deb copyright contents (package=%s): %s", m.Package, err) } - defer internal.CloseAndLogError(reader, location.RealPath) l := location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) diff --git a/syft/pkg/cataloger/dotnet/libman_json.go b/syft/pkg/cataloger/dotnet/libman_json.go index 4483a5cb44b..7f585eb0843 100644 --- a/syft/pkg/cataloger/dotnet/libman_json.go +++ b/syft/pkg/cataloger/dotnet/libman_json.go @@ -98,7 +98,6 @@ func findLibmanJSON(resolver file.Resolver, depsJSON file.Location) (*libmanJSON if err != nil { return nil, err } - internal.CloseAndLogError(reader, loc.RealPath) lj, err := newLibmanJSON(file.NewLocationReadCloser(*loc, reader)) if err != nil { diff --git a/syft/pkg/cataloger/generic/cataloger.go b/syft/pkg/cataloger/generic/cataloger.go index 77863dd6d59..abdad629302 100644 --- a/syft/pkg/cataloger/generic/cataloger.go +++ b/syft/pkg/cataloger/generic/cataloger.go @@ -53,6 +53,7 @@ func (p resolvingProcessorWrapper) process(ctx context.Context, resolver file.Re type Cataloger struct { processors []processExecutor requesters []requester + checks []func() error upstreamCataloger string } @@ -127,6 +128,11 @@ func (c *Cataloger) WithResolvingProcessors(processors ...ResolvingProcessor) *C return c } +func (c *Cataloger) WithChecks(checks ...func() error) *Cataloger { + c.checks = append(c.checks, checks...) + return c +} + func makeRequests(parser Parser, locations []file.Location) []request { var requests []request for _, l := range locations { @@ -152,6 +158,12 @@ func (c *Cataloger) Name() string { // Catalog is given an object to resolve file references and content, this function returns any discovered Packages after analyzing the catalog source. func (c *Cataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) { + for _, check := range c.checks { + if err := check(); err != nil { + return nil, nil, err + } + } + var packages []pkg.Package var relationships []artifact.Relationship diff --git a/syft/pkg/cataloger/githubactions/parse_composite_action.go b/syft/pkg/cataloger/githubactions/parse_composite_action.go index 87075e0992d..082d70fb7a2 100644 --- a/syft/pkg/cataloger/githubactions/parse_composite_action.go +++ b/syft/pkg/cataloger/githubactions/parse_composite_action.go @@ -5,7 +5,7 @@ import ( "fmt" "io" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" diff --git a/syft/pkg/cataloger/githubactions/parse_workflow.go b/syft/pkg/cataloger/githubactions/parse_workflow.go index 9862b7ee81c..c4f27c549d4 100644 --- a/syft/pkg/cataloger/githubactions/parse_workflow.go +++ b/syft/pkg/cataloger/githubactions/parse_workflow.go @@ -6,7 +6,7 @@ import ( "io" "regexp" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" diff --git a/syft/pkg/cataloger/golang/license_finder.go b/syft/pkg/cataloger/golang/license_finder.go new file mode 100644 index 00000000000..e73076a3176 --- /dev/null +++ b/syft/pkg/cataloger/golang/license_finder.go @@ -0,0 +1,149 @@ +package golang + +import ( + "context" + "fmt" + "path/filepath" + "regexp" + "strings" + + "github.com/spf13/afero" + + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" +) + +// resolveModuleLicenses finds and parses license files for Go modules +func resolveModuleLicenses(ctx context.Context, pkgInfos []pkgInfo, fs afero.Fs) pkg.LicenseSet { + licenses := pkg.NewLicenseSet() + + for _, info := range pkgInfos { + modDir, pkgDir, err := getAbsolutePkgPaths(info) + if err != nil { + continue + } + + licenseFiles, err := findAllLicenseCandidatesUpwards(pkgDir, licenseRegexp, modDir, fs) + if err != nil { + continue + } + + for _, f := range licenseFiles { + contents, err := fs.Open(f) + if err != nil { + continue + } + licenses.Add(pkg.NewLicensesFromReadCloserWithContext(ctx, file.NewLocationReadCloser(file.Location{}, contents))...) + _ = contents.Close() + } + } + + return licenses +} + +/* +findAllLicenseCandidatesUpwards performs a bubble-up search per package: +1. pkgInfos represents a sparse vertical distribution of packages within modules +2. we get more pkgInfos for free when the build configuration is updated + +The recursion terminates via two conditions: +- When dir is outside stopAt boundary (happy case) +- When reaching filesystem root where parent == dir (edge case) + +Note: The code does NOT follow symlinks. It returns a slice of absolute paths that +represent license file matches that are resolved independently of the bubble-up. + +When we should consider redesign tip to stem: +- Reduced filesystem calls: Single traversal vs multiple per-package +- Path deduplication: Avoids re-scanning common parent directories +- Better for wide module structures: Efficient when many packages share parent paths +- We need to consider the case here where nested modules are visited by accident and licenses +are erroneously associated to a 'parent module'; bubble up currently prevents this +*/ +func findAllLicenseCandidatesUpwards(dir string, r *regexp.Regexp, stopAt string, fs afero.Fs) ([]string, error) { + // Validate that both paths are absolute + if !filepath.IsAbs(dir) { + return nil, fmt.Errorf("dir must be an absolute path, got: %s", dir) + } + if !filepath.IsAbs(stopAt) { + return nil, fmt.Errorf("stopAt must be an absolute path, got: %s", stopAt) + } + + licenses, err := findLicenseCandidates(dir, r, stopAt, fs) + if err != nil { + return nil, err + } + + // Ensure we return an empty slice rather than nil for consistency + if licenses == nil { + return []string{}, nil + } + return licenses, nil +} + +func findLicenseCandidates(dir string, r *regexp.Regexp, stopAt string, fs afero.Fs) ([]string, error) { + // stop if we've gone outside the stopAt directory + if !strings.HasPrefix(dir, stopAt) { + return []string{}, nil + } + + licenses, err := findLicensesInDir(dir, r, fs) + if err != nil { + return nil, err + } + + parent := filepath.Dir(dir) + // can't go any higher up the directory tree: "/" case + if parent == dir { + return licenses, nil + } + + // search parent directory and combine results + parentLicenses, err := findLicenseCandidates(parent, r, stopAt, fs) + if err != nil { + return nil, err + } + + // Combine current directory licenses with parent directory licenses + return append(licenses, parentLicenses...), nil +} + +func getAbsolutePkgPaths(info pkgInfo) (modDir string, pkgDir string, err error) { + pkgDir, err = filepath.Abs(info.pkgDir) + if err != nil { + return modDir, pkgDir, err + } + + modDir, err = filepath.Abs(info.moduleDir) + if err != nil { + return modDir, pkgDir, err + } + + if !strings.HasPrefix(pkgDir, modDir) { + return modDir, pkgDir, fmt.Errorf("modDir %s should contain pkgDir %s", modDir, pkgDir) + } + + return modDir, pkgDir, nil +} + +func findLicensesInDir(dir string, r *regexp.Regexp, fs afero.Fs) ([]string, error) { + var licenses []string + + dirContents, err := afero.ReadDir(fs, dir) + if err != nil { + return nil, err + } + + for _, f := range dirContents { + if f.IsDir() { + continue + } + + if r.MatchString(f.Name()) { + path := filepath.Join(dir, f.Name()) + licenses = append(licenses, path) + } + } + + return licenses, nil +} diff --git a/syft/pkg/cataloger/golang/license_finder_test.go b/syft/pkg/cataloger/golang/license_finder_test.go new file mode 100644 index 00000000000..cbb33b14b38 --- /dev/null +++ b/syft/pkg/cataloger/golang/license_finder_test.go @@ -0,0 +1,220 @@ +package golang + +import ( + "testing" + + "github.com/spf13/afero" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestFindAllLicenseCandidatesUpwards(t *testing.T) { + tests := []struct { + name string + setupFS func(afero.Fs) + startDir string + stopAt string + expectedFiles []string + expectedError bool + description string + }{ + { + name: "normal traversal up to root", + startDir: "/project/subdir/deeper", + stopAt: "/project", + setupFS: func(fs afero.Fs) { + fs.MkdirAll("/project/subdir/deeper", 0755) + afero.WriteFile(fs, "/project/LICENSE", []byte("MIT"), 0644) + afero.WriteFile(fs, "/project/foobar", []byte("MIT"), 0644) + afero.WriteFile(fs, "/project/subdir/LICENSE.txt", []byte("Apache"), 0644) + afero.WriteFile(fs, "/project/subdir/deeper/COPYING", []byte("GPL"), 0644) + }, + expectedFiles: []string{ + "/project/subdir/deeper/COPYING", + "/project/subdir/LICENSE.txt", + "/project/LICENSE", + }, + description: "Should find all license files traversing upward", + }, + { + name: "stops at boundary directory", + startDir: "/project/subdir/deeper", + stopAt: "/project/subdir", + setupFS: func(fs afero.Fs) { + fs.MkdirAll("/project/subdir/deeper", 0755) + afero.WriteFile(fs, "/project/LICENSE", []byte("MIT"), 0644) + afero.WriteFile(fs, "/project/subdir/LICENSE.txt", []byte("Apache"), 0644) + afero.WriteFile(fs, "/project/subdir/deeper/COPYING", []byte("GPL"), 0644) + }, + expectedFiles: []string{ + "/project/subdir/deeper/COPYING", + "/project/subdir/LICENSE.txt", + }, + description: "Should stop at stopAt boundary and not find LICENSE in /project", + }, + { + name: "handles non-existent directory", + startDir: "/nonexistent", + stopAt: "/", + setupFS: func(fs afero.Fs) { + // Don't create the directory + }, + expectedError: true, + description: "Should return error for non-existent directory", + }, + { + name: "handles empty directory tree", + startDir: "/empty/dir/tree", + stopAt: "/empty", + setupFS: func(fs afero.Fs) { + fs.MkdirAll("/empty/dir/tree", 0755) + // No license files + }, + expectedFiles: []string{}, + description: "Should return empty slice when no license files found", + }, + { + name: "handles directory at filesystem root", + startDir: "/", + stopAt: "/", + setupFS: func(fs afero.Fs) { + afero.WriteFile(fs, "/LICENSE", []byte("MIT"), 0644) + }, + expectedFiles: []string{"/LICENSE"}, + description: "Should handle traversal starting at root", + }, + { + name: "ignores directories with license-like names", + startDir: "/project/subdir", + stopAt: "/project", + setupFS: func(fs afero.Fs) { + fs.MkdirAll("/project/subdir", 0755) + fs.MkdirAll("/project/LICENSE_DIR", 0755) // Directory, should be ignored + afero.WriteFile(fs, "/project/LICENSE", []byte("MIT"), 0644) + }, + expectedFiles: []string{"/project/LICENSE"}, + description: "Should ignore directories even if they match license pattern", + }, + { + name: "startDir equals stopAt", + startDir: "/project", + stopAt: "/project", + setupFS: func(fs afero.Fs) { + fs.MkdirAll("/project", 0755) + afero.WriteFile(fs, "/project/LICENSE", []byte("MIT"), 0644) + }, + expectedFiles: []string{"/project/LICENSE"}, + description: "Should handle case where start equals stop directory", + }, + { + name: "startDir is parent of stopAt (returns empty)", + startDir: "/", + stopAt: "/project", + setupFS: func(fs afero.Fs) { + fs.MkdirAll("/project", 0755) + afero.WriteFile(fs, "/LICENSE", []byte("MIT"), 0644) + }, + expectedFiles: []string{}, + description: "Should return empty when startDir is above stopAt", + }, + { + name: "very deep nesting", + startDir: "/a/b/c/d/e/f/g/h/i/j", + stopAt: "/a", + setupFS: func(fs afero.Fs) { + fs.MkdirAll("/a/b/c/d/e/f/g/h/i/j", 0755) + afero.WriteFile(fs, "/a/LICENSE", []byte("MIT"), 0644) + afero.WriteFile(fs, "/a/b/c/d/e/NOTICE", []byte("Notice"), 0644) + }, + expectedFiles: []string{ + "/a/b/c/d/e/NOTICE", + "/a/LICENSE", + }, + description: "Should handle deep directory nesting without stack overflow", + }, + { + name: "relative dir path rejected", + startDir: "project/subdir", + stopAt: "/project", + setupFS: func(fs afero.Fs) { + fs.MkdirAll("/project/subdir", 0755) + }, + expectedError: true, + description: "Should reject relative dir path", + }, + { + name: "relative stopAt path rejected", + startDir: "/project/subdir", + stopAt: "project", + setupFS: func(fs afero.Fs) { + fs.MkdirAll("/project/subdir", 0755) + }, + expectedError: true, + description: "Should reject relative stopAt path", + }, + { + name: "stopAt is descendant of startDir", + startDir: "/project", + stopAt: "/project/subdir/deeper", + setupFS: func(fs afero.Fs) { + fs.MkdirAll("/project/subdir/deeper", 0755) + afero.WriteFile(fs, "/project/LICENSE", []byte("MIT"), 0644) + }, + expectedFiles: []string{}, + description: "Should return empty when stopAt is below startDir", + }, + { + name: "disjoint paths", + startDir: "/foo/bar", + stopAt: "/baz/qux", + setupFS: func(fs afero.Fs) { + fs.MkdirAll("/foo/bar", 0755) + fs.MkdirAll("/baz/qux", 0755) + afero.WriteFile(fs, "/foo/bar/LICENSE", []byte("MIT"), 0644) + afero.WriteFile(fs, "/LICENSE", []byte("Root"), 0644) + }, + expectedFiles: []string{}, + description: "Should return empty for completely disjoint paths", + }, + { + name: "empty stopAt rejected", + startDir: "/project/deep/path", + stopAt: "", + setupFS: func(fs afero.Fs) { + fs.MkdirAll("/project/deep/path", 0755) + }, + expectedError: true, + description: "Should reject empty stopAt string", + }, + { + name: "empty startDir rejected", + startDir: "", + stopAt: "/project", + setupFS: func(fs afero.Fs) { + fs.MkdirAll("/project", 0755) + }, + expectedError: true, + description: "Should reject empty startDir string", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Create in-memory filesystem + fs := afero.NewMemMapFs() + tt.setupFS(fs) + + // Run the function + result, err := findAllLicenseCandidatesUpwards(tt.startDir, licenseRegexp, tt.stopAt, fs) + + // Check error expectation + if tt.expectedError { + assert.Error(t, err, tt.description) + return + } + + require.NoError(t, err, tt.description) + assert.Equal(t, tt.expectedFiles, result, tt.description) + }) + } +} diff --git a/syft/pkg/cataloger/golang/parse_go_mod.go b/syft/pkg/cataloger/golang/parse_go_mod.go index a0440580ef4..16a17a0694f 100644 --- a/syft/pkg/cataloger/golang/parse_go_mod.go +++ b/syft/pkg/cataloger/golang/parse_go_mod.go @@ -4,20 +4,30 @@ import ( "bufio" "context" "fmt" + "go/build" "io" + "path/filepath" + "regexp" "sort" "strings" + "github.com/spf13/afero" "golang.org/x/mod/modfile" + "golang.org/x/tools/go/packages" "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/generic" ) +var ( + licenseRegexp = regexp.MustCompile(`^(?i)((UN)?LICEN(S|C)E|COPYING|NOTICE).*$`) +) + type goModCataloger struct { licenseResolver goLicenseResolver } @@ -28,59 +38,322 @@ func newGoModCataloger(opts CatalogerConfig) *goModCataloger { } } -// parseGoModFile takes a go.mod and lists all packages discovered. -// -//nolint:funlen +// parseGoModFile takes a go.mod and tries to resolve and lists all packages discovered. func (c *goModCataloger) parseGoModFile(ctx context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { - packages := make(map[string]pkg.Package) - - contents, err := io.ReadAll(reader) + modDir := filepath.Dir(string(reader.Location.Reference().RealPath)) + digests, err := parseGoSumFile(resolver, reader) if err != nil { - return nil, nil, fmt.Errorf("failed to read go module: %w", err) + log.Debugf("unable to get go.sum: %v", err) } - f, err := modfile.Parse(reader.RealPath, contents, nil) + // source analysis using go toolchain if available + syftSourcePackages, sourceModules, sourceDependencies, unknownErr := c.loadPackages(modDir, reader.Location) + catalogedModules, sourceModuleToPkg := c.catalogModules(ctx, syftSourcePackages, sourceModules, reader, digests) + relationships := buildModuleRelationships(catalogedModules, sourceDependencies, sourceModuleToPkg) + + // base case go.mod file parsing + modFile, err := c.parseModFileContents(reader) if err != nil { - return nil, nil, fmt.Errorf("failed to parse go module: %w", err) + return nil, nil, err } - digests, err := parseGoSumFile(resolver, reader) + // only use mod packages NOT found in source analysis + goModPackages := c.createGoModPackages(ctx, resolver, modFile, sourceModules, reader, digests) + c.applyReplaceDirectives(ctx, resolver, modFile, goModPackages, reader, digests) + c.applyExcludeDirectives(modFile, goModPackages) + + finalPkgs := c.assembleResults(catalogedModules, goModPackages) + return finalPkgs, relationships, unknownErr +} + +// loadPackages uses golang.org/x/tools/go/packages to get dependency information. +func (c *goModCataloger) loadPackages(modDir string, loc file.Location) (pkgs map[string][]pkgInfo, modules map[string]*packages.Module, dependencies map[string][]string, unknownErr error) { + cfg := &packages.Config{ + // Mode flags control what information is loaded for each package. + // Performance impact increases significantly with each additional flag: + // + // packages.NeedModule - Required for module metadata (path, version, replace directives). + // Essential for SBOM generation. Minimal performance impact. + // + // packages.NeedName - Required for package names & package Path. Minimal performance impact. + // Needed to identify packages and filter out standard library packages. + // + // packages.NeedFiles - Loads source file paths for each package. + // Moderate performance impact as it requires filesystem traversal. + // Required for license discovery. + // + // packages.NeedDeps - Loads the dependency graph between packages. + // High performance impact as it builds the complete import graph. + // Critical for generating accurate dependency relationships in SBOM. + // + // packages.NeedImports - Loads import information for each package. + // High performance impact, especially with large codebases. + // Required for building module-to-module dependency mappings. + // + // Adding flags like NeedTypes, NeedSyntax, or NeedTypesInfo would dramatically + // increase memory usage and processing time (10x+ slower) but are not needed + // for SBOM generation as we only require dependency and module metadata. + Mode: packages.NeedModule | packages.NeedName | packages.NeedFiles | packages.NeedDeps | packages.NeedImports, + Dir: modDir, + Tests: true, + } + + // From Go documentation: "all" expands to all packages in the main module + // and their dependencies, including dependencies needed by tests. + // + // The special pattern "all" specifies all the active modules, + // first the main module and then dependencies sorted by module path. + // A pattern containing "..." specifies the active modules whose module paths match the pattern. + // On implementation we could not find a test case that differentiated between all and ... + // There may be a case where ... is non inclusive so we default to all for the inclusive guarantee + rootPkgs, err := packages.Load(cfg, "all") if err != nil { - log.Debugf("unable to get go.sum: %v", err) + log.Debugf("error loading packages: %v", err) } - for _, m := range f.Require { - lics := c.licenseResolver.getLicenses(ctx, resolver, m.Mod.Path, m.Mod.Version) - packages[m.Mod.Path] = pkg.Package{ - Name: m.Mod.Path, - Version: m.Mod.Version, - Licenses: pkg.NewLicenseSet(lics...), + // Check for any errors in loading + for _, p := range rootPkgs { + if len(p.Errors) > 0 { + // Log errors but continue processing + for _, e := range p.Errors { + log.Debugf("package load error for %s: %v", p.PkgPath, e) + unknownErr = unknown.Append(unknownErr, loc, err) + } + } + } + + // note: dependencies have already pruned local imports and only focuses on module => module dependencies + return c.visitPackages(rootPkgs, loc, unknownErr) +} + +type pkgInfo struct { + // pkgPath is the import path of the package. + pkgPath string + // modulePath is the module path of the package. + modulePath string + // pkgDir is the directory containing the package's source code. + pkgDir string + // moduleDir is the directory containing the module's source code. + moduleDir string +} + +// visitPackages processes Go module import graphs to get all modules +func (c *goModCataloger) visitPackages( + rootPkgs []*packages.Package, + loc file.Location, + uke error, +) (pkgs map[string][]pkgInfo, modules map[string]*packages.Module, dependencies map[string][]string, unknownErr error) { + modules = make(map[string]*packages.Module) + // note: packages are specific to inside the module - they do not include transitive pkgInfo + // packages is used for identifying licensing documents for modules that could contain multiple licenses + // dependencies cover transitive module imports; see p.Imports array in packages.Visit + pkgs = make(map[string][]pkgInfo) + // dependencies are module => module dependencies + dependencies = make(map[string][]string) + // persist unknown errs from previous parts of the catalog + unknownErr = uke + // closure (p *Package) bool + // return bool determines whether the imports of package p are visited. + packages.Visit(rootPkgs, func(p *packages.Package) bool { + if len(p.Errors) > 0 { + for _, err := range p.Errors { + unknownErr = unknown.Append(unknownErr, loc, err) + } + return false + } + + // skip for common causes + if shouldSkipVisit(p) { + return false + } + + // different from above; we still might want to visit imports + // ignoring a package shouldn't end walking the tree + // since we need to get the full picture for license discovery + // for _, prefix := range c.config.IgnorePaths { + // if strings.HasPrefix(p.PkgPath, prefix) { + // return c.config.IncludeIgnoredDeps + // } + //} + pkgDir := resolvePkgDir(p) + if pkgDir == "" { + return true + } + + module := newModule(p.Module) + if module.Dir == "" { + // We continue processing even when module.Dir is empty because we still want to: + // 1. Extract module dependencies from p.Imports for dependency graph construction + // 2. Create syft packages with available metadata (name, version, etc.) + // 3. Build relationships between modules even without complete filesystem info + // Not having the DIR here just means that we're not going to process the licenses + + // Common causes for module.Dir being empty: + // - Vendored dependencies where Go toolchain loses some module metadata + // - Replace directives pointing to non-existent or inaccessible paths + // A known cause is that the module is vendored, so some information is lost. + isVendored := strings.Contains(pkgDir, "/vendor/") + if !isVendored { + log.Debugf("module %s does not have dir and it's not vendored", module.Path) + } + } + + // extract module dependencies + for _, imp := range p.Imports { + if imp.Module != nil && imp.Module.Path != module.Path { + if dependencies[module.Path] == nil { + dependencies[module.Path] = []string{imp.Module.Path} + } else { + dependencies[module.Path] = append(dependencies[module.Path], imp.Module.Path) + } + } + } + pkgs[module.Path] = append(pkgs[module.Path], pkgInfo{ + pkgPath: p.PkgPath, + modulePath: module.Path, + pkgDir: pkgDir, + moduleDir: module.Dir, + }) + modules[p.Module.Path] = module + + return true + }, nil) + return pkgs, modules, dependencies, unknownErr +} + +// create syft packages from Go modules found by the go toolchain +func (c *goModCataloger) catalogModules( + ctx context.Context, + pkgs map[string][]pkgInfo, + modules map[string]*packages.Module, + reader file.LocationReadCloser, + digests map[string]string, +) ([]pkg.Package, map[string]artifact.Identifiable) { + syftPackages := make([]pkg.Package, 0) + moduleToPackage := make(map[string]artifact.Identifiable) + + for _, m := range modules { + if isRelativeImportOrMain(m.Path) { + // relativeImport modules are already accounted for by their full module paths at other portions of syft's cataloging + // example: something like ../../ found as a module for go.mod b, which is sub to go.mod a is accounted for + // in another call to the goModCataloger when go.mod a is parsed + // local modules that use a "main" heuristic, no module naming (sometimes common pre go module support) + // are also not built as syft packages + continue + } + + pkgInfos := pkgs[m.Path] + moduleLicenses := resolveModuleLicenses(ctx, pkgInfos, afero.NewOsFs()) + // we do out of source lookups for module parsing + // locations are NOT included in the SBOM because of this + goModulePkg := pkg.Package{ + Name: m.Path, + Version: m.Version, Locations: file.NewLocationSet(reader.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), - PURL: packageURL(m.Mod.Path, m.Mod.Version), + Licenses: moduleLicenses, Language: pkg.Go, Type: pkg.GoModulePkg, - Metadata: pkg.GolangModuleEntry{ - H1Digest: digests[fmt.Sprintf("%s %s", m.Mod.Path, m.Mod.Version)], - }, + PURL: packageURL(m.Path, m.Version), + Metadata: createSourceMetadata(digests[fmt.Sprintf("%s %s", m.Path, m.Version)]), } + goModulePkg.SetID() + + moduleToPackage[m.Path] = goModulePkg + syftPackages = append(syftPackages, goModulePkg) } - // remove any old packages and replace with new ones... - for _, m := range f.Replace { - lics := c.licenseResolver.getLicenses(ctx, resolver, m.New.Path, m.New.Version) + return syftPackages, moduleToPackage +} + +// buildModuleRelationships creates artifact relationships between Go modules. +func buildModuleRelationships( + syftPkgs []pkg.Package, + dependencies map[string][]string, + moduleToPkg map[string]artifact.Identifiable, +) []artifact.Relationship { + var rels []artifact.Relationship + seen := make(map[string]struct{}) + + for _, fromPkg := range syftPkgs { + for _, dep := range dependencies[fromPkg.Name] { + if dep == fromPkg.Name { + continue + } + toPkg, ok := moduleToPkg[dep] + if !ok { + continue + } + + key := string(fromPkg.ID()) + string(toPkg.ID()) + if _, exists := seen[key]; exists { + continue + } + + rels = append(rels, artifact.Relationship{ + From: toPkg, // dep + To: fromPkg, // parent + Type: artifact.DependencyOfRelationship, + }) + seen[key] = struct{}{} + } + } + + return rels +} - // the old path and new path may be the same, in which case this is a noop, - // but if they're different we need to remove the old package. - // note that we may change the path but we should always reference the new version (since the old version - // cannot be trusted as a correct value). +func (c *goModCataloger) parseModFileContents(reader file.LocationReadCloser) (*modfile.File, error) { + contents, err := io.ReadAll(reader) + if err != nil { + return nil, fmt.Errorf("failed to read go module: %w", err) + } + + f, err := modfile.Parse(reader.RealPath, contents, nil) + if err != nil { + return nil, fmt.Errorf("failed to parse go module: %w", err) + } + + return f, nil +} + +// note this handles the deduplication from source by checking if the mod path exists in the sourceModules map +func (c *goModCataloger) createGoModPackages(ctx context.Context, resolver file.Resolver, modFile *modfile.File, sourceModules map[string]*packages.Module, reader file.LocationReadCloser, digests map[string]string) map[string]pkg.Package { + goModPackages := make(map[string]pkg.Package) + + for _, m := range modFile.Require { + if _, exists := sourceModules[m.Mod.Path]; !exists { + lics := c.licenseResolver.getLicenses(ctx, resolver, m.Mod.Path, m.Mod.Version) + goModPkg := pkg.Package{ + Name: m.Mod.Path, + Version: m.Mod.Version, + Licenses: pkg.NewLicenseSet(lics...), + Locations: file.NewLocationSet(reader.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + PURL: packageURL(m.Mod.Path, m.Mod.Version), + Language: pkg.Go, + Type: pkg.GoModulePkg, + Metadata: pkg.GolangModuleEntry{ + H1Digest: digests[fmt.Sprintf("%s %s", m.Mod.Path, m.Mod.Version)], + }, + } + goModPkg.SetID() + goModPackages[m.Mod.Path] = goModPkg + } + } + + return goModPackages +} + +// applyReplaceDirectives processes replace directives from go.mod +func (c *goModCataloger) applyReplaceDirectives(ctx context.Context, resolver file.Resolver, modFile *modfile.File, goModPackages map[string]pkg.Package, reader file.LocationReadCloser, digests map[string]string) { + for _, m := range modFile.Replace { + lics := c.licenseResolver.getLicenses(ctx, resolver, m.New.Path, m.New.Version) var finalPath string if !strings.HasPrefix(m.New.Path, ".") && !strings.HasPrefix(m.New.Path, "/") { finalPath = m.New.Path - delete(packages, m.Old.Path) + delete(goModPackages, m.Old.Path) } else { finalPath = m.Old.Path } - packages[finalPath] = pkg.Package{ + goModPkg := pkg.Package{ Name: finalPath, Version: m.New.Version, Licenses: pkg.NewLicenseSet(lics...), @@ -92,26 +365,31 @@ func (c *goModCataloger) parseGoModFile(ctx context.Context, resolver file.Resol H1Digest: digests[fmt.Sprintf("%s %s", finalPath, m.New.Version)], }, } + goModPkg.SetID() + goModPackages[finalPath] = goModPkg } +} - // remove any packages from the exclude fields - for _, m := range f.Exclude { - delete(packages, m.Mod.Path) +func (c *goModCataloger) applyExcludeDirectives(modFile *modfile.File, goModPackages map[string]pkg.Package) { + for _, m := range modFile.Exclude { + delete(goModPackages, m.Mod.Path) } +} + +func (c *goModCataloger) assembleResults(catalogedPkgs []pkg.Package, goModPackages map[string]pkg.Package) []pkg.Package { + pkgsSlice := make([]pkg.Package, 0) + + pkgsSlice = append(pkgsSlice, catalogedPkgs...) - pkgsSlice := make([]pkg.Package, len(packages)) - idx := 0 - for _, p := range packages { - p.SetID() - pkgsSlice[idx] = p - idx++ + for _, p := range goModPackages { + pkgsSlice = append(pkgsSlice, p) } sort.SliceStable(pkgsSlice, func(i, j int) bool { return pkgsSlice[i].Name < pkgsSlice[j].Name }) - return pkgsSlice, nil, nil + return pkgsSlice } func parseGoSumFile(resolver file.Resolver, reader file.LocationReadCloser) (map[string]string, error) { @@ -151,3 +429,94 @@ func parseGoSumFile(resolver file.Resolver, reader file.LocationReadCloser) (map return out, nil } + +// createSourceMetadata creates metadata for packages found through source analysis using build.Default +func createSourceMetadata(h1Digest string) pkg.GolangSourceEntry { + return pkg.GolangSourceEntry{ + H1Digest: h1Digest, + OperatingSystem: build.Default.GOOS, + Architecture: build.Default.GOARCH, + BuildTags: strings.Join(build.Default.BuildTags, ","), + CgoEnabled: build.Default.CgoEnabled, + } +} + +func resolvePkgDir(p *packages.Package) string { + switch { + case len(p.GoFiles) > 0: + return filepath.Dir(p.GoFiles[0]) + case len(p.CompiledGoFiles) > 0: + return filepath.Dir(p.CompiledGoFiles[0]) + case len(p.OtherFiles) > 0: + return filepath.Dir(p.OtherFiles[0]) + default: + return "" + } +} + +func shouldSkipVisit(p *packages.Package) bool { + // skip packages that don't have module info + if p.Module == nil { + return true + } + + // skip stdlib + if isStdLib(p) { + return true + } + + return false +} + +// isStdLib returns true if this package is part of the Go standard library. +func isStdLib(pkg *packages.Package) bool { + if pkg.Name == "unsafe" { + // Special case unsafe stdlib, because it does not contain go files. + return true + } + if len(pkg.GoFiles) == 0 { + return false + } + prefix := build.Default.GOROOT + sep := string(filepath.Separator) + if !strings.HasSuffix(prefix, sep) { + prefix += sep + } + return strings.HasPrefix(pkg.GoFiles[0], prefix) +} + +// handle replace directives +func newModule(mod *packages.Module) *packages.Module { + // Example of a module with replace directive: k8s.io/kubernetes => k8s.io/kubernetes v1.11.1 + // { + // "Path": "k8s.io/kubernetes", + // "Version": "v0.17.9", + // "Replace": { + // "Path": "k8s.io/kubernetes", + // "Version": "v1.11.1", + // "Time": "2018-07-17T04:20:29Z", + // "Dir": "/home/gongyuan_kubeflow_org/go/pkg/mod/k8s.io/kubernetes@v1.11.1", + // "GoMod": "/home/gongyuan_kubeflow_org/go/pkg/mod/cache/download/k8s.io/kubernetes/@v/v1.11.1.mod" + // }, + // "Dir": "/home/gongyuan_kubeflow_org/go/pkg/mod/k8s.io/kubernetes@v1.11.1", + // "GoMod": "/home/gongyuan_kubeflow_org/go/pkg/mod/cache/download/k8s.io/kubernetes/@v/v1.11.1.mod" + // } + // handle replace directives + // Note, we specifically want to replace version field. + // Haven't confirmed, but we may also need to override the + // entire struct when using replace directive with local folders. + tmp := *mod + if tmp.Replace != nil { + tmp = *tmp.Replace + } + + return &tmp +} + +func isRelativeImportOrMain(p string) bool { + if p == "main" { + return true + } + // true for ".", "..", "./...", "../..." + return build.IsLocalImport(p) +} diff --git a/syft/pkg/cataloger/golang/parse_go_mod_test.go b/syft/pkg/cataloger/golang/parse_go_mod_test.go index 9158773b0e7..77232133f92 100644 --- a/syft/pkg/cataloger/golang/parse_go_mod_test.go +++ b/syft/pkg/cataloger/golang/parse_go_mod_test.go @@ -1,8 +1,13 @@ package golang import ( + "path/filepath" "testing" + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" + + "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/internal/fileresolver" "github.com/anchore/syft/syft/pkg" @@ -15,13 +20,13 @@ func TestParseGoMod(t *testing.T) { expected []pkg.Package }{ { - fixture: "test-fixtures/one-package", + fixture: "test-fixtures/go-mod-fixtures/one-package/go.mod", expected: []pkg.Package{ { Name: "github.com/bmatcuk/doublestar", Version: "v1.3.1", PURL: "pkg:golang/github.com/bmatcuk/doublestar@v1.3.1", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/one-package")), + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/go-mod-fixtures/one-package/go.mod")), Language: pkg.Go, Type: pkg.GoModulePkg, Metadata: pkg.GolangModuleEntry{}, @@ -29,28 +34,28 @@ func TestParseGoMod(t *testing.T) { }, }, { - fixture: "test-fixtures/relative-replace", + fixture: "test-fixtures/go-mod-fixtures/relative-replace/go.mod", expected: []pkg.Package{ { Name: "github.com/aws/aws-sdk-go-v2", Version: "", PURL: "pkg:golang/github.com/aws/aws-sdk-go-v2", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/relative-replace")), Language: pkg.Go, Type: pkg.GoModulePkg, + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/go-mod-fixtures/relative-replace/go.mod")), Metadata: pkg.GolangModuleEntry{}, }, }, }, { - fixture: "test-fixtures/many-packages", + fixture: "test-fixtures/go-mod-fixtures/many-packages/go.mod", expected: []pkg.Package{ { Name: "github.com/anchore/archiver/v3", Version: "v3.5.2", PURL: "pkg:golang/github.com/anchore/archiver@v3.5.2#v3", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/go-mod-fixtures/many-packages/go.mod")), Language: pkg.Go, Type: pkg.GoModulePkg, Metadata: pkg.GolangModuleEntry{}, @@ -59,7 +64,7 @@ func TestParseGoMod(t *testing.T) { Name: "github.com/anchore/go-testutils", Version: "v0.0.0-20200624184116-66aa578126db", PURL: "pkg:golang/github.com/anchore/go-testutils@v0.0.0-20200624184116-66aa578126db", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/go-mod-fixtures/many-packages/go.mod")), Language: pkg.Go, Type: pkg.GoModulePkg, Metadata: pkg.GolangModuleEntry{}, @@ -68,7 +73,7 @@ func TestParseGoMod(t *testing.T) { Name: "github.com/anchore/go-version", Version: "v1.2.2-0.20200701162849-18adb9c92b9b", PURL: "pkg:golang/github.com/anchore/go-version@v1.2.2-0.20200701162849-18adb9c92b9b", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/go-mod-fixtures/many-packages/go.mod")), Language: pkg.Go, Type: pkg.GoModulePkg, Metadata: pkg.GolangModuleEntry{}, @@ -77,7 +82,7 @@ func TestParseGoMod(t *testing.T) { Name: "github.com/anchore/stereoscope", Version: "v0.0.0-20200706164556-7cf39d7f4639", PURL: "pkg:golang/github.com/anchore/stereoscope@v0.0.0-20200706164556-7cf39d7f4639", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/go-mod-fixtures/many-packages/go.mod")), Language: pkg.Go, Type: pkg.GoModulePkg, Metadata: pkg.GolangModuleEntry{}, @@ -86,7 +91,7 @@ func TestParseGoMod(t *testing.T) { Name: "github.com/bmatcuk/doublestar", Version: "v8.8.8", PURL: "pkg:golang/github.com/bmatcuk/doublestar@v8.8.8", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/go-mod-fixtures/many-packages/go.mod")), Language: pkg.Go, Type: pkg.GoModulePkg, Metadata: pkg.GolangModuleEntry{}, @@ -95,7 +100,7 @@ func TestParseGoMod(t *testing.T) { Name: "github.com/go-test/deep", Version: "v1.0.6", PURL: "pkg:golang/github.com/go-test/deep@v1.0.6", - Locations: file.NewLocationSet(file.NewLocation("test-fixtures/many-packages")), + Locations: file.NewLocationSet(file.NewLocation("test-fixtures/go-mod-fixtures/many-packages/go.mod")), Language: pkg.Go, Type: pkg.GoModulePkg, Metadata: pkg.GolangModuleEntry{}, @@ -179,3 +184,156 @@ func Test_corruptGoMod(t *testing.T) { WithError(). TestCataloger(t, c) } + +func Test_parseGoSource_packageResolution(t *testing.T) { + tests := []struct { + name string + fixturePath string + config CatalogerConfig + expectedPkgs []string + expectedRels []string + expectedLicenses map[string][]string + }{ + { + name: "go-source with direct, transitive, and deps of transitive", + fixturePath: filepath.Join("test-fixtures", "go-source"), + expectedPkgs: []string{ + "anchore.io/not/real @ (go.mod)", + "github.com/davecgh/go-spew @ v1.1.1 (go.mod)", + "github.com/go-viper/mapstructure/v2 @ v2.2.1 (go.mod)", + "github.com/google/uuid @ v1.6.0 (go.mod)", + "github.com/pmezard/go-difflib @ v1.0.0 (go.mod)", + "github.com/sagikazarmark/locafero @ v0.7.0 (go.mod)", + "github.com/sirupsen/logrus @ v1.9.3 (go.mod)", + "github.com/sourcegraph/conc @ v0.3.0 (go.mod)", + "github.com/spf13/afero @ v1.12.0 (go.mod)", + "github.com/spf13/cast @ v1.7.1 (go.mod)", + "github.com/spf13/pflag @ v1.0.6 (go.mod)", + "github.com/spf13/viper @ v1.20.1 (go.mod)", + "github.com/stretchr/testify @ v1.10.0 (go.mod)", + "github.com/subosito/gotenv @ v1.6.0 (go.mod)", + "go.uber.org/multierr @ v1.10.0 (go.mod)", + "go.uber.org/zap @ v1.27.0 (go.mod)", + "golang.org/x/sys @ v0.33.0 (go.mod)", + "golang.org/x/text @ v0.21.0 (go.mod)", + "gopkg.in/yaml.v3 @ v3.0.1 (go.mod)", + "github.com/fsnotify/fsnotify @ v1.8.0 (go.mod)", + "github.com/pelletier/go-toml/v2 @ v2.2.3 (go.mod)", + "github.com/frankban/quicktest @ v1.14.6 (go.mod)", + "github.com/google/go-cmp @ v0.6.0 (go.mod)", + "github.com/kr/pretty @ v0.3.1 (go.mod)", + "github.com/kr/text @ v0.2.0 (go.mod)", + "github.com/rogpeppe/go-internal @ v1.9.0 (go.mod)", + "go.uber.org/goleak @ v1.3.0 (go.mod)", + "gopkg.in/check.v1 @ v1.0.0-20190902080502-41f04d3bba15 (go.mod)", + }, + expectedRels: []string{ + "github.com/davecgh/go-spew @ v1.1.1 (go.mod) [dependency-of] github.com/stretchr/testify @ v1.10.0 (go.mod)", + "github.com/frankban/quicktest @ v1.14.6 (go.mod) [dependency-of] github.com/spf13/cast @ v1.7.1 (go.mod)", + "github.com/fsnotify/fsnotify @ v1.8.0 (go.mod) [dependency-of] github.com/spf13/viper @ v1.20.1 (go.mod)", + "github.com/go-viper/mapstructure/v2 @ v2.2.1 (go.mod) [dependency-of] github.com/spf13/viper @ v1.20.1 (go.mod)", + "github.com/google/go-cmp @ v0.6.0 (go.mod) [dependency-of] github.com/frankban/quicktest @ v1.14.6 (go.mod)", + "github.com/google/uuid @ v1.6.0 (go.mod) [dependency-of] anchore.io/not/real @ (go.mod)", + "github.com/kr/pretty @ v0.3.1 (go.mod) [dependency-of] github.com/frankban/quicktest @ v1.14.6 (go.mod)", + "github.com/kr/pretty @ v0.3.1 (go.mod) [dependency-of] gopkg.in/check.v1 @ v1.0.0-20190902080502-41f04d3bba15 (go.mod)", + "github.com/kr/text @ v0.2.0 (go.mod) [dependency-of] github.com/kr/pretty @ v0.3.1 (go.mod)", + "github.com/pelletier/go-toml/v2 @ v2.2.3 (go.mod) [dependency-of] github.com/spf13/viper @ v1.20.1 (go.mod)", + "github.com/pmezard/go-difflib @ v1.0.0 (go.mod) [dependency-of] github.com/stretchr/testify @ v1.10.0 (go.mod)", + "github.com/rogpeppe/go-internal @ v1.9.0 (go.mod) [dependency-of] github.com/kr/pretty @ v0.3.1 (go.mod)", + "github.com/sagikazarmark/locafero @ v0.7.0 (go.mod) [dependency-of] github.com/spf13/viper @ v1.20.1 (go.mod)", + "github.com/sirupsen/logrus @ v1.9.3 (go.mod) [dependency-of] anchore.io/not/real @ (go.mod)", + "github.com/sourcegraph/conc @ v0.3.0 (go.mod) [dependency-of] github.com/sagikazarmark/locafero @ v0.7.0 (go.mod)", + "github.com/spf13/afero @ v1.12.0 (go.mod) [dependency-of] github.com/sagikazarmark/locafero @ v0.7.0 (go.mod)", + "github.com/spf13/afero @ v1.12.0 (go.mod) [dependency-of] github.com/spf13/viper @ v1.20.1 (go.mod)", + "github.com/spf13/cast @ v1.7.1 (go.mod) [dependency-of] github.com/spf13/viper @ v1.20.1 (go.mod)", + "github.com/spf13/pflag @ v1.0.6 (go.mod) [dependency-of] github.com/spf13/viper @ v1.20.1 (go.mod)", + "github.com/spf13/viper @ v1.20.1 (go.mod) [dependency-of] anchore.io/not/real @ (go.mod)", + "github.com/stretchr/testify @ v1.10.0 (go.mod) [dependency-of] anchore.io/not/real @ (go.mod)", + "github.com/stretchr/testify @ v1.10.0 (go.mod) [dependency-of] github.com/pelletier/go-toml/v2 @ v2.2.3 (go.mod)", + "github.com/stretchr/testify @ v1.10.0 (go.mod) [dependency-of] github.com/sagikazarmark/locafero @ v0.7.0 (go.mod)", + "github.com/stretchr/testify @ v1.10.0 (go.mod) [dependency-of] github.com/sirupsen/logrus @ v1.9.3 (go.mod)", + "github.com/stretchr/testify @ v1.10.0 (go.mod) [dependency-of] github.com/sourcegraph/conc @ v0.3.0 (go.mod)", + "github.com/stretchr/testify @ v1.10.0 (go.mod) [dependency-of] github.com/spf13/viper @ v1.20.1 (go.mod)", + "github.com/stretchr/testify @ v1.10.0 (go.mod) [dependency-of] github.com/subosito/gotenv @ v1.6.0 (go.mod)", + "github.com/stretchr/testify @ v1.10.0 (go.mod) [dependency-of] go.uber.org/multierr @ v1.10.0 (go.mod)", + "github.com/stretchr/testify @ v1.10.0 (go.mod) [dependency-of] go.uber.org/zap @ v1.27.0 (go.mod)", + "github.com/subosito/gotenv @ v1.6.0 (go.mod) [dependency-of] github.com/spf13/viper @ v1.20.1 (go.mod)", + "go.uber.org/goleak @ v1.3.0 (go.mod) [dependency-of] go.uber.org/zap @ v1.27.0 (go.mod)", + "go.uber.org/multierr @ v1.10.0 (go.mod) [dependency-of] go.uber.org/zap @ v1.27.0 (go.mod)", + "go.uber.org/zap @ v1.27.0 (go.mod) [dependency-of] anchore.io/not/real @ (go.mod)", + "golang.org/x/sys @ v0.33.0 (go.mod) [dependency-of] github.com/fsnotify/fsnotify @ v1.8.0 (go.mod)", + "golang.org/x/sys @ v0.33.0 (go.mod) [dependency-of] github.com/sirupsen/logrus @ v1.9.3 (go.mod)", + "golang.org/x/text @ v0.21.0 (go.mod) [dependency-of] github.com/spf13/afero @ v1.12.0 (go.mod)", + "golang.org/x/text @ v0.21.0 (go.mod) [dependency-of] github.com/subosito/gotenv @ v1.6.0 (go.mod)", + "gopkg.in/check.v1 @ v1.0.0-20190902080502-41f04d3bba15 (go.mod) [dependency-of] gopkg.in/yaml.v3 @ v3.0.1 (go.mod)", + "gopkg.in/yaml.v3 @ v3.0.1 (go.mod) [dependency-of] github.com/spf13/viper @ v1.20.1 (go.mod)", + "gopkg.in/yaml.v3 @ v3.0.1 (go.mod) [dependency-of] github.com/stretchr/testify @ v1.10.0 (go.mod)", + "gopkg.in/yaml.v3 @ v3.0.1 (go.mod) [dependency-of] go.uber.org/zap @ v1.27.0 (go.mod)", + }, + expectedLicenses: map[string][]string{ + "github.com/fsnotify/fsnotify": {"BSD-3-Clause"}, + "github.com/go-viper/mapstructure/v2": {"MIT"}, + "github.com/google/uuid": {"BSD-3-Clause"}, + "github.com/pelletier/go-toml/v2": {"MIT"}, + "github.com/sagikazarmark/locafero": {"MIT"}, + "github.com/sirupsen/logrus": {"MIT"}, + "github.com/sourcegraph/conc": {"MIT"}, + "github.com/spf13/afero": {"Apache-2.0"}, + "github.com/spf13/cast": {"MIT"}, + "github.com/spf13/pflag": {"BSD-3-Clause"}, + "github.com/spf13/viper": {"MIT"}, + "github.com/subosito/gotenv": {"MIT"}, + "go.uber.org/multierr": {"MIT"}, + "go.uber.org/zap": {"MIT"}, + "golang.org/x/sys": {"BSD-3-Clause"}, + "golang.org/x/text": {"BSD-3-Clause"}, + "gopkg.in/yaml.v3": {"Apache-2.0", "MIT"}, + "github.com/davecgh/go-spew": {"ISC"}, + "github.com/pmezard/go-difflib": {"BSD-3-Clause"}, + "github.com/stretchr/testify": {"MIT"}, + "github.com/frankban/quicktest": {"MIT"}, + "github.com/google/go-cmp": {"BSD-3-Clause"}, + "github.com/kr/text": {"MIT"}, + "github.com/kr/pretty": {"MIT"}, + "github.com/rogpeppe/go-internal": {"BSD-3-Clause"}, + "go.uber.org/goleak": {"MIT"}, + "gopkg.in/check.v1": {"BSD-2-Clause"}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + pkgtest.NewCatalogTester(). + FromDirectory(t, tt.fixturePath). + ExpectsPackageStrings(tt.expectedPkgs). + ExpectsRelationshipStrings(tt.expectedRels). + ExpectsAssertion(func(t *testing.T, pkgs []pkg.Package, relationships []artifact.Relationship) { + for _, p := range pkgs { + if metadata, ok := p.Metadata.(pkg.GolangSourceEntry); ok { + // Validate that GolangSourceEntry metadata is present but don't assert on specific field values + // since these might vary across development machines + require.IsType(t, pkg.GolangSourceEntry{}, metadata, "expected GolangSourceEntry metadata for package %s", p.Name) + // Verify that the metadata struct is populated (non-zero values indicate go source method was used) + require.NotEmpty(t, metadata, "GolangSourceEntry metadata should not be empty for package %s", p.Name) + } + } + }). + ExpectsAssertion(func(t *testing.T, pkgs []pkg.Package, relationships []artifact.Relationship) { + actualLicenses := make(map[string][]string) + for _, p := range pkgs { + for _, l := range p.Licenses.ToSlice() { + if actualLicenses[p.Name] == nil { + actualLicenses[p.Name] = make([]string, 0) + } + actualLicenses[p.Name] = append(actualLicenses[p.Name], l.Value) + } + } + if diff := cmp.Diff(tt.expectedLicenses, actualLicenses); diff != "" { + t.Errorf("mismatch in licenses (-want +got):\n%s", diff) + } + }). + TestCataloger(t, NewGoModuleFileCataloger(CatalogerConfig{})) + }) + } +} diff --git a/syft/pkg/cataloger/golang/test-fixtures/many-packages b/syft/pkg/cataloger/golang/test-fixtures/go-mod-fixtures/many-packages/go.mod similarity index 100% rename from syft/pkg/cataloger/golang/test-fixtures/many-packages rename to syft/pkg/cataloger/golang/test-fixtures/go-mod-fixtures/many-packages/go.mod diff --git a/syft/pkg/cataloger/golang/test-fixtures/one-package b/syft/pkg/cataloger/golang/test-fixtures/go-mod-fixtures/one-package/go.mod similarity index 100% rename from syft/pkg/cataloger/golang/test-fixtures/one-package rename to syft/pkg/cataloger/golang/test-fixtures/go-mod-fixtures/one-package/go.mod diff --git a/syft/pkg/cataloger/golang/test-fixtures/go-mod-fixtures/one-package/go.sum b/syft/pkg/cataloger/golang/test-fixtures/go-mod-fixtures/one-package/go.sum new file mode 100644 index 00000000000..589ad126fc8 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/go-mod-fixtures/one-package/go.sum @@ -0,0 +1 @@ +github.com/bmatcuk/doublestar v1.3.1/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= diff --git a/syft/pkg/cataloger/golang/test-fixtures/relative-replace b/syft/pkg/cataloger/golang/test-fixtures/go-mod-fixtures/relative-replace/go.mod similarity index 100% rename from syft/pkg/cataloger/golang/test-fixtures/relative-replace rename to syft/pkg/cataloger/golang/test-fixtures/go-mod-fixtures/relative-replace/go.mod diff --git a/syft/pkg/cataloger/golang/test-fixtures/go-source/cmd/bin1/main.go b/syft/pkg/cataloger/golang/test-fixtures/go-source/cmd/bin1/main.go new file mode 100644 index 00000000000..a02799d5f16 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/go-source/cmd/bin1/main.go @@ -0,0 +1,11 @@ +package main + +import ( + "anchore.io/not/real/pk1" + "anchore.io/not/real/pk2" +) + +func main() { + pk1.Test() + pk2.Test() +} diff --git a/syft/pkg/cataloger/golang/test-fixtures/go-source/cmd/bin2/main.go b/syft/pkg/cataloger/golang/test-fixtures/go-source/cmd/bin2/main.go new file mode 100644 index 00000000000..d27f8462500 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/go-source/cmd/bin2/main.go @@ -0,0 +1,11 @@ +package main + +import ( + "anchore.io/not/real/pk1" + "anchore.io/not/real/pk3" +) + +func main() { + pk1.Test() + pk3.Zap() +} diff --git a/syft/pkg/cataloger/golang/test-fixtures/go-source/go.mod b/syft/pkg/cataloger/golang/test-fixtures/go-source/go.mod new file mode 100644 index 00000000000..6abaa1f6a67 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/go-source/go.mod @@ -0,0 +1,29 @@ +module anchore.io/not/real + +go 1.24.3 + +require ( + github.com/google/uuid v1.6.0 + github.com/sirupsen/logrus v1.9.3 + github.com/spf13/viper v1.20.1 + github.com/stretchr/testify v1.10.0 + go.uber.org/zap v1.27.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fsnotify/fsnotify v1.8.0 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/sagikazarmark/locafero v0.7.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.12.0 // indirect + github.com/spf13/cast v1.7.1 // indirect + github.com/spf13/pflag v1.0.6 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + go.uber.org/multierr v1.10.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/text v0.21.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/syft/pkg/cataloger/golang/test-fixtures/go-source/go.sum b/syft/pkg/cataloger/golang/test-fixtures/go-source/go.sum new file mode 100644 index 00000000000..cb724193580 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/go-source/go.sum @@ -0,0 +1,60 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= +github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +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/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= +github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= +github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= +github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= +github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +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= diff --git a/syft/pkg/cataloger/golang/test-fixtures/go-source/pk1/pk1.go b/syft/pkg/cataloger/golang/test-fixtures/go-source/pk1/pk1.go new file mode 100644 index 00000000000..9e16b67e5c5 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/go-source/pk1/pk1.go @@ -0,0 +1,17 @@ +package pk1 + +import ( + "github.com/google/uuid" + log "github.com/sirupsen/logrus" +) + +func Test() { + return +} + +func NewID() string { + log.WithFields(log.Fields{ + "animal": "walrus", + }).Info("A walrus appears") + return uuid.New().String() +} diff --git a/syft/pkg/cataloger/golang/test-fixtures/go-source/pk1/pk1_test.go b/syft/pkg/cataloger/golang/test-fixtures/go-source/pk1/pk1_test.go new file mode 100644 index 00000000000..f8d9570e6bd --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/go-source/pk1/pk1_test.go @@ -0,0 +1,12 @@ +package pk1 + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNewID(t *testing.T) { + id := NewID() + assert.NotEmpty(t, id) +} diff --git a/syft/pkg/cataloger/golang/test-fixtures/go-source/pk2/pk2.go b/syft/pkg/cataloger/golang/test-fixtures/go-source/pk2/pk2.go new file mode 100644 index 00000000000..a2853f23614 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/go-source/pk2/pk2.go @@ -0,0 +1,5 @@ +package pk2 + +func Test() { + return +} diff --git a/syft/pkg/cataloger/golang/test-fixtures/go-source/pk3/pk3.go b/syft/pkg/cataloger/golang/test-fixtures/go-source/pk3/pk3.go new file mode 100644 index 00000000000..6d811690f77 --- /dev/null +++ b/syft/pkg/cataloger/golang/test-fixtures/go-source/pk3/pk3.go @@ -0,0 +1,20 @@ +package pk3 + +import ( + "time" + + "github.com/spf13/viper" + "go.uber.org/zap" +) + +func Zap() { + sugar := zap.NewExample().Sugar() + defer sugar.Sync() + sugar.Infow("failed to fetch URL", + "url", "http://example.com", + "attempt", 3, + "backoff", time.Second, + ) + sugar.Infof("failed to fetch URL: %s", "http://example.com") + viper.SetDefault("ContentDir", "content") +} diff --git a/syft/pkg/cataloger/haskell/parse_stack_lock.go b/syft/pkg/cataloger/haskell/parse_stack_lock.go index f878594fe82..bc1de89e3a2 100644 --- a/syft/pkg/cataloger/haskell/parse_stack_lock.go +++ b/syft/pkg/cataloger/haskell/parse_stack_lock.go @@ -6,7 +6,7 @@ import ( "io" "strings" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/unknown" diff --git a/syft/pkg/cataloger/haskell/parse_stack_yaml.go b/syft/pkg/cataloger/haskell/parse_stack_yaml.go index 6791fb3b755..32aa129b55a 100644 --- a/syft/pkg/cataloger/haskell/parse_stack_yaml.go +++ b/syft/pkg/cataloger/haskell/parse_stack_yaml.go @@ -5,7 +5,7 @@ import ( "fmt" "io" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/unknown" diff --git a/syft/pkg/cataloger/internal/binutils/branching_matcher.go b/syft/pkg/cataloger/internal/binutils/branching_matcher.go new file mode 100644 index 00000000000..c18e433e179 --- /dev/null +++ b/syft/pkg/cataloger/internal/binutils/branching_matcher.go @@ -0,0 +1,51 @@ +package binutils + +import ( + "io" + + "github.com/anchore/syft/internal" + "github.com/anchore/syft/syft/internal/unionreader" + "github.com/anchore/syft/syft/pkg" +) + +// BranchingEvidenceMatcher loads the contents of the reader into memory, assuming that all +// classifier matchers are going to be reading the same file, e.g. a "java" binary, continuing to +// try classifier EvidenceMatcher until the first set of packages is found +func BranchingEvidenceMatcher(classifiers ...Classifier) EvidenceMatcher { + return func(_ Classifier, context MatcherContext) ([]pkg.Package, error) { + // we are scanning the same contents multiple times, so read it into memory for a reader that can reset + rdr, err := getReader(context) + if err != nil { + return nil, err + } + defer internal.CloseAndLogError(rdr, context.Location.RealPath) + if err != nil { + return nil, err + } + for _, c := range classifiers { + pkgs, err := c.EvidenceMatcher(c, MatcherContext{ + Resolver: context.Resolver, + Location: context.Location, + GetReader: func(_ MatcherContext) (unionreader.UnionReader, error) { + _, err := rdr.Seek(0, io.SeekStart) + if err != nil { + return nil, err + } + return &nonClosingUnionReader{rdr}, nil + }, + }) + if len(pkgs) > 0 || err != nil { + return pkgs, err + } + } + return nil, nil + } +} + +type nonClosingUnionReader struct { + unionreader.UnionReader +} + +func (c *nonClosingUnionReader) Close() error { + return nil +} diff --git a/syft/pkg/cataloger/internal/binutils/branching_matcher_test.go b/syft/pkg/cataloger/internal/binutils/branching_matcher_test.go new file mode 100644 index 00000000000..faf6a763349 --- /dev/null +++ b/syft/pkg/cataloger/internal/binutils/branching_matcher_test.go @@ -0,0 +1,95 @@ +package binutils + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/internal/unionreader" +) + +func Test_BranchingMatcher(t *testing.T) { + matchingTest := FileContentsVersionMatcher("", `my-verison:(?\d+\.\d+)`) + notMatchingTest := MatchPath("**/not-version*") + + tests := []struct { + name string + matcher EvidenceMatcher + expectedPackageNames []string + }{ + { + name: "not matching", + matcher: BranchingEvidenceMatcher( + Classifier{ + EvidenceMatcher: MatchAll( + notMatchingTest, + matchingTest, + ), + Package: "a-pkg", + }, + ), + expectedPackageNames: nil, + }, + { + name: "both match", + matcher: BranchingEvidenceMatcher( + Classifier{ + EvidenceMatcher: matchingTest, + Package: "a-pkg", + }, + Classifier{ + EvidenceMatcher: matchingTest, + Package: "b-pkg", + }, + ), + expectedPackageNames: []string{"a-pkg"}, + }, + { + name: "first-does-not-match", + matcher: BranchingEvidenceMatcher( + Classifier{ + EvidenceMatcher: MatchAll( + notMatchingTest, + matchingTest, + ), + Package: "b-pkg", + }, + Classifier{ + EvidenceMatcher: matchingTest, + Package: "c-pkg", + }, + ), + expectedPackageNames: []string{"c-pkg"}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + resolver := file.NewMockResolverForPaths("test-fixtures/version.txt", "test-fixtures/version-parts.txt") + locs, err := resolver.FilesByGlob("**/version.txt") + require.NoError(t, err) + require.Len(t, locs, 1) + loc := locs[0] + rdr, err := resolver.FileContentsByLocation(loc) + require.NoError(t, err) + urdr, err := unionreader.GetUnionReader(rdr) + require.NoError(t, err) + pkgs, err := test.matcher(Classifier{ + Package: "a-pkg", + }, MatcherContext{ + Resolver: resolver, + Location: loc, + GetReader: func(resolver MatcherContext) (unionreader.UnionReader, error) { + return urdr, nil + }, + }) + require.NoError(t, err) + var got []string + for i := range pkgs { + got = append(got, pkgs[i].Name) + } + require.EqualValues(t, test.expectedPackageNames, got) + }) + } +} diff --git a/syft/pkg/cataloger/internal/binutils/classifier.go b/syft/pkg/cataloger/internal/binutils/classifier.go index c48a657c6d2..e01ea966695 100644 --- a/syft/pkg/cataloger/internal/binutils/classifier.go +++ b/syft/pkg/cataloger/internal/binutils/classifier.go @@ -8,11 +8,14 @@ import ( "encoding/json" "fmt" "io" + "maps" "regexp" "strconv" "strings" "text/template" + "github.com/bmatcuk/doublestar/v4" + "github.com/anchore/packageurl-go" "github.com/anchore/syft/internal" "github.com/anchore/syft/internal/log" @@ -71,7 +74,8 @@ func (cfg Classifier) MarshalJSON() ([]byte, error) { return json.Marshal(m) } -// EvidenceMatcher is a function called to catalog Packages that match some sort of evidence +// EvidenceMatcher is a function called to identify based on some sort of evidence in the filesystem contents. +// A non-nil return value indicates a successful match, regardless of packages being returned. type EvidenceMatcher func(classifier Classifier, context MatcherContext) ([]pkg.Package, error) type MatcherContext struct { @@ -80,13 +84,16 @@ type MatcherContext struct { GetReader func(resolver MatcherContext) (unionreader.UnionReader, error) } -func EvidenceMatchers(matchers ...EvidenceMatcher) EvidenceMatcher { +// MatchAny returns a combined evidence matcher that returns results from the first +// matcher that returns results +func MatchAny(matchers ...EvidenceMatcher) EvidenceMatcher { return func(classifier Classifier, context MatcherContext) ([]pkg.Package, error) { for _, matcher := range matchers { match, err := matcher(classifier, context) if err != nil { return nil, err } + // only return when results if match != nil { return match, nil } @@ -95,6 +102,23 @@ func EvidenceMatchers(matchers ...EvidenceMatcher) EvidenceMatcher { } } +// MatchAll executes all matchers until one returns nil results, only returning the final results +func MatchAll(matchers ...EvidenceMatcher) EvidenceMatcher { + return func(classifier Classifier, context MatcherContext) ([]pkg.Package, error) { + var out []pkg.Package + for _, matcher := range matchers { + match, err := matcher(classifier, context) + if match == nil || err != nil { + return nil, err + } + if len(match) > 0 { + out = match + } + } + return out, nil + } +} + type ContextualEvidenceMatchers struct { CatalogerName string } @@ -103,8 +127,8 @@ func (c ContextualEvidenceMatchers) FileNameTemplateVersionMatcher(fileNamePatte return FileNameTemplateVersionMatcher(fileNamePattern, contentTemplate, c.CatalogerName) } -func (c ContextualEvidenceMatchers) FileContentsVersionMatcher(pattern string) EvidenceMatcher { - return FileContentsVersionMatcher(pattern, c.CatalogerName) +func (c ContextualEvidenceMatchers) FileContentsVersionMatcher(patterns ...string) EvidenceMatcher { + return FileContentsVersionMatcher(c.CatalogerName, patterns...) } func FileNameTemplateVersionMatcher(fileNamePattern, contentTemplate, catalogerName string) EvidenceMatcher { @@ -156,17 +180,36 @@ func FileNameTemplateVersionMatcher(fileNamePattern, contentTemplate, catalogerN } } -func FileContentsVersionMatcher(pattern, catalogerName string) EvidenceMatcher { - pat := regexp.MustCompile(pattern) +// FileContentsVersionMatcher will match all provided patterns, extracting named capture groups from each pattern, overwriting earlier results +func FileContentsVersionMatcher(catalogerName string, patterns ...string) EvidenceMatcher { + if len(patterns) == 0 { + panic("must specify at least one pattern") + } + var pats []*regexp.Regexp + for _, pattern := range patterns { + pats = append(pats, regexp.MustCompile(pattern)) + } return func(classifier Classifier, context MatcherContext) ([]pkg.Package, error) { - contents, err := getReader(context) - if err != nil { - return nil, fmt.Errorf("unable to get read contents for file: %w", err) - } + var matchMetadata map[string]string - matchMetadata, err := internal.MatchNamedCaptureGroupsFromReader(pat, contents) - if err != nil { - return nil, fmt.Errorf("unable to match version: %w", err) + for _, pat := range pats { + contents, err := getReader(context) + if err != nil { + return nil, fmt.Errorf("unable to get read contents for file: %w", err) + } + + match, err := internal.MatchNamedCaptureGroupsFromReader(pat, contents) + if err != nil { + return nil, fmt.Errorf("unable to match version: %w", err) + } + if match == nil { + return nil, nil + } + if matchMetadata == nil { + matchMetadata = match + } else { + maps.Copy(matchMetadata, match) + } } // Convert {major: 1, minor: 2, patch: 3} to "1.2.3" @@ -187,6 +230,10 @@ func FileContentsVersionMatcher(pattern, catalogerName string) EvidenceMatcher { p := NewClassifierPackage(classifier, context.Location, matchMetadata, catalogerName) if p == nil { + if matchMetadata != nil { + // if we had a successful metadata match, but no packages, return a successful match result + return []pkg.Package{}, nil + } return nil, nil } @@ -194,29 +241,6 @@ func FileContentsVersionMatcher(pattern, catalogerName string) EvidenceMatcher { } } -// MatchExcluding tests the provided regular expressions against the file, and if matched, DOES NOT return -// anything that the matcher would otherwise return -func MatchExcluding(matcher EvidenceMatcher, contentPatternsToExclude ...string) EvidenceMatcher { - var nonMatchPatterns []*regexp.Regexp - for _, p := range contentPatternsToExclude { - nonMatchPatterns = append(nonMatchPatterns, regexp.MustCompile(p)) - } - return func(classifier Classifier, context MatcherContext) ([]pkg.Package, error) { - contents, err := getReader(context) - if err != nil { - return nil, fmt.Errorf("unable to get read contents for file: %w", err) - } - matches, err := internal.MatchAnyFromReader(contents, nonMatchPatterns...) - if err != nil { - return nil, fmt.Errorf("unable to match content: %w", err) - } - if matches { - return nil, nil - } - return matcher(classifier, context) - } -} - func SharedLibraryLookup(sharedLibraryPattern string, sharedLibraryMatcher EvidenceMatcher) EvidenceMatcher { pat := regexp.MustCompile(sharedLibraryPattern) return func(classifier Classifier, context MatcherContext) (packages []pkg.Package, _ error) { @@ -234,16 +258,19 @@ func SharedLibraryLookup(sharedLibraryPattern string, sharedLibraryMatcher Evide return nil, err } for _, libraryLocation := range locations { + // create a new resolver without the cached context lookup -- this is decidedly a different file newResolver := MatcherContext{ - Resolver: context.Resolver, - Location: libraryLocation, - GetReader: context.GetReader, + Resolver: context.Resolver, + Location: libraryLocation, } - newResolver.Location = libraryLocation pkgs, err := sharedLibraryMatcher(classifier, newResolver) if err != nil { return nil, err } + // not a successful match + if pkgs == nil { + continue + } for _, p := range pkgs { // set the source binary as the first location locationSet := file.NewLocationSet(context.Location) @@ -260,12 +287,28 @@ func SharedLibraryLookup(sharedLibraryPattern string, sharedLibraryMatcher Evide } packages = append(packages, p) } + // return non-nil package results as a successful match indication if the evidence matcher returned a successful match indication + if packages == nil { + packages = pkgs + } } } return packages, nil } } +func MatchPath(path string) EvidenceMatcher { + if !doublestar.ValidatePattern(path) { + panic("invalid pattern") + } + return func(_ Classifier, context MatcherContext) ([]pkg.Package, error) { + if doublestar.MatchUnvalidated(path, context.Location.RealPath) { + return []pkg.Package{}, nil // return non-nil + } + return nil, nil + } +} + func getReader(context MatcherContext) (unionreader.UnionReader, error) { if context.GetReader != nil { return context.GetReader(context) diff --git a/syft/pkg/cataloger/internal/binutils/classifier_package.go b/syft/pkg/cataloger/internal/binutils/classifier_package.go index 897a88e979f..42831ddae71 100644 --- a/syft/pkg/cataloger/internal/binutils/classifier_package.go +++ b/syft/pkg/cataloger/internal/binutils/classifier_package.go @@ -1,9 +1,12 @@ package binutils import ( + "bytes" "reflect" + "text/template" "github.com/anchore/packageurl-go" + "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/cpe" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/pkg" @@ -21,8 +24,8 @@ func NewClassifierPackage(classifier Classifier, location file.Location, matchMe var cpes []cpe.CPE for _, c := range classifier.CPEs { - c.Attributes.Version = version - c.Attributes.Update = update + c.Attributes.Version = templatedUpdate(c.Attributes.Version, matchMetadata, version) + c.Attributes.Update = templatedUpdate(c.Attributes.Update, matchMetadata, update) cpes = append(cpes, c) } @@ -55,3 +58,28 @@ func NewClassifierPackage(classifier Classifier, location file.Location, matchMe return &p } + +func templatedUpdate(providedValue string, matchMetadata map[string]string, defaultValue string) string { + // if no template provided, just use the value directly + if providedValue == "" { + return defaultValue + } + // support templated updates + t, err := template.New("").Option("missingkey=zero").Parse(providedValue) + if err != nil { + log.Debugf("unable to parse classifier template=%q : %w", providedValue, err) + } else { + update := bytes.Buffer{} + err = t.Execute(&update, matchMetadata) + if err != nil { + log.Debugf("unable to render template: %w", err) + } else { + // only use the template result if it's non-empty + providedValue = update.String() + if providedValue != "" { + return providedValue + } + } + } + return defaultValue +} diff --git a/syft/pkg/cataloger/internal/binutils/classifier_test.go b/syft/pkg/cataloger/internal/binutils/classifier_test.go index 0cfb0f9a4f3..e0497957d7c 100644 --- a/syft/pkg/cataloger/internal/binutils/classifier_test.go +++ b/syft/pkg/cataloger/internal/binutils/classifier_test.go @@ -27,7 +27,7 @@ func Test_ClassifierCPEs(t *testing.T) { classifier: Classifier{ Package: "some-app", FileGlob: "**/version.txt", - EvidenceMatcher: FileContentsVersionMatcher(`(?m)my-verison:(?P[0-9.]+)`, "cataloger-name"), + EvidenceMatcher: FileContentsVersionMatcher("cataloger-name", `(?m)my-verison:(?P[0-9.]+)`), CPEs: []cpe.CPE{}, }, cpes: nil, @@ -38,7 +38,7 @@ func Test_ClassifierCPEs(t *testing.T) { classifier: Classifier{ Package: "some-app", FileGlob: "**/version.txt", - EvidenceMatcher: FileContentsVersionMatcher(`(?m)my-verison:(?P[0-9.]+)`, "cataloger-name"), + EvidenceMatcher: FileContentsVersionMatcher("cataloger-name", `(?m)my-verison:(?P[0-9.]+)`), CPEs: []cpe.CPE{ cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*", cpe.GeneratedSource), }, @@ -53,7 +53,7 @@ func Test_ClassifierCPEs(t *testing.T) { classifier: Classifier{ Package: "some-app", FileGlob: "**/version.txt", - EvidenceMatcher: FileContentsVersionMatcher(`(?m)my-verison:(?P[0-9.]+)`, "cataloger-name"), + EvidenceMatcher: FileContentsVersionMatcher("cataloger-name", `(?m)my-verison:(?P[0-9.]+)`), CPEs: []cpe.CPE{ cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*", cpe.GeneratedSource), cpe.Must("cpe:2.3:a:some:apps:*:*:*:*:*:*:*:*", cpe.GeneratedSource), @@ -70,7 +70,7 @@ func Test_ClassifierCPEs(t *testing.T) { classifier: Classifier{ Package: "some-app", FileGlob: "**/version-parts.txt", - EvidenceMatcher: FileContentsVersionMatcher(`(?m)\x00(?P[0-9.]+)\x00(?P[0-9.]+)\x00(?P[0-9.]+)\x00`, "cataloger-name"), + EvidenceMatcher: FileContentsVersionMatcher("cataloger-name", `(?m)\x00(?P[0-9.]+)\x00(?P[0-9.]+)\x00(?P[0-9.]+)\x00`), CPEs: []cpe.CPE{}, }, cpes: nil, @@ -113,7 +113,7 @@ func TestClassifier_MarshalJSON(t *testing.T) { classifier: Classifier{ Class: "class", FileGlob: "glob", - EvidenceMatcher: FileContentsVersionMatcher(".thing", "cataloger-name"), + EvidenceMatcher: FileContentsVersionMatcher("cataloger-name", ".thing"), Package: "pkg", PURL: packageurl.PackageURL{ Type: "type", @@ -168,7 +168,7 @@ func TestFileContentsVersionMatcher(t *testing.T) { mockGetContent := func(context MatcherContext) (unionreader.UnionReader, error) { return unionreader.GetUnionReader(io.NopCloser(bytes.NewBufferString(tt.data))) } - fn := FileContentsVersionMatcher(tt.pattern, "cataloger-name") + fn := FileContentsVersionMatcher("cataloger-name", tt.pattern) p, err := fn(Classifier{}, MatcherContext{ GetReader: mockGetContent, }) diff --git a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json index 1a4ac771fb4..3091c043dec 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json +++ b/syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json @@ -61,6 +61,9 @@ "github.com/gofiber/template/django/v3": [ "cpe:2.3:a:gofiber:django:*:*:*:*:*:go:*:*" ], + "github.com/google/nftables": [ + "cpe:2.3:a:google:nftables:*:*:*:*:*:go:*:*" + ], "github.com/gookit/goutil": [ "cpe:2.3:a:go_util_project:go_util:*:*:*:*:*:go:*:*" ], @@ -161,6 +164,9 @@ ] }, "jenkins_plugins": { + "ApicaLoadtest": [ + "cpe:2.3:a:jenkins:apica_loadtest:*:*:*:*:*:jenkins:*:*" + ], "DotCi": [ "cpe:2.3:a:jenkins:dotci:*:*:*:*:*:jenkins:*:*" ], @@ -226,6 +232,9 @@ "applatix": [ "cpe:2.3:a:jenkins:applatix:*:*:*:*:*:jenkins:*:*" ], + "applitools-eyes": [ + "cpe:2.3:a:jenkins:applitools_eyes:*:*:*:*:*:jenkins:*:*" + ], "apprenda": [ "cpe:2.3:a:jenkins:apprenda:*:*:*:*:*:jenkins:*:*" ], @@ -699,7 +708,11 @@ "cpe:2.3:a:jenkins:dingding_json_pusher:*:*:*:*:*:jenkins:*:*" ], "dingding-notifications": [ - "cpe:2.3:a:jenkins:dingding:*:*:*:*:*:jenkins:*:*" + "cpe:2.3:a:jenkins:dingding:*:*:*:*:*:jenkins:*:*", + "cpe:2.3:a:jenkins:dingtalk:*:*:*:*:*:jenkins:*:*" + ], + "dingtalk": [ + "cpe:2.3:a:jenkins:dingtalk:*:*:*:*:*:jenkins:*:*" ], "distfork": [ "cpe:2.3:a:jenkins:distributed_fork:*:*:*:*:*:jenkins:*:*" @@ -1022,9 +1035,15 @@ "ibm-asoc": [ "cpe:2.3:a:jenkins:ibm_application_security_on_cloud:*:*:*:*:*:jenkins:*:*" ], + "ibm-cloud-devops": [ + "cpe:2.3:a:jenkins:ibm_cloud_devops:*:*:*:*:*:jenkins:*:*" + ], "icescrum": [ "cpe:2.3:a:jenkins:icescrum:*:*:*:*:*:jenkins:*:*" ], + "ifttt-build-notifier": [ + "cpe:2.3:a:jenkins:ifttt_build_notifier:*:*:*:*:*:jenkins:*:*" + ], "image-gallery": [ "cpe:2.3:a:jenkins:image_gallery:*:*:*:*:*:jenkins:*:*" ], @@ -1326,6 +1345,9 @@ "nomad": [ "cpe:2.3:a:jenkins:nomad:*:*:*:*:*:jenkins:*:*" ], + "nouvola-divecloud": [ + "cpe:2.3:a:jenkins:nouvola_divecloud:*:*:*:*:*:jenkins:*:*" + ], "nuget": [ "cpe:2.3:a:jenkins:nuget:*:*:*:*:*:jenkins:*:*" ], @@ -1500,6 +1522,9 @@ "pwauth": [ "cpe:2.3:a:jenkins:pwauth_security_realm:*:*:*:*:*:jenkins:*:*" ], + "qmetry-test-management": [ + "cpe:2.3:a:jenkins:qmetry_test_management:*:*:*:*:*:jenkins:*:*" + ], "quality-gates": [ "cpe:2.3:a:jenkins:quality_gates:*:*:*:*:*:jenkins:*:*" ], @@ -1718,6 +1743,7 @@ "cpe:2.3:a:jenkins:amazon_sns_build_notifier:*:*:*:*:*:jenkins:*:*" ], "soapui-pro-functional-testing": [ + "cpe:2.3:a:jenkins:readyapi_functional_testing:*:*:*:*:*:jenkins:*:*", "cpe:2.3:a:jenkins:soapui_pro_functional_testing:*:*:*:*:*:jenkins:*:*" ], "sofy-ai": [ @@ -1774,6 +1800,9 @@ "starteam": [ "cpe:2.3:a:jenkins:starteam:*:*:*:*:*:jenkins:*:*" ], + "statistics-gatherer": [ + "cpe:2.3:a:jenkins:statistics_gatherer:*:*:*:*:*:jenkins:*:*" + ], "storable-configs": [ "cpe:2.3:a:jenkins:storable_configs:*:*:*:*:*:jenkins:*:*" ], @@ -1842,6 +1871,9 @@ "testquality-updater": [ "cpe:2.3:a:jenkins:testquality_updater:*:*:*:*:*:jenkins:*:*" ], + "testsigma": [ + "cpe:2.3:a:jenkins:testsigma_test_plan_run:*:*:*:*:*:jenkins:*:*" + ], "tfs": [ "cpe:2.3:a:jenkins:team_foundation_server:*:*:*:*:*:jenkins:*:*" ], @@ -1896,6 +1928,9 @@ "usemango-runner": [ "cpe:2.3:a:jenkins:usemango_runner:*:*:*:*:*:jenkins:*:*" ], + "vaddy-plugin": [ + "cpe:2.3:a:jenkins:vaddy:*:*:*:*:*:jenkins:*:*" + ], "valgrind": [ "cpe:2.3:a:jenkins:valgrind:*:*:*:*:*:jenkins:*:*" ], @@ -2325,6 +2360,9 @@ "@zxcvbn-ts/core": [ "cpe:2.3:a:zxcvbn-ts_project:zxcvbn-ts:*:*:*:*:*:node.js:*:*" ], + "ContentTools": [ + "cpe:2.3:a:getme:contenttools:*:*:*:*:*:node.js:*:*" + ], "Proto": [ "cpe:2.3:a:proto_project:proto:*:*:*:*:*:node.js:*:*" ], @@ -4547,6 +4585,9 @@ "plupload": [ "cpe:2.3:a:tiny:plupload:*:*:*:*:*:node.js:*:*" ], + "pm2": [ + "cpe:2.3:a:keymetric:pm2:*:*:*:*:*:node.js:*:*" + ], "pm2-kafka": [ "cpe:2.3:a:pm2-kafka_project:pm2-kafka:*:*:*:*:*:node.js:*:*" ], @@ -5526,6 +5567,9 @@ "mustache/mustache": [ "cpe:2.3:a:mustache_project:mustache:*:*:*:*:*:php:*:*" ], + "nitsan/ns-backup": [ + "cpe:2.3:a:nitsantech:ns-backup:*:*:*:*:*:typo3:*:*" + ], "phpfastcache/phpfastcache": [ "cpe:2.3:a:phpfastcache:phpfastcache:*:*:*:*:*:*:*:*" ], @@ -5875,6 +5919,9 @@ "pretix": [ "cpe:2.3:a:rami:pretix:*:*:*:*:*:*:*:*" ], + "promptflow-tools": [ + "cpe:2.3:a:microsoft:azure_promptflow_tools:*:*:*:*:*:*:*:*" + ], "protobuf": [ "cpe:2.3:a:google:protobuf-python:*:*:*:*:*:*:*:*" ], @@ -5902,6 +5949,9 @@ "pybluemonday": [ "cpe:2.3:a:python:pybluemonday:*:*:*:*:*:*:*:*" ], + "pycel": [ + "cpe:2.3:a:dgorissen:pycel:*:*:*:*:*:python:*:*" + ], "pycryptodome": [ "cpe:2.3:a:pycryptodome:pycryptodome:*:*:*:*:*:python:*:*" ], @@ -5935,6 +5985,9 @@ "python-gnupg": [ "cpe:2.3:a:python:python-gnupg:*:*:*:*:*:*:*:*" ], + "python-json-logger": [ + "cpe:2.3:a:nhairs:python_json_logger:*:*:*:*:*:*:*:*" + ], "python-jwt": [ "cpe:2.3:a:python-jwt_project:python-jwt:*:*:*:*:*:*:*:*" ], @@ -6625,6 +6678,9 @@ "beef": [ "cpe:2.3:a:beef_project:beef:*:*:*:*:*:rust:*:*" ], + "below": [ + "cpe:2.3:a:facebook:below:*:*:*:*:*:rust:*:*" + ], "bigint": [ "cpe:2.3:a:bigint_project:bigint:*:*:*:*:*:rust:*:*" ], @@ -6778,6 +6834,9 @@ "id-map": [ "cpe:2.3:a:id-map_project:id-map:*:*:*:*:*:rust:*:*" ], + "idna": [ + "cpe:2.3:a:servo:idna:*:*:*:*:*:rust:*:*" + ], "insert_many": [ "cpe:2.3:a:insert_many_project:insert_many:*:*:*:*:*:rust:*:*" ], @@ -7343,6 +7402,9 @@ "activedemand": [ "cpe:2.3:a:jumpdemand:activedemand:*:*:*:*:*:wordpress:*:*" ], + "activity-link-preview-for-buddypress": [ + "cpe:2.3:a:wbcomdesigns:activity_link_preview_for_buddypress:*:*:*:*:*:wordpress:*:*" + ], "activity-reactions-for-buddypress": [ "cpe:2.3:a:areteit:activity_reactions_for_buddypress:*:*:*:*:*:wordpress:*:*" ], @@ -7429,6 +7491,9 @@ "add-to-calendar-button": [ "cpe:2.3:a:add-to-calendar-button-pro:add_to_calendar_button:*:*:*:*:*:wordpress:*:*" ], + "add-to-cart-button-labels-for-woocommerce": [ + "cpe:2.3:a:wpfactory:change_add_to_cart_button_text_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "add-to-cart-direct-checkout-for-woocommerce": [ "cpe:2.3:a:piwebsolution:add-to-cart-direct-checkout-for-woocommerce:*:*:*:*:*:wordpress:*:*" ], @@ -7446,6 +7511,9 @@ "cpe:2.3:a:livemesh:elementor_addons:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:livemeshelementor:addons_for_elementor:*:*:*:*:*:wordpress:*:*" ], + "addons-for-visual-composer": [ + "cpe:2.3:a:livemeshthemes:wpbakery_page_builder_addons:*:*:*:*:-:wordpress:*:*" + ], "addthis": [ "cpe:2.3:a:addthis:addthis:*:*:*:*:*:wordpress:*:*" ], @@ -7842,6 +7910,9 @@ "amo-team-showcase": [ "cpe:2.3:a:amothemo:amo_team_showcase:*:*:*:*:*:wordpress:*:*" ], + "amount-left-free-shipping-woocommerce": [ + "cpe:2.3:a:wpfactory:free_shipping_bar:*:*:*:*:free:wordpress:*:*" + ], "amp-img-shortcode": [ "cpe:2.3:a:wpza:amp_img_shortcode:*:*:*:*:*:wordpress:*:*" ], @@ -7909,7 +7980,7 @@ "cpe:2.3:a:aakashweb:announcer:*:*:*:*:*:wordpress:*:*" ], "anonymous-restricted-content": [ - "cpe:2.3:a:tarassych:anonymous_restricted_content:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:cayenne:anonymous_restricted_content:*:*:*:*:*:wordpress:*:*" ], "another-wordpress-classifieds-plugin": [ "cpe:2.3:a:strategy11:awp_classifieds:*:*:*:*:*:wordpress:*:*" @@ -8242,6 +8313,9 @@ "awsm-team": [ "cpe:2.3:a:awsm:awsm_team:*:*:*:*:free:wordpress:*:*" ], + "axle-demo-importer": [ + "cpe:2.3:a:axlethemes:axle_demo_importer:*:*:*:*:*:wordpress:*:*" + ], "ays-chatgpt-assistant": [ "cpe:2.3:a:ays-pro:chatgpt_assistant:*:*:*:*:free:wordpress:*:*" ], @@ -8253,6 +8327,9 @@ "cpe:2.3:a:ays-pro:popup_box:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:ays-pro:popup_box:*:*:*:*:pro:wordpress:*:*" ], + "azan": [ + "cpe:2.3:a:wp-master:azan:*:*:*:*:*:wordpress:*:*" + ], "azindex": [ "cpe:2.3:a:azindex_project:azindex:*:*:*:*:*:wordpress:*:*" ], @@ -8350,6 +8427,9 @@ "cpe:2.3:a:brainstormforce:cards_for_beaver_builder:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:ultimateaddons:cards_for_beaver_builder:*:*:*:*:*:wordpress:*:*" ], + "bb-plugin": [ + "cpe:2.3:a:fastlinemedia:beaver_builder:*:*:*:*:lite:wordpress:*:*" + ], "bbp-core": [ "cpe:2.3:a:spider-themes:bbp_core:*:*:*:*:*:wordpress:*:*" ], @@ -8412,6 +8492,9 @@ "bee-layer-slider": [ "cpe:2.3:a:aumsrini:bee_layer_slider:*:*:*:*:-:wordpress:*:*" ], + "beeteam368-extensions": [ + "cpe:2.3:a:beeteam368:vidmov:*:*:*:*:*:wordpress:*:*" + ], "before-after-image-slider": [ "cpe:2.3:a:swadeshswain:before_after_image_slider:*:*:*:*:*:wordpress:*:*" ], @@ -8723,6 +8806,9 @@ "cpe:2.3:a:brizy:brizy:*:*:*:*:free:wordpress:*:*", "cpe:2.3:a:brizy:brizy:*:*:*:*:pro:wordpress:*:*" ], + "broadstreet": [ + "cpe:2.3:a:broadstreetads:broadstreet:*:*:*:*:*:wordpress:*:*" + ], "broken-link-checker": [ "cpe:2.3:a:managewp:broken_link_checker:*:*:*:*:*:wordpress:*:*" ], @@ -8733,6 +8819,9 @@ "cpe:2.3:a:broken_link_manager_project:broken_link_manager:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:k-78:broken_link_manager:*:*:*:*:*:wordpress:*:*" ], + "broken-link-notifier": [ + "cpe:2.3:a:pluginrx:broken_link_notifier:*:*:*:*:*:wordpress:*:*" + ], "browser-shots": [ "cpe:2.3:a:prothemedesign:browser_screenshots:*:*:*:*:*:wordpress:*:*" ], @@ -8775,6 +8864,9 @@ "buddypress-activity-plus": [ "cpe:2.3:a:incsub:buddypress-activity-plus:*:*:*:*:*:wordpress:*:*" ], + "buddypress-docs": [ + "cpe:2.3:a:boonebgorges:buddypress_docs:*:*:*:*:*:wordpress:*:*" + ], "buddypress-global-search": [ "cpe:2.3:a:buddyboss:buddypress_global_search:*:*:*:*:*:wordpress:*:*" ], @@ -8839,6 +8931,9 @@ "business-manager": [ "cpe:2.3:a:linksoftwarellc:business_manager:*:*:*:*:*:wordpress:*:*" ], + "business-reviews-wp": [ + "cpe:2.3:a:radiustheme:widget_for_google_reviews:*:*:*:*:*:wordpress:*:*" + ], "button-block": [ "cpe:2.3:a:bplugins:button_block:*:*:*:*:*:wordpress:*:*" ], @@ -9164,6 +9259,7 @@ "cpe:2.3:a:change_wp-admin_login_project:change_wp-admin_login:*:*:*:*:*:wordpress:*:*" ], "charitable": [ + "cpe:2.3:a:wpbeginner:charitable:*:*:*:*:-:wordpress:*:*", "cpe:2.3:a:wpcharitable:charitable:*:*:*:*:*:wordpress:*:*" ], "charity-addon-for-elementor": [ @@ -9250,6 +9346,9 @@ "cpe:2.3:a:cleantalk:anti-spam:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:cleantalk:spam_protection\\,_antispam\\,_firewall:*:*:*:*:*:wordpress:*:*" ], + "clearfy": [ + "cpe:2.3:a:cm-wp:clearfy:*:*:*:*:*:wordpress:*:*" + ], "clerkio": [ "cpe:2.3:a:clerk:clerk.io:*:*:*:*:*:wordpress:*:*" ], @@ -9520,6 +9619,9 @@ "contact-form-7-datepicker": [ "cpe:2.3:a:contact-form-7-datepicker_project:contact-form-7-datepicker:*:*:*:*:*:wordpress:*:*" ], + "contact-form-7-dynamic-text-extension": [ + "cpe:2.3:a:sevenspark:contact_form_7_-_dynamic_text_extension:*:*:*:*:*:wordpress:*:*" + ], "contact-form-7-integrations": [ "cpe:2.3:a:contactus:contact_form_7_integrations:*:*:*:*:*:wordpress:*:*" ], @@ -10017,7 +10119,8 @@ "cpe:2.3:a:custom_dashboard_widgets_project:custom_dashboard_widgets:*:*:*:*:*:wordpress:*:*" ], "custom-facebook-feed": [ - "cpe:2.3:a:smashballoon:smash_balloon_social_post_feed:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:smashballoon:smash_balloon_social_post_feed:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpbeginner:smash_balloon_social_post_feed:*:*:*:*:*:wordpress:*:*" ], "custom-field-for-wp-job-manager": [ "cpe:2.3:a:custom_field_for_wp_job_manager_project:custom_field_for_wp_job_manager:*:*:*:*:*:wordpress:*:*" @@ -10465,6 +10568,9 @@ "drawblog": [ "cpe:2.3:a:drawblog_project:drawblog:*:*:*:*:*:wordpress:*:*" ], + "drive-folder-embeder": [ + "cpe:2.3:a:azumbro:drive_folder_embedder:*:*:*:*:*:wordpress:*:*" + ], "droit-dark-mode": [ "cpe:2.3:a:droitthemes:droit_dark_mode:*:*:*:*:*:wordpress:*:*" ], @@ -10840,15 +10946,19 @@ "cpe:2.3:a:elementor:elementor_page_builder:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:elementor:elementor_page_builder:*:*:*:*:pro:wordpress:*:*", "cpe:2.3:a:elementor:page_builder:*:*:*:*:*:wordpress:*:*", - "cpe:2.3:a:elementor:website_builder:*:*:*:*:free:wordpress:*:*" + "cpe:2.3:a:elementor:website_builder:*:*:*:*:free:wordpress:*:*", + "cpe:2.3:a:elementor:website_builder:*:*:*:*:pro:wordpress:*:*" ], "elementor-pro": [ - "cpe:2.3:a:elementor:elementor_pro:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:elementor:elementor_page_builder:*:*:*:*:pro:wordpress:*:*", + "cpe:2.3:a:elementor:elementor_pro:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:elementor:website_builder:*:*:*:*:pro:wordpress:*:*" ], "elementskit": [ "cpe:2.3:a:wpmet:elementskit:*:*:*:*:pro:wordpress:*:*" ], "elementskit-lite": [ + "cpe:2.3:a:plugin-devs:post_carousel_slider_for_elementor:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:wpmet:elements_kit_elementor_addons:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:wpmet:elementskit_elementor_addons:*:*:*:*:*:wordpress:*:*" ], @@ -10858,6 +10968,9 @@ "elex-helpdesk-customer-support-ticket-system": [ "cpe:2.3:a:elula:wsdesk:*:*:*:*:free:wordpress:*:*" ], + "elisqlreports": [ + "cpe:2.3:a:ieonly:ez_sql_reports_shortcode_widget_and_db_backup:*:*:*:*:*:wordpress:*:*" + ], "elo-rating-shortcode": [ "cpe:2.3:a:timelord:elo_rating_shortcode:*:*:*:*:*:wordpress:*:*" ], @@ -10967,6 +11080,7 @@ "cpe:2.3:a:inisev:enhanced_text_widget:*:*:*:*:*:wordpress:*:*" ], "enhanced-tooltipglossary": [ + "cpe:2.3:a:cminds:cm_tooltip_glossary:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:cminds:tooltip_glossary:*:*:*:*:*:wordpress:*:*" ], "enqueue-anything": [ @@ -11584,6 +11698,9 @@ "fontsy": [ "cpe:2.3:a:fontsy_project:fontsy:*:*:*:*:*:wordpress:*:*" ], + "foobox-image-lightbox": [ + "cpe:2.3:a:fooplugins:foobox:*:*:*:*:*:wordpress:*:*" + ], "food-and-drink-menu": [ "cpe:2.3:a:fivestarplugins:five_star_restaurant_menu:*:*:*:*:*:wordpress:*:*" ], @@ -11600,7 +11717,7 @@ "cpe:2.3:a:anwp:football_leagues:*:*:*:*:premium:wordpress:*:*" ], "football-pool": [ - "cpe:2.3:a:football_pool_project:football_pool:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:antoineh:football_pool:*:*:*:*:*:wordpress:*:*" ], "footer-putter": [ "cpe:2.3:a:diywebmastery:footer_putter:*:*:*:*:*:wordpress:*:*" @@ -11725,6 +11842,9 @@ "frontier-post": [ "cpe:2.3:a:wpfrontier:frontier_post:*:*:*:*:*:wordpress:*:*" ], + "fs-product-inquiry": [ + "cpe:2.3:a:fudugo:fs_product_inquiry:*:*:*:*:*:wordpress:*:*" + ], "fs-shopping-cart": [ "cpe:2.3:a:firestormplugins:fs-shopping-cart:*:*:*:*:*:wordpress:*:*" ], @@ -11755,6 +11875,9 @@ "furikake": [ "cpe:2.3:a:furikake_project:furikake:*:*:*:*:*:wordpress:*:*" ], + "fusedesk": [ + "cpe:2.3:a:jeremyshapiro:fusedesk:*:*:*:*:*:wordpress:*:*" + ], "fusion-builder": [ "cpe:2.3:a:theme-fusion:avada:*:*:*:*:*:wordpress:*:*" ], @@ -11983,6 +12106,9 @@ "glossary-by-codeat": [ "cpe:2.3:a:codeat:glossary:*:*:*:*:*:wordpress:*:*" ], + "glossy": [ + "cpe:2.3:a:croberts:glossy:*:*:*:*:*:wordpress:*:*" + ], "gm-woocommerce-quote-popup": [ "cpe:2.3:a:gravitymaster:product_enquiry_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], @@ -12171,6 +12297,9 @@ "cpe:2.3:a:gsplugins:gs_logo_slider:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:gsplugins:logo_slider:*:*:*:*:*:wordpress:*:*" ], + "gs-pinterest-portfolio": [ + "cpe:2.3:a:gsplugins:gs_pinterest_portfolio:*:*:*:*:free:wordpress:*:*" + ], "gs-portfolio": [ "cpe:2.3:a:gsplugins:gs_filterable_portfolio:*:*:*:*:*:wordpress:*:*" ], @@ -12204,6 +12333,9 @@ "gtbabel": [ "cpe:2.3:a:gtbabel:gtbabel:*:*:*:*:*:wordpress:*:*" ], + "gtg-advanced-blocks": [ + "cpe:2.3:a:gutengeek:free_gutenberg_blocks:*:*:*:*:*:wordpress:*:*" + ], "gtm-server-side": [ "cpe:2.3:a:stape:gtm_server_side:*:*:*:*:*:wordpress:*:*" ], @@ -12249,6 +12381,9 @@ "gutenverse": [ "cpe:2.3:a:jegstudio:gutenverse:*:*:*:*:free:wordpress:*:*" ], + "gutenverse-news": [ + "cpe:2.3:a:jegstudio:gutenverse_news:*:*:*:*:*:wordpress:*:*" + ], "gwa-autoresponder": [ "cpe:2.3:a:\\[gwa\\]_autoresponder_project:\\[gwa\\]_autoresponder:*:*:*:*:*:wordpress:*:*" ], @@ -12375,6 +12510,9 @@ "homepage-product-organizer-for-woocommerce": [ "cpe:2.3:a:homepage_product_organizer_for_woocommerce_project:homepage_product_organizer_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], + "homerunner-smartcheckout": [ + "cpe:2.3:a:coolrunner:homerunner:*:*:*:*:*:wordpress:*:*" + ], "honeypot": [ "cpe:2.3:a:dineshkarki:wp_armour:*:*:*:*:*:wordpress:*:*" ], @@ -12403,6 +12541,9 @@ "hot-linked-image-cacher": [ "cpe:2.3:a:hot_linked_image_cacher_project:hot_linked_image_cacher:*:*:*:*:*:wordpress:*:*" ], + "hot-random-image": [ + "cpe:2.3:a:hot-themes:hot_random_image:*:*:*:*:*:wordpress:*:*" + ], "hotjar": [ "cpe:2.3:a:hotjar:hotjar:*:*:*:*:*:wordpress:*:*" ], @@ -12665,6 +12806,9 @@ "imgspider": [ "cpe:2.3:a:wbolt:imgspider:*:*:*:*:*:wordpress:*:*" ], + "import-export-for-woocommerce": [ + "cpe:2.3:a:sidngr:import_export_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "import-legacy-media": [ "cpe:2.3:a:import_legacy_media_project:import_legacy_media:*:*:*:*:*:wordpress:*:*" ], @@ -12693,6 +12837,12 @@ "indeed-job-importer": [ "cpe:2.3:a:indeed-job-importer_project:indeed-job-importer:*:*:*:*:*:*:*:*" ], + "index-wp-mysql-for-speed": [ + "cpe:2.3:a:plumislandmedia:index_wp_mysql_for_speed:*:*:*:*:*:wordpress:*:*" + ], + "indieblocks": [ + "cpe:2.3:a:janboddez:indieblocks:*:*:*:*:*:wordpress:*:*" + ], "indieweb-post-kinds": [ "cpe:2.3:a:indieweb_post_kinds_project:indieweb_post_kinds:*:*:*:*:*:wordpress:*:*" ], @@ -12874,6 +13024,9 @@ "iq-block-country": [ "cpe:2.3:a:webence:iq_block_country:*:*:*:*:*:wordpress:*:*" ], + "irm-newsroom": [ + "cpe:2.3:a:irmau:irm_newsroom:*:*:*:*:*:wordpress:*:*" + ], "ithemelandco-woo-report": [ "cpe:2.3:a:ithemelandco:woocommerce_report:*:*:*:*:*:wordpress:*:*" ], @@ -13003,6 +13156,12 @@ "cpe:2.3:a:joomsky:js_help_desk:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:wiselyhub:js_help_desk:*:*:*:*:*:wordpress:*:*" ], + "js_composer": [ + "cpe:2.3:a:wpbakery:page_builder:*:*:*:*:*:wordpress:*:*" + ], + "jsfiddle-shortcode": [ + "cpe:2.3:a:wvega:jsfiddle_shortcode:*:*:*:*:*:wordpress:*:*" + ], "jsmol2wp": [ "cpe:2.3:a:jsmol2wp_project:jsmol2wp:*:*:*:*:*:wordpress:*:*" ], @@ -13141,6 +13300,9 @@ "kraken-image-optimizer": [ "cpe:2.3:a:kraken:kraken.io_image_optimizer:*:*:*:*:*:wordpress:*:*" ], + "kudos-donations": [ + "cpe:2.3:a:iseard.media:kudos_donations:*:*:*:*:*:wordpress:*:*" + ], "kunze-law": [ "cpe:2.3:a:kunze-medien:kunze_law:*:*:*:*:*:wordpress:*:*" ], @@ -13180,7 +13342,8 @@ "cpe:2.3:a:lara\\'s_google_analytics_project:lara\\'s_google_analytics:*:*:*:*:*:wordpress:*:*" ], "lastudio-element-kit": [ - "cpe:2.3:a:la-studioweb:element_kit_for_elementor:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:la-studioweb:element_kit_for_elementor:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:la-studioweb:la-studio_element_kit_for_elementor:*:*:*:*:*:wordpress:*:*" ], "lastunes": [ "cpe:2.3:a:calenfretts:lastunes:*:*:*:*:*:wordpress:*:*" @@ -13284,6 +13447,9 @@ "leira-roles": [ "cpe:2.3:a:leira:roles_\\\u0026_capabilities:*:*:*:*:*:wordpress:*:*" ], + "lenix-elementor-leads-addon": [ + "cpe:2.3:a:wpmaspik:lenix_leads_collector:*:*:*:*:*:wordpress:*:*" + ], "letterpress": [ "cpe:2.3:a:themeqx:letterpress:*:*:*:*:*:wordpress:*:*" ], @@ -13502,9 +13668,41 @@ "lokalyze-call-now": [ "cpe:2.3:a:lokalyze:call_me_now:*:*:*:*:*:wordpress:*:*" ], + "ltl-freight-quotes-abf-freight-edition": [ + "cpe:2.3:a:eniture:ltl_freight_quotes:*:*:*:*:abf:wordpress:*:*", + "cpe:2.3:a:eniture:ltl_freight_quotes:*:*:*:*:abf_freight:wordpress:*:*" + ], + "ltl-freight-quotes-globaltranz-edition": [ + "cpe:2.3:a:eniture:ltl_freight_quotes:*:*:*:*:globaltranz:wordpress:*:*", + "cpe:2.3:a:eniture:small_package_quotes:*:*:*:*:ups:wordpress:*:*" + ], + "ltl-freight-quotes-odfl-edition": [ + "cpe:2.3:a:eniture:ltl_freight_quotes:*:*:*:*:odfl:wordpress:*:*" + ], + "ltl-freight-quotes-purolator-freight-edition": [ + "cpe:2.3:a:eniture:small_package_quotes:*:*:*:*:purolator:wordpress:*:*" + ], + "ltl-freight-quotes-saia-edition": [ + "cpe:2.3:a:eniture:ltl_freight_quotes:*:*:*:*:saia:wordpress:*:*" + ], + "ltl-freight-quotes-sefl-edition": [ + "cpe:2.3:a:eniture:ltl_freight_quotes:*:*:*:*:sefl:wordpress:*:*", + "cpe:2.3:a:eniture:ltl_freight_quotes:*:*:*:*:southeastern_freight_lines:wordpress:*:*" + ], "ltl-freight-quotes-unishippers-edition": [ "cpe:2.3:a:eniture:ltl_freight_quotes:*:*:*:*:unishippers:wordpress:*:*" ], + "ltl-freight-quotes-ups-edition": [ + "cpe:2.3:a:eniture:ltl_freight_quotes:*:*:*:*:tforce:wordpress:*:*", + "cpe:2.3:a:eniture:ltl_freight_quotes:*:*:*:*:ups:wordpress:*:*" + ], + "ltl-freight-quotes-worldwide-express-edition": [ + "cpe:2.3:a:eniture:ltl_freight_quotes:*:*:*:*:worldwide_express:wordpress:*:*", + "cpe:2.3:a:eniture:small_package_quotes:*:*:*:*:worldwide_express:wordpress:*:*" + ], + "ltl-freight-quotes-xpo-edition": [ + "cpe:2.3:a:eniture:ltl_freight_quotes:*:*:*:*:xpo:wordpress:*:*" + ], "lucas-string-replace": [ "cpe:2.3:a:lucasstad:lucas_string_replace:*:*:*:*:*:wordpress:*:*" ], @@ -13839,13 +14037,14 @@ "cpe:2.3:a:mekshq:meks_flexible_shortcodes:*:*:*:*:*:wordpress:*:*" ], "meks-smart-author-widget": [ - "cpe:2.3:a:mekshq:meks_smart_author_widget:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:mekshq:meks_smart_author_widget:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:mekshq:smart_author_widget:*:*:*:*:*:wordpress:*:*" ], "meks-smart-social-widget": [ "cpe:2.3:a:mekshq:meks_smart_social_widget:*:*:*:*:*:wordpress:*:*" ], "melapress-login-security": [ - "cpe:2.3:a:melapress:melapress_login_security:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:melapress:melapress_login_security:*:*:*:*:free:wordpress:*:*" ], "member-hero": [ "cpe:2.3:a:memberhero:member_hero:*:*:*:*:*:wordpress:*:*" @@ -13940,6 +14139,9 @@ "mighty-builder": [ "cpe:2.3:a:mightyplugins:mighty_builder:*:*:*:*:*:wordpress:*:*" ], + "mightyforms": [ + "cpe:2.3:a:mightyforms:mightyforms:*:*:*:*:*:wordpress:*:*" + ], "mihdan-index-now": [ "cpe:2.3:a:kobzarev:index_now:*:*:*:*:*:wordpress:*:*" ], @@ -14026,12 +14228,18 @@ "mollie-forms": [ "cpe:2.3:a:wobbie:mollie_forms:*:*:*:*:*:wordpress:*:*" ], + "mollie-payments-for-woocommerce": [ + "cpe:2.3:a:mollie:mollie_payments_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "molongui-authorship": [ "cpe:2.3:a:amitzy:molongui_authorship:*:*:*:*:*:wordpress:*:*" ], "monetize": [ "cpe:2.3:a:monetize_project:monetize:*:*:*:*:*:wordpress:*:*" ], + "month-name-translation-benaceur": [ + "cpe:2.3:a:benaceur-php:month_name_translation_benaceur:*:*:*:*:*:wordpress:*:*" + ], "montonio-for-woocommerce": [ "cpe:2.3:a:montonio:montonio_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], @@ -14353,7 +14561,8 @@ "cpe:2.3:a:mndpsingh287:newsletter_popup:*:*:*:*:*:wordpress:*:*" ], "newsletters-lite": [ - "cpe:2.3:a:tribulant:newsletters:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:tribulant:newsletters:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:tribulant:newsletters:*:*:*:*:free:wordpress:*:*" ], "newsplugin": [ "cpe:2.3:a:ipdgroup:newsplugin:*:*:*:*:*:wordpress:*:*" @@ -14456,6 +14665,9 @@ "note-press": [ "cpe:2.3:a:datainterlock:note_press:*:*:*:*:*:wordpress:*:*" ], + "notice-faq": [ + "cpe:2.3:a:notice:notice_faq:*:*:*:*:*:wordpress:*:*" + ], "notices": [ "cpe:2.3:a:notices_project:notices:*:*:*:*:*:wordpress:*:*" ], @@ -14468,6 +14680,9 @@ "notificationx": [ "cpe:2.3:a:wpdeveloper:notificationx:*:*:*:*:*:wordpress:*:*" ], + "notifier": [ + "cpe:2.3:a:wanotifier:wanotifier:*:*:*:*:*:wordpress:*:*" + ], "nova-blocks": [ "cpe:2.3:a:pixelgrade:nova_blocks:*:*:*:*:*:wordpress:*:*" ], @@ -14687,6 +14902,9 @@ "osmapper": [ "cpe:2.3:a:b4after:osmapper:*:*:*:*:*:wordpress:*:*" ], + "osomblocks": [ + "cpe:2.3:a:osompress:osom_blocks:*:*:*:*:*:wordpress:*:*" + ], "ota-sync-booking-engine-widget": [ "cpe:2.3:a:otasync:ota_sync_booking_engine_widget:*:*:*:*:*:wordpress:*:*" ], @@ -15040,6 +15258,9 @@ "plausible-analytics": [ "cpe:2.3:a:plausible:plausible_analytics:*:*:*:*:*:wordpress:*:*" ], + "play-ht": [ + "cpe:2.3:a:hammadh:play.ht:*:*:*:*:*:wordpress:*:*" + ], "player": [ "cpe:2.3:a:web-dorado:spidervplayer:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:web-dorado:web-dorado_spider_video_player:*:*:*:*:*:wordpress:*:*" @@ -15192,6 +15413,12 @@ "post-and-page-builder": [ "cpe:2.3:a:boldgrid:post_and_page_builder:*:*:*:*:*:wordpress:*:*" ], + "post-carousel": [ + "cpe:2.3:a:shapedplugin:smart_post_show:*:*:*:*:*:wordpress:*:*" + ], + "post-carousel-slider-for-elementor": [ + "cpe:2.3:a:plugin-devs:post_carousel_slider_for_elementor:*:*:*:*:*:wordpress:*:*" + ], "post-connector": [ "cpe:2.3:a:never5:post_connector:*:*:*:*:*:wordpress:*:*" ], @@ -15296,6 +15523,9 @@ "posts-reminder": [ "cpe:2.3:a:lucasgarcia:posts_reminder:*:*:*:*:*:wordpress:*:*" ], + "posts-table-filterable": [ + "cpe:2.3:a:pluginus:tableon_-_wordpress_posts_table_filterable:*:*:*:*:*:wordpress:*:*" + ], "posttabs": [ "cpe:2.3:a:posttabs_project:posttabs:*:*:*:*:*:wordpress:*:*" ], @@ -15455,6 +15685,9 @@ "product-import-export-for-woo": [ "cpe:2.3:a:webtoffee:product_import_export_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], + "product-input-fields-for-woocommerce": [ + "cpe:2.3:a:tychesoftwares:product_input_fields_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "product-reviews-import-export-for-woocommerce": [ "cpe:2.3:a:webtoffee:product_reviews_import_export_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], @@ -15688,6 +15921,9 @@ "randomtext": [ "cpe:2.3:a:random_text_project:random_text:*:*:*:*:*:wordpress:*:*" ], + "rapid-cache": [ + "cpe:2.3:a:megaoptim:rapid_cache:*:*:*:*:*:wordpress:*:*" + ], "rara-one-click-demo-import": [ "cpe:2.3:a:rarathemes:rara_one_click_demo_import:*:*:*:*:*:wordpress:*:*" ], @@ -15774,6 +16010,9 @@ "recall-products": [ "cpe:2.3:a:recall-products_project:recall-products:*:*:*:*:*:wordpress:*:*" ], + "recaptcha-jetpack": [ + "cpe:2.3:a:bozdoz:recaptcha_jetpack:*:*:*:*:*:wordpress:*:*" + ], "recent-backups": [ "cpe:2.3:a:recent-backups_project:recent-backups:*:*:*:*:*:wordpress:*:*" ], @@ -16222,6 +16461,9 @@ "search-meter": [ "cpe:2.3:a:search_meter_project:search_meter:*:*:*:*:*:wordpress:*:*" ], + "search-with-typesense": [ + "cpe:2.3:a:codemanas:search_with_typesense:*:*:*:*:*:wordpress:*:*" + ], "searchiq": [ "cpe:2.3:a:searchiq:searchiq:*:*:*:*:*:wordpress:*:*" ], @@ -16243,6 +16485,9 @@ "secure-copy-content-protection": [ "cpe:2.3:a:ays-pro:secure_copy_content_protection_and_content_locking:*:*:*:*:*:wordpress:*:*" ], + "secure-downloads": [ + "cpe:2.3:a:wpbookingcalendar:secure_downloads:*:*:*:*:*:wordpress:*:*" + ], "secure-file-manager": [ "cpe:2.3:a:themexa:secure_file_manager:*:*:*:*:*:wordpress:*:*" ], @@ -16413,6 +16658,9 @@ "shiny-buttons": [ "cpe:2.3:a:wpeden:shiny_buttons:*:*:*:*:*:wordpress:*:*" ], + "shipengine-shipping-quotes": [ + "cpe:2.3:a:eniture:shipengine_shipping_quotes:*:*:*:*:*:wordpress:*:*" + ], "shopello": [ "cpe:2.3:a:shopello_api_project:shopello_api:*:*:*:*:*:wordpress:*:*" ], @@ -16664,6 +16912,9 @@ "simple-mail-address-encoder": [ "cpe:2.3:a:simple_mail_address_encoder_project:simple_mail_address_encoder:*:*:*:*:*:wordpress:*:*" ], + "simple-map-no-api": [ + "cpe:2.3:a:shaonback2:simple_map_no_api:*:*:*:*:*:wordpress:*:*" + ], "simple-matted-thumbnails": [ "cpe:2.3:a:devondev:simple_matted_thumbnails:*:*:*:*:*:wordpress:*:*" ], @@ -16685,6 +16936,9 @@ "simple-page-transition": [ "cpe:2.3:a:simple_page_transition_project:simple_page_transition:*:*:*:*:*:wordpress:*:*" ], + "simple-payment": [ + "cpe:2.3:a:idokd:simple_payment:*:*:*:*:*:wordpress:*:*" + ], "simple-pdf-viewer": [ "cpe:2.3:a:simple_pdf_viewer_project:simple_pdf_viewer:*:*:*:*:*:wordpress:*:*" ], @@ -16870,7 +17124,8 @@ "cpe:2.3:a:sitepact:contact_form_7_extension_for_klaviyo:*:*:*:*:*:wordpress:*:*" ], "sitepress-multilingual-cms": [ - "cpe:2.3:a:onthegosystems:sitepress-multilingual-cms:*:*:*:*:*:wordpress:*:*" + "cpe:2.3:a:onthegosystems:sitepress-multilingual-cms:*:*:*:*:*:wordpress:*:*", + "cpe:2.3:a:wpml:wpml:*:*:*:*:*:wordpress:*:*" ], "sitesupercharger": [ "cpe:2.3:a:marketingheroes:sitesupercharger:*:*:*:*:*:wordpress:*:*" @@ -16972,13 +17227,28 @@ "slideshow-se": [ "cpe:2.3:a:slideshow_se_project:slideshow_se:*:*:*:*:*:wordpress:*:*" ], + "small-package-quotes-fedex-edition": [ + "cpe:2.3:a:eniture:small_package_quotes:*:*:*:*:fedex:wordpress:*:*" + ], + "small-package-quotes-purolator-edition": [ + "cpe:2.3:a:eniture:small_package_quotes:*:*:*:*:purolator:wordpress:*:*" + ], "small-package-quotes-unishippers-edition": [ "cpe:2.3:a:eniture:ltl_freight_quotes:*:*:*:*:unishippers:wordpress:*:*", "cpe:2.3:a:eniture:small_package_quotes:*:*:*:*:unishippers:wordpress:*:*" ], "small-package-quotes-ups-edition": [ + "cpe:2.3:a:eniture:small_package_quotes:*:*:*:*:ups:wordpress:*:*", + "cpe:2.3:a:eniture:small_package_quotes:*:*:*:*:usps:wordpress:*:*", + "cpe:2.3:a:eniture:small_package_quotes:*:*:*:*:wee:wordpress:*:*", "cpe:2.3:a:enituretechnology:small_package_quotes:*:*:*:*:ups:wordpress:*:*" ], + "small-package-quotes-usps-edition": [ + "cpe:2.3:a:eniture:small_package_quotes:*:*:*:*:usps:wordpress:*:*" + ], + "small-package-quotes-wwe-edition": [ + "cpe:2.3:a:eniture:small_package_quotes:*:*:*:*:wee:wordpress:*:*" + ], "smart-app-banner": [ "cpe:2.3:a:wandlesoftware:smart_app_banner:*:*:*:*:*:wordpress:*:*" ], @@ -17030,6 +17300,9 @@ "smartcrawl-seo": [ "cpe:2.3:a:wpmudev:smartcrawl:*:*:*:*:*:wordpress:*:*" ], + "smartpay": [ + "cpe:2.3:a:themesgrove:wp_smartpay:*:*:*:*:*:wordpress:*:*" + ], "smartsearchwp": [ "cpe:2.3:a:smartsearchwp:smartsearchwp:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:webdigit:chatbot_with_chatgpt:*:*:*:*:*:wordpress:*:*" @@ -17118,6 +17391,9 @@ "social-pixel": [ "cpe:2.3:a:labschool:social_pixel:*:*:*:*:*:*:wordpress:*" ], + "social-polls-by-opinionstage": [ + "cpe:2.3:a:opinionstage:poll\\,_survey_\\\u0026_quiz_maker:*:*:*:*:*:wordpress:*:*" + ], "social-proof-testimonials-slider": [ "cpe:2.3:a:brandid:social_proof_\\(testimonial\\)_slider:*:*:*:*:*:wordpress:*:*" ], @@ -17305,6 +17581,9 @@ "stax-addons-for-elementor": [ "cpe:2.3:a:staxwp:stax:*:*:*:*:*:wordpress:*:*" ], + "stax-buddy-builder": [ + "cpe:2.3:a:staxwp:buddybuilder:*:*:*:*:*:wordpress:*:*" + ], "stellissimo-text-box": [ "cpe:2.3:a:overclokk:stellissimo_text_box:*:*:*:*:*:wordpress:*:*" ], @@ -17367,6 +17646,9 @@ "cpe:2.3:a:store_locator_project:store_locator:*:*:*:*:*:wordpress:*:*", "cpe:2.3:a:viadat:store_locator_for_wordpress_with_google_maps:*:*:*:*:*:wordpress:*:*" ], + "store-manager-connector": [ + "cpe:2.3:a:emagicone:emagicone_store_manager_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "storefront-footer-text": [ "cpe:2.3:a:wooassist:storefront_footer_text:*:*:*:*:*:wordpress:*:*" ], @@ -17428,6 +17710,9 @@ "sucuri-scanner": [ "cpe:2.3:a:sucuri:security:*:*:*:*:*:wordpress:*:*" ], + "sugar-calendar-lite": [ + "cpe:2.3:a:wpbeginner:sugar_calendar:*:*:*:*:*:wordpress:*:*" + ], "sully": [ "cpe:2.3:a:toolstack:sully:*:*:*:*:*:wordpress:*:*" ], @@ -17459,6 +17744,9 @@ "support-svg": [ "cpe:2.3:a:sayedulsayem:support_svg:*:*:*:*:*:wordpress:*:*" ], + "supportboard": [ + "cpe:2.3:a:schiocco:support_board:*:*:*:*:*:wordpress:*:*" + ], "supportcandy": [ "cpe:2.3:a:supportcandy:supportcandy:*:*:*:*:*:wordpress:*:*" ], @@ -17671,6 +17959,9 @@ "tf-numbers-number-counter-animaton": [ "cpe:2.3:a:metagauss:themeflection_numbers:*:*:*:*:*:wordpress:*:*" ], + "th-advance-product-search": [ + "cpe:2.3:a:themehunk:advance_product_search:*:*:*:*:free:wordpress:*:*" + ], "thank-me-later": [ "cpe:2.3:a:thank_me_later_project:thank_me_later:*:*:*:*:*:wordpress:*:*" ], @@ -17889,6 +18180,9 @@ "tourfic": [ "cpe:2.3:a:themefic:tourfic:*:*:*:*:*:wordpress:*:*" ], + "tourmaster": [ + "cpe:2.3:a:goodlayers:tour_master:*:*:*:*:*:wordpress:*:*" + ], "tournamatch": [ "cpe:2.3:a:tournamatch:tournamatch:*:*:*:*:*:wordpress:*:*" ], @@ -18689,6 +18983,9 @@ "website-article-monetization-by-magenet": [ "cpe:2.3:a:magenet:website_article_monetization:*:*:*:*:*:wordpress:*:*" ], + "website-file-changes-monitor": [ + "cpe:2.3:a:melapress:melapress_file_monitor:*:*:*:*:*:wordpress:*:*" + ], "website-monetization-by-magenet": [ "cpe:2.3:a:magenet:website_monetization:*:*:*:*:*:wordpress:*:*" ], @@ -18803,6 +19100,9 @@ "wiseagentleadform": [ "cpe:2.3:a:wiseagent:wise_agent_capture_forms:*:*:*:*:*:wordpress:*:*" ], + "wish-list-for-woocommerce": [ + "cpe:2.3:a:wpfactory:wishlist_for_woocommerce\\:_multi_wishlists_per_customer:*:*:*:*:*:wordpress:*:*" + ], "wishsuite": [ "cpe:2.3:a:hasthemes:wishsuite:*:*:*:*:*:wordpress:*:*" ], @@ -18967,6 +19267,9 @@ "woo-shipping-dpd-baltic": [ "cpe:2.3:a:dpdgroup:woocommerce_shipping:*:*:*:*:*:wordpress:*:*" ], + "woo-smart-compare": [ + "cpe:2.3:a:wpclever:wpc_smart_compare_for_woocommerce:*:*:*:*:*:wordpress:*:*" + ], "woo-smart-quick-view": [ "cpe:2.3:a:wpclever:wpc_smart_quick_view_for_woocommerce:*:*:*:*:*:wordpress:*:*" ], @@ -19182,6 +19485,9 @@ "wordlift": [ "cpe:2.3:a:wordlift:wordlift:*:*:*:*:*:wordpress:*:*" ], + "wordpress-23-related-posts-plugin": [ + "cpe:2.3:a:sovrn:wordpress_related_posts:*:*:*:*:*:wordpress:*:*" + ], "wordpress-access-control": [ "cpe:2.3:a:brandonwamboldt:wordpress_access_control:*:*:*:*:*:wordpress:*:*" ], @@ -19318,6 +19624,9 @@ "wp-backgrounds-lite": [ "cpe:2.3:a:inoplugs:wp-backgrounds_lite:*:*:*:*:*:wordpress:*:*" ], + "wp-backitup": [ + "cpe:2.3:a:wpbackitup:backup_and_restore_wordpress:*:*:*:*:*:wordpress:*:*" + ], "wp-baidu-submit": [ "cpe:2.3:a:wp_baidu_submit_project:wp_baidu_submit:*:*:*:*:*:wordpress:*:*" ], @@ -19608,6 +19917,12 @@ "wp-e-commerce": [ "cpe:2.3:a:zao:wp_ecommerce:*:*:*:*:*:wordpress:*:*" ], + "wp-easy-contact": [ + "cpe:2.3:a:emarketdesign:wp_easy_contact:*:*:*:*:*:wordpress:*:*" + ], + "wp-easy-gallery": [ + "cpe:2.3:a:plugingarden:wp_easy_gallery:*:*:*:*:*:wordpress:*:*" + ], "wp-easy-pay": [ "cpe:2.3:a:wpeasypay:wp_easypay:*:*:*:*:*:wordpress:*:*" ], @@ -19916,6 +20231,9 @@ "wp-latest-posts": [ "cpe:2.3:a:joomunited:wp_latest_posts:*:*:*:*:*:wordpress:*:*" ], + "wp-leads-builder-any-crm": [ + "cpe:2.3:a:smackcoders:lead_form_data_collection_to_crm:*:*:*:*:*:wordpress:*:*" + ], "wp-libre-form": [ "cpe:2.3:a:wp_libre_form_project:wp_libre_form:*:*:*:*:*:wordpress:*:*" ], @@ -20004,6 +20322,9 @@ "wp-marketing-automations": [ "cpe:2.3:a:funnelkit:funnelkit_automations:*:*:*:*:*:wordpress:*:*" ], + "wp-masonry-infinite-scroll": [ + "cpe:2.3:a:wporbit:wp_masonry_\\\u0026_infinite_scroll:*:*:*:*:*:wordpress:*:*" + ], "wp-media-cleaner": [ "cpe:2.3:a:wp_media_cleaner_project:wp_media_cleaner:*:*:*:*:*:wordpress:*:*" ], @@ -20580,6 +20901,9 @@ "wp-users-exporter": [ "cpe:2.3:a:wp-users-exporter_project:wp-users-exporter:*:*:*:*:*:wordpress:*:*" ], + "wp-users-masquerade": [ + "cpe:2.3:a:lagunaisw:wp_users_masquerade:*:*:*:*:*:wordpress:*:*" + ], "wp-vertical-image-slider": [ "cpe:2.3:a:i13websolution:wordpress_vertical_image_slider:*:*:*:*:*:wordpress:*:*" ], @@ -20662,12 +20986,18 @@ "wpb-elementor-addons": [ "cpe:2.3:a:wpbean:wpb_elementor_addons:*:*:*:*:*:wordpress:*:*" ], + "wpb-popup-for-contact-form-7": [ + "cpe:2.3:a:wpbean:wpb_popup_for_contact_form_7:*:*:*:*:free:wordpress:*:*" + ], "wpb-show-core": [ "cpe:2.3:a:wpb_show_core_project:wpb_show_core:*:*:*:*:*:wordpress:*:*" ], "wpbits-addons-for-elementor": [ "cpe:2.3:a:wpbits:wpbits_addons_for_elementor_page_builder:*:*:*:*:*:wordpress:*:*" ], + "wpbookit": [ + "cpe:2.3:a:iqonic:wpbookit:*:*:*:*:free:wordpress:*:*" + ], "wpbulky-wp-bulk-edit-post-types": [ "cpe:2.3:a:villatheme:wpbulky:*:*:*:*:*:wordpress:*:*" ], @@ -21449,6 +21779,9 @@ "posterity": [ "cpe:2.3:a:sktthemes:posterity:*:*:*:*:*:wordpress:*:*" ], + "pressmart": [ + "cpe:2.3:a:presslayouts:pressmart:*:*:*:*:*:wordpress:*:*" + ], "regina-lite": [ "cpe:2.3:a:machothemes:regina_lite:*:*:*:*:*:wordpress:*:*" ], diff --git a/syft/pkg/cataloger/internal/cpegenerate/generate.go b/syft/pkg/cataloger/internal/cpegenerate/generate.go index 3a8e7ac9d84..1ccbf5e25ac 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/generate.go +++ b/syft/pkg/cataloger/internal/cpegenerate/generate.go @@ -6,9 +6,11 @@ import ( _ "embed" "encoding/json" "fmt" + "regexp" "sort" "strings" "sync" + "unicode" "github.com/scylladb/go-set/strset" @@ -228,6 +230,11 @@ func candidateVendors(p pkg.Package) []string { vendors.union(candidateVendorsForWordpressPlugin(p)) } + if p.Type == pkg.BinaryPkg && endsWithNumber(p.Name) { + // add binary package digit-suffix variations (e.g. Qt5 -> Qt) + addBinaryPackageDigitVariations(vendors) + } + // We should no longer be generating vendor candidates with these values ["" and "*"] // (since CPEs will match any other value) vendors.removeByValue("") @@ -286,6 +293,9 @@ func candidateProductSet(p pkg.Package) fieldCandidateSet { if prod != "" { products.addValue(prod) } + case p.Type == pkg.BinaryPkg && endsWithNumber(p.Name): + // add binary package digit-suffix variations (e.g. Qt5 -> Qt) + addBinaryPackageDigitVariations(products) } switch p.Metadata.(type) { @@ -404,3 +414,33 @@ func addDelimiterVariations(fields fieldCandidateSet) { } } } + +// removeTrailingDigits removes all trailing digits from a string +func removeTrailingDigits(s string) string { + re := regexp.MustCompile(`\d+$`) + return re.ReplaceAllString(s, "") +} + +// addBinaryPackageDigitVariations adds variations with trailing digits removed for binary packages.For binary package types only, when the name ends with a digit, add a new variation with all suffix-digits removed (e.g. Qt5 -> Qt). This helps generate additional CPE permutations for better vulnerability matching. +func addBinaryPackageDigitVariations(fields fieldCandidateSet) { + candidatesForVariations := fields.copy() + for _, candidate := range candidatesForVariations.values() { + // Check if the candidate ends with a digit + if len(candidate) > 0 && candidate[len(candidate)-1] >= '0' && candidate[len(candidate)-1] <= '9' { + // Create variation with all suffix digits removed + withoutDigits := removeTrailingDigits(candidate) + if withoutDigits != "" && withoutDigits != candidate { + fields.addValue(withoutDigits) + } + } + } +} + +func endsWithNumber(s string) bool { + if len(s) == 0 { + return false + } + r := []rune(s) + last := r[len(r)-1] + return unicode.IsDigit(last) +} diff --git a/syft/pkg/cataloger/internal/cpegenerate/generate_test.go b/syft/pkg/cataloger/internal/cpegenerate/generate_test.go index d78baea1b6e..3323fbc6c85 100644 --- a/syft/pkg/cataloger/internal/cpegenerate/generate_test.go +++ b/syft/pkg/cataloger/internal/cpegenerate/generate_test.go @@ -1145,3 +1145,67 @@ func TestDictionaryFindIsWired(t *testing.T) { }) } } + +// TestAddBinaryPackageDigitVariations tests the heuristic for binary package types +// where names ending with digits get variations with all suffix-digits removed (e.g. Qt5 -> Qt). +// This improves vulnerability matching for binary packages like Qt6, libfoo123, etc. +func TestAddBinaryPackageDigitVariations(t *testing.T) { + tests := []struct { + name string + packageType pkg.Type + inputCandidates []string + expectedPresent []string // These should be present in the result + expectedAbsent []string // These should NOT be present in the result + }{ + { + name: "Qt5 binary package example", + packageType: pkg.BinaryPkg, + inputCandidates: []string{"Qt5"}, + expectedPresent: []string{"Qt5", "Qt"}, + expectedAbsent: []string{}, + }, + { + name: "package with trailing digits", + packageType: pkg.BinaryPkg, + inputCandidates: []string{"Qt5", "libfoo123", "bar42", "baz"}, + expectedPresent: []string{"Qt5", "Qt", "libfoo123", "libfoo", "bar42", "bar", "baz"}, + expectedAbsent: []string{}, + }, + { + name: "multiple trailing digits", + inputCandidates: []string{"Qt872", "package999"}, + expectedPresent: []string{"Qt872", "Qt", "package999", "package"}, + expectedAbsent: []string{}, + }, + { + name: "package without trailing digits", + inputCandidates: []string{"QtCore", "libfoo", "bar"}, + expectedPresent: []string{"QtCore", "libfoo", "bar"}, + expectedAbsent: []string{"QtCor", "libfo", "ba"}, + }, + { + name: "empty candidate set", + packageType: pkg.BinaryPkg, + inputCandidates: []string{}, + expectedPresent: []string{}, + expectedAbsent: []string{}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + fields := newFieldCandidateSet(test.inputCandidates...) + addBinaryPackageDigitVariations(fields) + + values := fields.uniqueValues() + + for _, expected := range test.expectedPresent { + assert.Contains(t, values, expected, "expected %q to be present", expected) + } + + for _, notExpected := range test.expectedAbsent { + assert.NotContains(t, values, notExpected, "expected %q to be absent", notExpected) + } + }) + } +} diff --git a/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go b/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go index 95f6e5d039b..28cffb02fd9 100644 --- a/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go +++ b/syft/pkg/cataloger/internal/pkgtest/test_generic_parser.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "os" + "path/filepath" "sort" "strings" "sync" @@ -16,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + stereofile "github.com/anchore/stereoscope/pkg/file" "github.com/anchore/stereoscope/pkg/imagetest" "github.com/anchore/syft/internal/cmptest" "github.com/anchore/syft/internal/licenses" @@ -130,11 +132,14 @@ func (p *CatalogTester) FromFile(t *testing.T, path string) *CatalogTester { return p } + absPath, err := filepath.Abs(path) + require.NoError(t, err) + fixture, err := os.Open(path) require.NoError(t, err) p.reader = file.LocationReadCloser{ - Location: file.NewLocation(fixture.Name()), + Location: file.NewVirtualLocationFromDirectory(fixture.Name(), fixture.Name(), *stereofile.NewFileReference(stereofile.Path(absPath))), ReadCloser: fixture, } return p diff --git a/syft/pkg/cataloger/java/archive_parser.go b/syft/pkg/cataloger/java/archive_parser.go index d06b6587288..382414d835d 100644 --- a/syft/pkg/cataloger/java/archive_parser.go +++ b/syft/pkg/cataloger/java/archive_parser.go @@ -1,15 +1,18 @@ package java import ( + "cmp" "context" "crypto" "fmt" "io" + "iter" "os" "path" "slices" "strings" + "github.com/scylladb/go-set/strset" "golang.org/x/exp/maps" "github.com/anchore/syft/internal" @@ -391,20 +394,32 @@ func (j *archiveParser) discoverMainPackageFromPomInfo(ctx context.Context) (gro projects, _ := pomProjectByParentPath(j.archivePath, j.location, j.fileManifest.GlobMatch(false, pomXMLGlob)) // map of all the artifacts in the pom properties, in order to chek exact match with the filename - artifactsMap := make(map[string]bool) + artifactsMap := strset.New() for _, propertiesObj := range properties { - artifactsMap[propertiesObj.ArtifactID] = true + artifactsMap.Add(propertiesObj.ArtifactID) } - parentPaths := maps.Keys(properties) - slices.Sort(parentPaths) - for _, parentPath := range parentPaths { - propertiesObj := properties[parentPath] + for parentPath, propertiesObj := range sortedIter(properties) { + // the logic for selecting the best name is as follows: + // if we find an artifact id AND group id which are both contained in the filename + // OR if we have an artifact id that exactly matches the filename, prefer this + // OTHERWISE track the first matching pom properties with a pom.xml + // FINALLY return the first matching pom properties if artifactIDMatchesFilename(propertiesObj.ArtifactID, j.fileInfo.name, artifactsMap) { - pomProperties = propertiesObj + if pomProperties.ArtifactID == "" { // keep the first match, or overwrite if we find more specific entries + pomProperties = propertiesObj + } if proj, exists := projects[parentPath]; exists { - parsedPom = proj - break + if parsedPom == nil { // keep the first matching artifact if we don't find an exact match or groupid + artfiact id match + pomProperties = propertiesObj // set this, as it may not be the first entry found + parsedPom = proj + } + // if artifact ID is the entire filename or BOTH artifactID and groupID are contained in the artifact, prefer this match + if strings.Contains(j.fileInfo.name, propertiesObj.GroupID) || j.fileInfo.name == propertiesObj.ArtifactID { + pomProperties = propertiesObj // this is an exact match, use it + parsedPom = proj + break + } } } } @@ -429,12 +444,13 @@ func (j *archiveParser) discoverMainPackageFromPomInfo(ctx context.Context) (gro return group, name, version, parsedPom } -func artifactIDMatchesFilename(artifactID, fileName string, artifactsMap map[string]bool) bool { +// artifactIDMatchesFilename returns true if one starts with the other +func artifactIDMatchesFilename(artifactID, fileName string, artifactsMap *strset.Set) bool { if artifactID == "" || fileName == "" { return false } // Ensure true is returned when filename matches the artifact ID, prevent random retrieval by checking prefix and suffix - if _, exists := artifactsMap[fileName]; exists { + if artifactsMap.Has(fileName) { return artifactID == fileName } // Use fallback check with suffix and prefix if no POM properties file matches the exact artifact name @@ -464,7 +480,7 @@ func (j *archiveParser) discoverPkgsFromAllMavenFiles(ctx context.Context, paren return nil, err } - for parentPath, propertiesObj := range properties { + for parentPath, propertiesObj := range sortedIter(properties) { var parsedPom *parsedPomProject if proj, exists := projects[parentPath]; exists { parsedPom = proj @@ -546,7 +562,7 @@ func discoverPkgsFromOpeners(ctx context.Context, location file.Location, opener var pkgs []pkg.Package var relationships []artifact.Relationship - for pathWithinArchive, archiveOpener := range openers { + for pathWithinArchive, archiveOpener := range sortedIter(openers) { nestedPkgs, nestedRelationships, err := discoverPkgsFromOpener(ctx, location, pathWithinArchive, archiveOpener, cfg, parentPkg) if err != nil { log.WithFields("location", location.Path(), "error", err).Debug("unable to discover java packages from opener") @@ -604,7 +620,7 @@ func pomPropertiesByParentPath(archivePath string, location file.Location, extra } propertiesByParentPath := make(map[string]pkg.JavaPomProperties) - for filePath, fileContents := range contentsOfMavenPropertiesFiles { + for filePath, fileContents := range sortedIter(contentsOfMavenPropertiesFiles) { pomProperties, err := parsePomProperties(filePath, strings.NewReader(fileContents)) if err != nil { log.WithFields("contents-path", filePath, "location", location.Path(), "error", err).Debug("failed to parse pom.properties") @@ -633,7 +649,7 @@ func pomProjectByParentPath(archivePath string, location file.Location, extractP } projectByParentPath := make(map[string]*parsedPomProject) - for filePath, fileContents := range contentsOfMavenProjectFiles { + for filePath, fileContents := range sortedIter(contentsOfMavenProjectFiles) { // TODO: when we support locations of paths within archives we should start passing the specific pom.xml location object instead of the top jar pom, err := maven.ParsePomXML(strings.NewReader(fileContents)) if err != nil { @@ -784,3 +800,15 @@ func updateParentPackage(p pkg.Package, parentPkg *pkg.Package) { parentPkg.Metadata = parentMetadata } } + +func sortedIter[K cmp.Ordered, V any](values map[K]V) iter.Seq2[K, V] { + return func(yield func(K, V) bool) { + keys := maps.Keys(values) + slices.Sort(keys) + for _, key := range keys { + if !yield(key, values[key]) { + return + } + } + } +} diff --git a/syft/pkg/cataloger/java/archive_parser_test.go b/syft/pkg/cataloger/java/archive_parser_test.go index 55a4a0c543d..b3d656ecff6 100644 --- a/syft/pkg/cataloger/java/archive_parser_test.go +++ b/syft/pkg/cataloger/java/archive_parser_test.go @@ -1086,7 +1086,7 @@ func Test_artifactIDMatchesFilename(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.want, artifactIDMatchesFilename(tt.artifactID, tt.fileName, nil)) + assert.Equal(t, tt.want, artifactIDMatchesFilename(tt.artifactID, tt.fileName, strset.New())) }) } } @@ -1382,6 +1382,10 @@ func Test_deterministicMatchingPomProperties(t *testing.T) { fixture: "multiple-matching-2.11.5", expected: maven.NewID("org.multiple", "multiple-matching-1", "2.11.5"), }, + { + fixture: "org.multiple-thename", + expected: maven.NewID("org.multiple", "thename", "10.11.12"), + }, } for _, test := range tests { diff --git a/syft/pkg/cataloger/java/graalvm_native_image_cataloger.go b/syft/pkg/cataloger/java/graalvm_native_image_cataloger.go index a5d57911d24..c9611b9daa6 100644 --- a/syft/pkg/cataloger/java/graalvm_native_image_cataloger.go +++ b/syft/pkg/cataloger/java/graalvm_native_image_cataloger.go @@ -508,7 +508,7 @@ func (ni nativeImagePE) fetchPkgs() (pkgs []pkg.Package, relationships []artifac } // fetchPkgs provides the packages available in a UnionReader. -func fetchPkgs(reader unionreader.UnionReader, filename string) ([]pkg.Package, []artifact.Relationship) { +func fetchPkgs(reader unionreader.UnionReader, location file.Location) ([]pkg.Package, []artifact.Relationship) { var pkgs []pkg.Package var relationships []artifact.Relationship imageFormats := []func(string, io.ReaderAt) (nativeImage, error){newElf, newMachO, newPE} @@ -520,6 +520,7 @@ func fetchPkgs(reader unionreader.UnionReader, filename string) ([]pkg.Package, log.Debugf("failed to open the java native-image binary: %v", err) return nil, nil } + filename := location.RealPath for _, r := range readers { for _, makeNativeImage := range imageFormats { ni, err := makeNativeImage(filename, r) @@ -534,6 +535,10 @@ func fetchPkgs(reader unionreader.UnionReader, filename string) ([]pkg.Package, log.Tracef("unable to extract SBOM from possible java native-image %s: %v", filename, err) continue } + // Associate extracted packages with the native image location + for i := range newPkgs { + newPkgs[i].Locations.Add(location) + } pkgs = append(pkgs, newPkgs...) relationships = append(relationships, newRelationships...) } @@ -574,6 +579,6 @@ func processLocation(location file.Location, resolver file.Resolver) ([]pkg.Pack if err != nil { return nil, nil, err } - pkgs, relationships := fetchPkgs(reader, location.RealPath) + pkgs, relationships := fetchPkgs(reader, location) return pkgs, relationships, nil } diff --git a/syft/pkg/cataloger/java/graalvm_native_image_cataloger_test.go b/syft/pkg/cataloger/java/graalvm_native_image_cataloger_test.go index fb2ec7d917c..fd2db0aad2f 100644 --- a/syft/pkg/cataloger/java/graalvm_native_image_cataloger_test.go +++ b/syft/pkg/cataloger/java/graalvm_native_image_cataloger_test.go @@ -11,7 +11,7 @@ import ( "path" "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/cpe" @@ -36,16 +36,16 @@ func TestParseNativeImage(t *testing.T) { for _, test := range tests { t.Run(test.fixture, func(t *testing.T) { f, err := os.Open("test-fixtures/java-builds/packages/" + test.fixture) - assert.NoError(t, err) + require.NoError(t, err) readerCloser := io.NopCloser(f) reader, err := unionreader.GetUnionReader(readerCloser) - assert.NoError(t, err) + require.NoError(t, err) parsed := false readers, err := unionreader.GetReaders(reader) - assert.NoError(t, err) + require.NoError(t, err) for _, r := range readers { ni, err := test.newFn(test.fixture, r) - assert.NoError(t, err) + require.NoError(t, err) _, _, err = ni.fetchPkgs() if err == nil { t.Fatalf("should have failed to extract SBOM.") @@ -228,11 +228,11 @@ func buildPackageMap(packages []pkg.Package) map[string]pkg.Package { } func verifyPackageFields(t *testing.T, expected, actual pkg.Package) { - assert.Equal(t, expected.Name, actual.Name) - assert.Equal(t, expected.Version, actual.Version) - assert.Equal(t, expected.FoundBy, actual.FoundBy) - assert.Equal(t, expected.PURL, actual.PURL) - assert.ElementsMatch(t, expected.CPEs, actual.CPEs) + require.Equal(t, expected.Name, actual.Name) + require.Equal(t, expected.Version, actual.Version) + require.Equal(t, expected.FoundBy, actual.FoundBy) + require.Equal(t, expected.PURL, actual.PURL) + require.ElementsMatch(t, expected.CPEs, actual.CPEs) } func verifyRelationships(t *testing.T, expected, actual []artifact.Relationship) { @@ -260,8 +260,8 @@ func buildRelationshipMap(relationships []artifact.Relationship) map[string][]ar } func verifyRelationshipFields(t *testing.T, expected, actual []artifact.Relationship) { - assert.Equal(t, len(expected), len(actual)) + require.Equal(t, len(expected), len(actual)) for i := range expected { - assert.Equal(t, expected[i].Type, actual[i].Type) + require.Equal(t, expected[i].Type, actual[i].Type) } } diff --git a/syft/pkg/cataloger/java/parse_jvm_release.go b/syft/pkg/cataloger/java/parse_jvm_release.go index df1a5cf5ed3..3ef5233ee3b 100644 --- a/syft/pkg/cataloger/java/parse_jvm_release.go +++ b/syft/pkg/cataloger/java/parse_jvm_release.go @@ -91,7 +91,7 @@ func parseJVMRelease(_ context.Context, resolver file.Resolver, _ *generic.Envir // the reason we use the reference to get the real path is in cases where the file cataloger is involved // (thus the real path is not available except for in the original file reference). This is important // since the path is critical for distinguishing between different JVM vendors. - vendor, product := jvmPrimaryVendorProduct(ri.Implementor, string(reader.Reference().RealPath), ri.ImageType, hasJdk) + vendor, product := jvmPrimaryVendorProduct(ri, string(reader.Reference().RealPath), hasJdk) p := pkg.Package{ Name: product, @@ -163,11 +163,11 @@ func jvmPurl(ri pkg.JavaVMRelease, version, vendor, product string) string { return pURL.ToString() } -func jvmPrimaryVendorProduct(implementor, path, imageType string, hasJdk bool) (string, string) { - implementor = strings.ReplaceAll(strings.ToLower(implementor), " ", "") +func jvmPrimaryVendorProduct(ri *pkg.JavaVMRelease, path string, hasJdk bool) (string, string) { + implementor := strings.ReplaceAll(strings.ToLower(ri.Implementor), " ", "") pickProduct := func() string { - if hasJdk || jvmProjectByType(imageType) == jdk { + if hasJdk || jvmProjectByType(ri.ImageType) == jdk { return jdk } return jre @@ -180,7 +180,13 @@ func jvmPrimaryVendorProduct(implementor, path, imageType string, hasJdk bool) ( case strings.Contains(implementor, "sun"): return "sun", pickProduct() - case strings.Contains(implementor, "oracle") || strings.Contains(path, "oracle"): + case strings.Contains(implementor, "ibm") || strings.Contains(path, "/ibm"): + if hasJdk { + return "ibm", "java_sdk" + } + return "ibm", "java" + + case strings.Contains(implementor, "oracle") || strings.Contains(path, "oracle") || strings.Contains(ri.BuildType, "commercial"): return oracleVendor, pickProduct() } return oracleVendor, openJdkProduct diff --git a/syft/pkg/cataloger/java/parse_jvm_release_test.go b/syft/pkg/cataloger/java/parse_jvm_release_test.go index 08a8cb4d5d9..0e7c32da752 100644 --- a/syft/pkg/cataloger/java/parse_jvm_release_test.go +++ b/syft/pkg/cataloger/java/parse_jvm_release_test.go @@ -307,6 +307,7 @@ func TestJvmPrimaryVendorProduct(t *testing.T) { tests := []struct { name string implementor string + buildType string path string imageType string hasJdk bool @@ -340,6 +341,25 @@ func TestJvmPrimaryVendorProduct(t *testing.T) { expectedVendor: "oracle", expectedProduct: "jre", }, + { + name: "Oracle commercial build type with JRE", + implementor: "", + buildType: "commercial", + path: "/usr/lib/jvm/jdk8/release", + imageType: "JRE", + hasJdk: false, + expectedVendor: "oracle", + expectedProduct: "jre", + }, + { + name: "Oracle commercial build type with JDK", + implementor: "", + buildType: "commercial", + path: "/usr/lib/jvm/jdk8/release", + hasJdk: true, + expectedVendor: "oracle", + expectedProduct: "jdk", + }, { name: "Oracle vendor with JDK in path", implementor: "", @@ -367,11 +387,29 @@ func TestJvmPrimaryVendorProduct(t *testing.T) { expectedVendor: "oracle", // corretto upstream is oracle openjdk expectedProduct: "openjdk", }, + { + name: "IBM JRE", + path: "/opt/ibm/java/release", + expectedVendor: "ibm", + expectedProduct: "java", + }, + { + name: "IBM JDK", + path: "/opt/ibm/java/release", + hasJdk: true, + expectedVendor: "ibm", + expectedProduct: "java_sdk", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - vendor, product := jvmPrimaryVendorProduct(tt.implementor, tt.path, tt.imageType, tt.hasJdk) + ri := pkg.JavaVMRelease{ + Implementor: tt.implementor, + BuildType: tt.buildType, + ImageType: tt.imageType, + } + vendor, product := jvmPrimaryVendorProduct(&ri, tt.path, tt.hasJdk) assert.Equal(t, tt.expectedVendor, vendor) assert.Equal(t, tt.expectedProduct, product) }) diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile index cf0d21a8672..c8904e7259f 100644 --- a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/Makefile @@ -12,6 +12,7 @@ OPENSAML_CORE = opensaml-core-3.4.6 API_ALL_SOURCES = api-all-2.0.0-sources SPRING_INSTRUMENTATION = spring-instrumentation-4.3.0-1.0 MULTIPLE_MATCHING = multiple-matching-2.11.5 +ORG_MULTIPLE_THENAME = org.multiple-thename .DEFAULT_GOAL := fixtures @@ -48,7 +49,11 @@ $(CACHE_DIR)/$(MULTIPLE_MATCHING).jar: mkdir -p $(CACHE_DIR) cd $(MULTIPLE_MATCHING) && zip -r $(CACHE_PATH)/$(MULTIPLE_MATCHING).jar . -# Jenkins plugins typically do not have the version included in the archive name, +$(CACHE_DIR)/$(ORG_MULTIPLE_THENAME).jar: + mkdir -p $(CACHE_DIR) + cd $(ORG_MULTIPLE_THENAME) && zip -r $(CACHE_PATH)/$(ORG_MULTIPLE_THENAME).jar . + +# Jenkins plugins typically do not have the version included in the archive name, # so it is important to not include it in the generated test fixture $(CACHE_DIR)/gradle.hpi: mkdir -p $(CACHE_DIR) diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/README.md b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/README.md index c3e3fcc52db..d20ebede03e 100644 --- a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/README.md +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/README.md @@ -1,7 +1,7 @@ # Jar-Metadata test fixtures Each directory is the name of a jar to be created (simply a zip) based on the contents of the directory. -This prevents us from having to create real jars by hand or keep binaries in the repo. This also means we dont need the +This prevents us from having to create real jars by hand or keep binaries in the repo. This also means we don't need the entire jar, only the necessary metadata for testing. ### api-all-2.0.0-sources diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/org.multiple-thename/META-INF/MANIFEST.MF b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/org.multiple-thename/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..525109c7337 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/org.multiple-thename/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +Created-By: Multi diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/org.multiple-thename/META-INF/maven/com.multiple/thename/pom.properties b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/org.multiple-thename/META-INF/maven/com.multiple/thename/pom.properties new file mode 100644 index 00000000000..6f8299f9766 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/org.multiple-thename/META-INF/maven/com.multiple/thename/pom.properties @@ -0,0 +1,3 @@ +version=10.11.12 +groupId=com.multiple +artifactId=thename \ No newline at end of file diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/org.multiple-thename/META-INF/maven/com.multiple/thename/pom.xml b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/org.multiple-thename/META-INF/maven/com.multiple/thename/pom.xml new file mode 100644 index 00000000000..ea01735f7c4 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/org.multiple-thename/META-INF/maven/com.multiple/thename/pom.xml @@ -0,0 +1,8 @@ + + + 4.0.0 + + com.multiple + thename + 10.11.12 + diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/org.multiple-thename/META-INF/maven/org.multiple/thename/pom.properties b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/org.multiple-thename/META-INF/maven/org.multiple/thename/pom.properties new file mode 100644 index 00000000000..72e40e4c913 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/org.multiple-thename/META-INF/maven/org.multiple/thename/pom.properties @@ -0,0 +1,3 @@ +version=10.11.12 +groupId=org.multiple +artifactId=thename diff --git a/syft/pkg/cataloger/java/test-fixtures/jar-metadata/org.multiple-thename/META-INF/maven/org.multiple/thename/pom.xml b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/org.multiple-thename/META-INF/maven/org.multiple/thename/pom.xml new file mode 100644 index 00000000000..31522832243 --- /dev/null +++ b/syft/pkg/cataloger/java/test-fixtures/jar-metadata/org.multiple-thename/META-INF/maven/org.multiple/thename/pom.xml @@ -0,0 +1,8 @@ + + + 4.0.0 + + org.multiple + thename + 10.11.12 + diff --git a/syft/pkg/cataloger/javascript/package.go b/syft/pkg/cataloger/javascript/package.go index ed901fc8017..f74a5da9aa5 100644 --- a/syft/pkg/cataloger/javascript/package.go +++ b/syft/pkg/cataloger/javascript/package.go @@ -25,6 +25,39 @@ func newPackageJSONPackage(ctx context.Context, u packageJSON, indexLocation fil } license := pkg.NewLicensesFromLocationWithContext(ctx, indexLocation, licenseCandidates...) + // Handle author, authors, contributors, and maintainers fields + var authorParts []string + + // Add a single author field if it exists + if u.Author.Name != "" || u.Author.Email != "" || u.Author.URL != "" { + if authStr := u.Author.AuthorString(); authStr != "" { + authorParts = append(authorParts, authStr) + } + } + + // Add authors field if it exists + if len(u.Authors) > 0 { + if authorsStr := u.Authors.String(); authorsStr != "" { + authorParts = append(authorParts, authorsStr) + } + } + + // Add contributors field if it exists + if len(u.Contributors) > 0 { + if contributorsStr := u.Contributors.String(); contributorsStr != "" { + authorParts = append(authorParts, contributorsStr) + } + } + + // Add maintainers field if it exists + if len(u.Maintainers) > 0 { + if maintainersStr := u.Maintainers.String(); maintainersStr != "" { + authorParts = append(authorParts, maintainersStr) + } + } + + authorInfo := strings.Join(authorParts, ", ") + p := pkg.Package{ Name: u.Name, Version: u.Version, @@ -37,7 +70,7 @@ func newPackageJSONPackage(ctx context.Context, u packageJSON, indexLocation fil Name: u.Name, Version: u.Version, Description: u.Description, - Author: u.Author.AuthorString(), + Author: authorInfo, Homepage: u.Homepage, URL: u.Repository.URL, Private: u.Private, diff --git a/syft/pkg/cataloger/javascript/parse_package_json.go b/syft/pkg/cataloger/javascript/parse_package_json.go index 5da2c54124e..3a34871a1a9 100644 --- a/syft/pkg/cataloger/javascript/parse_package_json.go +++ b/syft/pkg/cataloger/javascript/parse_package_json.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "regexp" + "strings" "github.com/go-viper/mapstructure/v2" @@ -24,7 +25,10 @@ var _ generic.Parser = parsePackageJSON type packageJSON struct { Version string `json:"version"` Latest []string `json:"latest"` - Author author `json:"author"` + Author person `json:"author"` + Authors people `json:"authors"` + Contributors people `json:"contributors"` + Maintainers people `json:"maintainers"` License json.RawMessage `json:"license"` Licenses json.RawMessage `json:"licenses"` Name string `json:"name"` @@ -35,12 +39,14 @@ type packageJSON struct { Private bool `json:"private"` } -type author struct { +type person struct { Name string `json:"name" mapstructure:"name"` Email string `json:"email" mapstructure:"email"` URL string `json:"url" mapstructure:"url"` } +type people []person + type repository struct { Type string `json:"type" mapstructure:"type"` URL string `json:"url" mapstructure:"url"` @@ -76,9 +82,9 @@ func parsePackageJSON(ctx context.Context, _ file.Resolver, _ *generic.Environme return pkgs, nil, nil } -func (a *author) UnmarshalJSON(b []byte) error { +func (p *person) UnmarshalJSON(b []byte) error { var authorStr string - var auth author + var auth person if err := json.Unmarshal(b, &authorStr); err == nil { // successfully parsed as a string, now parse that string into fields @@ -97,18 +103,18 @@ func (a *author) UnmarshalJSON(b []byte) error { } } - *a = auth + *p = auth return nil } -func (a *author) AuthorString() string { - result := a.Name - if a.Email != "" { - result += fmt.Sprintf(" <%s>", a.Email) +func (p *person) AuthorString() string { + result := p.Name + if p.Email != "" { + result += fmt.Sprintf(" <%s>", p.Email) } - if a.URL != "" { - result += fmt.Sprintf(" (%s)", a.URL) + if p.URL != "" { + result += fmt.Sprintf(" (%s)", p.URL) } return result } @@ -210,3 +216,58 @@ func pathContainsNodeModulesDirectory(p string) bool { } return false } + +func (p *people) UnmarshalJSON(b []byte) error { + // Try to unmarshal as an array of strings + var authorStrings []string + if err := json.Unmarshal(b, &authorStrings); err == nil { + // Successfully parsed as an array of strings + auths := make([]person, len(authorStrings)) + for i, authorStr := range authorStrings { + // Parse each string into author fields + fields := internal.MatchNamedCaptureGroups(authorPattern, authorStr) + var auth person + if err := mapstructure.Decode(fields, &auth); err != nil { + return fmt.Errorf("unable to decode package.json author: %w", err) + } + // Trim whitespace from name if it was parsed + if auth.Name != "" { + auth.Name = strings.TrimSpace(auth.Name) + } + auths[i] = auth + } + *p = auths + return nil + } + + // Try to unmarshal as an array of objects + var authorObjs []map[string]interface{} + if err := json.Unmarshal(b, &authorObjs); err == nil { + // Successfully parsed as an array of objects + auths := make([]person, len(authorObjs)) + for i, fields := range authorObjs { + var auth person + if err := mapstructure.Decode(fields, &auth); err != nil { + return fmt.Errorf("unable to decode package.json author object: %w", err) + } + auths[i] = auth + } + *p = auths + return nil + } + + // If we get here, it means neither format matched + return fmt.Errorf("unable to parse package.json authors field: expected array of strings or array of objects") +} + +func (p people) String() string { + if len(p) == 0 { + return "" + } + + authorStrings := make([]string, len(p)) + for i, auth := range p { + authorStrings[i] = auth.AuthorString() + } + return strings.Join(authorStrings, ", ") +} diff --git a/syft/pkg/cataloger/javascript/parse_package_json_test.go b/syft/pkg/cataloger/javascript/parse_package_json_test.go index 7764cde5f35..01da032a9a5 100644 --- a/syft/pkg/cataloger/javascript/parse_package_json_test.go +++ b/syft/pkg/cataloger/javascript/parse_package_json_test.go @@ -152,7 +152,7 @@ func TestParsePackageJSON(t *testing.T) { Metadata: pkg.NpmPackage{ Name: "function-bind", Version: "1.1.1", - Author: "Raynos ", + Author: "Raynos , Raynos, Jordan Harband (https://github.com/ljharb)", Homepage: "https://github.com/Raynos/function-bind", URL: "git://github.com/Raynos/function-bind.git", Description: "Implementation of Function.prototype.bind", @@ -202,6 +202,132 @@ func TestParsePackageJSON(t *testing.T) { }, }, }, + { + Fixture: "test-fixtures/pkg-json/package-authors-array.json", + ExpectedPkg: pkg.Package{ + Name: "npm", + Version: "6.14.6", + PURL: "pkg:npm/npm@6.14.6", + Type: pkg.NpmPkg, + Licenses: pkg.NewLicenseSet( + pkg.NewLicenseFromLocationsWithContext(ctx, "Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package-authors-array.json")), + ), + Language: pkg.JavaScript, + Metadata: pkg.NpmPackage{ + Name: "npm", + Version: "6.14.6", + Author: "Harry Potter (http://youknowwho.com/), John Smith (http://awebsite.com/)", + Homepage: "https://docs.npmjs.com/", + URL: "https://github.com/npm/cli", + Description: "a package manager for JavaScript", + }, + }, + }, + { + Fixture: "test-fixtures/pkg-json/package-authors-objects.json", + ExpectedPkg: pkg.Package{ + Name: "npm", + Version: "6.14.6", + PURL: "pkg:npm/npm@6.14.6", + Type: pkg.NpmPkg, + Licenses: pkg.NewLicenseSet( + pkg.NewLicenseFromLocationsWithContext(ctx, "Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package-authors-objects.json")), + ), + Language: pkg.JavaScript, + Metadata: pkg.NpmPackage{ + Name: "npm", + Version: "6.14.6", + Author: "Harry Potter (http://youknowwho.com/), John Smith (http://awebsite.com/)", + Homepage: "https://docs.npmjs.com/", + URL: "https://github.com/npm/cli", + Description: "a package manager for JavaScript", + }, + }, + }, + { + Fixture: "test-fixtures/pkg-json/package-both-author-and-authors.json", + ExpectedPkg: pkg.Package{ + Name: "npm", + Version: "6.14.6", + PURL: "pkg:npm/npm@6.14.6", + Type: pkg.NpmPkg, + Licenses: pkg.NewLicenseSet( + pkg.NewLicenseFromLocationsWithContext(ctx, "Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package-both-author-and-authors.json")), + ), + Language: pkg.JavaScript, + Metadata: pkg.NpmPackage{ + Name: "npm", + Version: "6.14.6", + Author: "Isaac Z. Schlueter (http://blog.izs.me), Harry Potter (http://youknowwho.com/), John Smith (http://awebsite.com/)", + Homepage: "https://docs.npmjs.com/", + URL: "https://github.com/npm/cli", + Description: "a package manager for JavaScript", + }, + }, + }, + { + Fixture: "test-fixtures/pkg-json/package-contributors.json", + ExpectedPkg: pkg.Package{ + Name: "npm", + Version: "6.14.6", + PURL: "pkg:npm/npm@6.14.6", + Type: pkg.NpmPkg, + Licenses: pkg.NewLicenseSet( + pkg.NewLicenseFromLocationsWithContext(ctx, "Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package-contributors.json")), + ), + Language: pkg.JavaScript, + Metadata: pkg.NpmPackage{ + Name: "npm", + Version: "6.14.6", + Author: "Alice Contributor , Bob Helper ", + Homepage: "https://docs.npmjs.com/", + URL: "https://github.com/npm/cli", + Description: "a package manager for JavaScript", + }, + }, + }, + { + Fixture: "test-fixtures/pkg-json/package-maintainers.json", + ExpectedPkg: pkg.Package{ + Name: "npm", + Version: "6.14.6", + PURL: "pkg:npm/npm@6.14.6", + Type: pkg.NpmPkg, + Licenses: pkg.NewLicenseSet( + pkg.NewLicenseFromLocationsWithContext(ctx, "Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package-maintainers.json")), + ), + Language: pkg.JavaScript, + Metadata: pkg.NpmPackage{ + Name: "npm", + Version: "6.14.6", + Author: "Charlie Maintainer , Diana Keeper ", + Homepage: "https://docs.npmjs.com/", + URL: "https://github.com/npm/cli", + Description: "a package manager for JavaScript", + }, + }, + }, + { + Fixture: "test-fixtures/pkg-json/package-all-author-fields.json", + ExpectedPkg: pkg.Package{ + Name: "npm", + Version: "6.14.6", + PURL: "pkg:npm/npm@6.14.6", + Type: pkg.NpmPkg, + Licenses: pkg.NewLicenseSet( + pkg.NewLicenseFromLocationsWithContext(ctx, "Artistic-2.0", file.NewLocation("test-fixtures/pkg-json/package-all-author-fields.json")), + ), + Language: pkg.JavaScript, + Metadata: pkg.NpmPackage{ + Name: "npm", + Version: "6.14.6", + Author: "Main Author , Second Author , Contrib One , Maintainer One ", + Homepage: "https://docs.npmjs.com/", + URL: "https://github.com/npm/cli", + Description: "a package manager for JavaScript", + }, + }, + }, } for _, test := range tests { diff --git a/syft/pkg/cataloger/javascript/parse_pnpm_lock.go b/syft/pkg/cataloger/javascript/parse_pnpm_lock.go index 82df0f1affc..706bcdfe974 100644 --- a/syft/pkg/cataloger/javascript/parse_pnpm_lock.go +++ b/syft/pkg/cataloger/javascript/parse_pnpm_lock.go @@ -4,11 +4,11 @@ import ( "context" "fmt" "io" - "regexp" + "sort" "strconv" "strings" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/unknown" @@ -21,92 +21,186 @@ import ( // integrity check var _ generic.Parser = parsePnpmLock -type pnpmLockYaml struct { - Version string `json:"lockfileVersion" yaml:"lockfileVersion"` - Dependencies map[string]interface{} `json:"dependencies" yaml:"dependencies"` - Packages map[string]interface{} `json:"packages" yaml:"packages"` +// pnpmPackage holds the raw name and version extracted from the lockfile. +type pnpmPackage struct { + Name string + Version string } -func parsePnpmLock(ctx context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { - bytes, err := io.ReadAll(reader) - if err != nil { - return nil, nil, fmt.Errorf("failed to load pnpm-lock.yaml file: %w", err) - } +// pnpmLockfileParser defines the interface for parsing different versions of pnpm lockfiles. +type pnpmLockfileParser interface { + Parse(version float64, data []byte) ([]pnpmPackage, error) +} + +// pnpmV6LockYaml represents the structure of pnpm lockfiles for versions < 9.0. +type pnpmV6LockYaml struct { + Dependencies map[string]interface{} `yaml:"dependencies"` + Packages map[string]interface{} `yaml:"packages"` +} - var pkgs []pkg.Package - var lockFile pnpmLockYaml +// pnpmV9LockYaml represents the structure of pnpm lockfiles for versions >= 9.0. +type pnpmV9LockYaml struct { + LockfileVersion string `yaml:"lockfileVersion"` + Importers map[string]interface{} `yaml:"importers"` // Using interface{} for forward compatibility + Packages map[string]interface{} `yaml:"packages"` +} - if err := yaml.Unmarshal(bytes, &lockFile); err != nil { - return nil, nil, fmt.Errorf("failed to parse pnpm-lock.yaml file: %w", err) +// Parse implements the pnpmLockfileParser interface for v6-v8 lockfiles. +func (p *pnpmV6LockYaml) Parse(version float64, data []byte) ([]pnpmPackage, error) { + if err := yaml.Unmarshal(data, p); err != nil { + return nil, fmt.Errorf("failed to unmarshal pnpm v6 lockfile: %w", err) } - lockVersion, _ := strconv.ParseFloat(lockFile.Version, 64) - - for name, info := range lockFile.Dependencies { - version := "" - - switch info := info.(type) { - case string: - version = info - case map[string]interface{}: - v, ok := info["version"] - if !ok { - break - } - ver, ok := v.(string) - if ok { - version = parseVersion(ver) - } - default: - log.Tracef("unsupported pnpm dependency type: %+v", info) - continue - } + packages := make(map[string]pnpmPackage) - if hasPkg(pkgs, name, version) { + // Direct dependencies + for name, info := range p.Dependencies { + ver, err := parseVersionField(name, info) + if err != nil { + log.WithFields("package", name, "error", err).Trace("unable to parse pnpm dependency") continue } - - pkgs = append(pkgs, newPnpmPackage(ctx, resolver, reader.Location, name, version)) + key := name + "@" + ver + packages[key] = pnpmPackage{Name: name, Version: ver} } - packageNameRegex := regexp.MustCompile(`^/?([^(]*)(?:\(.*\))*$`) splitChar := "/" - if lockVersion >= 6.0 { + if version >= 6.0 { splitChar = "@" } - // parse packages from packages section of pnpm-lock.yaml - for nameVersion := range lockFile.Packages { - nameVersion = packageNameRegex.ReplaceAllString(nameVersion, "$1") - nameVersionSplit := strings.Split(strings.TrimPrefix(nameVersion, "/"), splitChar) + // All transitive dependencies + for key := range p.Packages { + name, ver, ok := parsePnpmPackageKey(key, splitChar) + if !ok { + log.WithFields("key", key).Trace("unable to parse pnpm package key") + continue + } + pkgKey := name + "@" + ver + packages[pkgKey] = pnpmPackage{Name: name, Version: ver} + } - // last element in split array is version - version := nameVersionSplit[len(nameVersionSplit)-1] + return toSortedSlice(packages), nil +} + +// Parse implements the PnpmLockfileParser interface for v9+ lockfiles. +func (p *pnpmV9LockYaml) Parse(_ float64, data []byte) ([]pnpmPackage, error) { + if err := yaml.Unmarshal(data, p); err != nil { + return nil, fmt.Errorf("failed to unmarshal pnpm v9 lockfile: %w", err) + } - // construct name from all array items other than last item (version) - name := strings.Join(nameVersionSplit[:len(nameVersionSplit)-1], splitChar) + packages := make(map[string]pnpmPackage) - if hasPkg(pkgs, name, version) { + // In v9, all resolved dependencies are listed in the top-level "packages" field. + // The key format is like /@ or /@(). + for key := range p.Packages { + // The separator for name and version is consistently '@' in v9+ keys. + name, ver, ok := parsePnpmPackageKey(key, "@") + if !ok { + log.WithFields("key", key).Trace("unable to parse pnpm v9 package key") continue } + pkgKey := name + "@" + ver + packages[pkgKey] = pnpmPackage{Name: name, Version: ver} + } + + return toSortedSlice(packages), nil +} - pkgs = append(pkgs, newPnpmPackage(ctx, resolver, reader.Location, name, version)) +// newPnpmLockfileParser is a factory function that returns the correct parser for the given lockfile version. +func newPnpmLockfileParser(version float64) pnpmLockfileParser { + if version >= 9.0 { + return &pnpmV9LockYaml{} } + return &pnpmV6LockYaml{} +} - pkg.Sort(pkgs) +// parsePnpmLock is the main parser function for pnpm-lock.yaml files. +func parsePnpmLock(ctx context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + data, err := io.ReadAll(reader) + if err != nil { + return nil, nil, fmt.Errorf("failed to load pnpm-lock.yaml file: %w", err) + } + + var lockfile struct { + Version string `yaml:"lockfileVersion"` + } + if err := yaml.Unmarshal(data, &lockfile); err != nil { + return nil, nil, fmt.Errorf("failed to parse pnpm-lock.yaml version: %w", err) + } + + version, err := strconv.ParseFloat(lockfile.Version, 64) + if err != nil { + return nil, nil, fmt.Errorf("invalid lockfile version %q: %w", lockfile.Version, err) + } + + parser := newPnpmLockfileParser(version) + pnpmPkgs, err := parser.Parse(version, data) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse pnpm-lock.yaml file: %w", err) + } - return pkgs, nil, unknown.IfEmptyf(pkgs, "unable to determine packages") + packages := make([]pkg.Package, len(pnpmPkgs)) + for i, p := range pnpmPkgs { + packages[i] = newPnpmPackage(ctx, resolver, reader.Location, p.Name, p.Version) + } + + return packages, nil, unknown.IfEmptyf(packages, "unable to determine packages") } -func hasPkg(pkgs []pkg.Package, name, version string) bool { - for _, p := range pkgs { - if p.Name == name && p.Version == version { - return true +// parseVersionField extracts the version string from a dependency entry. +func parseVersionField(name string, info interface{}) (string, error) { + switch v := info.(type) { + case string: + return v, nil + case map[string]interface{}: + if ver, ok := v["version"].(string); ok { + // e.g., "1.2.3(react@17.0.0)" -> "1.2.3" + return strings.SplitN(ver, "(", 2)[0], nil } + return "", fmt.Errorf("version field is not a string for %q", name) + default: + return "", fmt.Errorf("unsupported dependency type %T for %q", info, name) } - return false } -func parseVersion(version string) string { - return strings.SplitN(version, "(", 2)[0] +// parsePnpmPackageKey extracts the package name and version from a lockfile package key. +// Handles formats like: +// - /@babel/runtime/7.16.7 +// - /@types/node@14.18.12 +// - /is-glob@4.0.3 +// - /@babel/helper-plugin-utils@7.24.7(@babel/core@7.24.7) +func parsePnpmPackageKey(key, separator string) (name, version string, ok bool) { + // Strip peer dependency information, e.g., (...) + key = strings.SplitN(key, "(", 2)[0] + + // Strip leading slash + key = strings.TrimPrefix(key, "/") + + parts := strings.Split(key, separator) + if len(parts) < 2 { + return "", "", false + } + + version = parts[len(parts)-1] + name = strings.Join(parts[:len(parts)-1], separator) + + return name, version, true +} + +// toSortedSlice converts the map of packages to a sorted slice for deterministic output. +func toSortedSlice(packages map[string]pnpmPackage) []pnpmPackage { + pkgs := make([]pnpmPackage, 0, len(packages)) + for _, p := range packages { + pkgs = append(pkgs, p) + } + + sort.Slice(pkgs, func(i, j int) bool { + if pkgs[i].Name == pkgs[j].Name { + return pkgs[i].Version < pkgs[j].Version + } + return pkgs[i].Name < pkgs[j].Name + }) + + return pkgs } diff --git a/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go b/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go index 8b5ed7d0ae0..7ba17a54694 100644 --- a/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go +++ b/syft/pkg/cataloger/javascript/parse_pnpm_lock_test.go @@ -145,6 +145,50 @@ func TestParsePnpmV6Lock(t *testing.T) { pkgtest.TestFileParser(t, fixture, parsePnpmLock, expectedPkgs, expectedRelationships) } +func TestParsePnpmLockV9(t *testing.T) { + var expectedRelationships []artifact.Relationship + fixture := "test-fixtures/pnpm-v9/pnpm-lock.yaml" + locationSet := file.NewLocationSet(file.NewLocation(fixture)) + + expected := []pkg.Package{ + { + Name: "@babel/core", + Version: "7.24.7", + PURL: "pkg:npm/%40babel/core@7.24.7", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + }, + { + Name: "@babel/helper-plugin-utils", + Version: "7.24.7", + PURL: "pkg:npm/%40babel/helper-plugin-utils@7.24.7", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + }, + { + Name: "is-positive", + Version: "3.1.0", + PURL: "pkg:npm/is-positive@3.1.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + }, + { + Name: "rollup", + Version: "4.18.0", + PURL: "pkg:npm/rollup@4.18.0", + Locations: locationSet, + Language: pkg.JavaScript, + Type: pkg.NpmPkg, + }, + } + + // TODO: no relationships are under test + pkgtest.TestFileParser(t, fixture, parsePnpmLock, expected, expectedRelationships) +} + func Test_corruptPnpmLock(t *testing.T) { pkgtest.NewCatalogTester(). FromFile(t, "test-fixtures/corrupt/pnpm-lock.yaml"). diff --git a/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-all-author-fields.json b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-all-author-fields.json new file mode 100644 index 00000000000..188e73f8b36 --- /dev/null +++ b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-all-author-fields.json @@ -0,0 +1,24 @@ +{ + "version": "6.14.6", + "name": "npm", + "description": "a package manager for JavaScript", + "homepage": "https://docs.npmjs.com/", + "author": "Main Author ", + "authors": [ + "Second Author " + ], + "contributors": [ + "Contrib One " + ], + "maintainers": [ + { + "name": "Maintainer One", + "email": "maintain1@example.com" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/npm/cli" + }, + "license": "Artistic-2.0" +} \ No newline at end of file diff --git a/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-authors-array.json b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-authors-array.json new file mode 100644 index 00000000000..bce357d548f --- /dev/null +++ b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-authors-array.json @@ -0,0 +1,15 @@ +{ + "version": "6.14.6", + "name": "npm", + "description": "a package manager for JavaScript", + "homepage": "https://docs.npmjs.com/", + "authors": [ + "Harry Potter (http://youknowwho.com/)", + "John Smith (http://awebsite.com/)" + ], + "repository": { + "type": "git", + "url": "https://github.com/npm/cli" + }, + "license": "Artistic-2.0" +} diff --git a/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-authors-objects.json b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-authors-objects.json new file mode 100644 index 00000000000..335b099ddec --- /dev/null +++ b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-authors-objects.json @@ -0,0 +1,23 @@ +{ + "version": "6.14.6", + "name": "npm", + "description": "a package manager for JavaScript", + "homepage": "https://docs.npmjs.com/", + "authors": [ + { + "name": "Harry Potter", + "email": "hp@hogwards.com", + "url": "http://youknowwho.com/" + }, + { + "name": "John Smith", + "email": "j.smith@something.com", + "url": "http://awebsite.com/" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/npm/cli" + }, + "license": "Artistic-2.0" +} diff --git a/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-both-author-and-authors.json b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-both-author-and-authors.json new file mode 100644 index 00000000000..f6fec06946c --- /dev/null +++ b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-both-author-and-authors.json @@ -0,0 +1,16 @@ +{ + "version": "6.14.6", + "name": "npm", + "description": "a package manager for JavaScript", + "homepage": "https://docs.npmjs.com/", + "author": "Isaac Z. Schlueter (http://blog.izs.me)", + "authors": [ + "Harry Potter (http://youknowwho.com/)", + "John Smith (http://awebsite.com/)" + ], + "repository": { + "type": "git", + "url": "https://github.com/npm/cli" + }, + "license": "Artistic-2.0" +} diff --git a/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-contributors.json b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-contributors.json new file mode 100644 index 00000000000..b1378afb674 --- /dev/null +++ b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-contributors.json @@ -0,0 +1,15 @@ +{ + "version": "6.14.6", + "name": "npm", + "description": "a package manager for JavaScript", + "homepage": "https://docs.npmjs.com/", + "contributors": [ + "Alice Contributor ", + "Bob Helper " + ], + "repository": { + "type": "git", + "url": "https://github.com/npm/cli" + }, + "license": "Artistic-2.0" +} \ No newline at end of file diff --git a/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-maintainers.json b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-maintainers.json new file mode 100644 index 00000000000..88cd5a6b74e --- /dev/null +++ b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-maintainers.json @@ -0,0 +1,21 @@ +{ + "version": "6.14.6", + "name": "npm", + "description": "a package manager for JavaScript", + "homepage": "https://docs.npmjs.com/", + "maintainers": [ + { + "name": "Charlie Maintainer", + "email": "charlie@example.com" + }, + { + "name": "Diana Keeper", + "email": "diana@example.com" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/npm/cli" + }, + "license": "Artistic-2.0" +} \ No newline at end of file diff --git a/syft/pkg/cataloger/javascript/test-fixtures/pnpm-v9/pnpm-lock.yaml b/syft/pkg/cataloger/javascript/test-fixtures/pnpm-v9/pnpm-lock.yaml new file mode 100644 index 00000000000..19b4b02e4ee --- /dev/null +++ b/syft/pkg/cataloger/javascript/test-fixtures/pnpm-v9/pnpm-lock.yaml @@ -0,0 +1,31 @@ +lockfileVersion: '9.0' + +importers: + .: + dependencies: + is-positive: + specifier: ^3.1.0 + version: 3.1.0 + rollup: + specifier: ^4.18.0 + version: 4.18.0 + +packages: + /@babel/core@7.24.7: + resolution: {integrity: sha512-4RjkiFFI42+268iBv2nC+iMLTJGQW3u9P7YvA3x/6MDrJ9IYZ8I/xx5a2GIhY5gBTOcI4iC5S5in2fGjE+P4Yw==} + dev: false + + /@babel/helper-plugin-utils@7.24.7(@babel/core@7.24.7): + resolution: {integrity: sha512-8A2+zKm53/3w4rwbX11FMW/yFS6c5Vam02P/dw01aK6KbwkKqBaIt3eEATiKtn9I2uS1itk8/aZ2yZ/kURee4Q==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dev: false + + /is-positive@3.1.0: + resolution: {integrity: sha512-9ffLCf_f5sopimAhg2g91a7b9Rw5A1aA9eI6S391S3VEzYw99I3iKjcZGxLp25s0cRxNBV5aL2mhn7421SSlA==} + dev: false + + /rollup@4.18.0: + resolution: {integrity: sha512-QpQY2Q5i0y0Q3RoAvoChE/R5iN2k05N//bNvQbC2XvRjHFT1qWJ2r3n1bNqE+gGRJaeuQf0BxE42D7CyuLh3ZQ==} + hasBin: true + dev: false diff --git a/syft/pkg/cataloger/php/interpreter_cataloger.go b/syft/pkg/cataloger/php/interpreter_cataloger.go index a4abe243342..4c1619eb3f5 100644 --- a/syft/pkg/cataloger/php/interpreter_cataloger.go +++ b/syft/pkg/cataloger/php/interpreter_cataloger.go @@ -219,7 +219,7 @@ func (p interpreterCataloger) getClassifier(realPath string) (string, *binutils. return name, &binutils.Classifier{ Class: fmt.Sprintf("php-ext-%s-binary", name), - EvidenceMatcher: binutils.FileContentsVersionMatcher(match, p.name), + EvidenceMatcher: binutils.FileContentsVersionMatcher(p.name, match), Package: name, PURL: packageurl.PackageURL{ Type: packageurl.TypeGeneric, diff --git a/syft/pkg/cataloger/python/cataloger.go b/syft/pkg/cataloger/python/cataloger.go index 07bd231b7ed..18c343585bc 100644 --- a/syft/pkg/cataloger/python/cataloger.go +++ b/syft/pkg/cataloger/python/cataloger.go @@ -27,7 +27,8 @@ func NewPackageCataloger(cfg CatalogerConfig) pkg.Cataloger { WithParserByGlobs(rqp.parseRequirementsTxt, "**/*requirements*.txt"). WithParserByGlobs(parsePoetryLock, "**/poetry.lock"). WithParserByGlobs(parsePipfileLock, "**/Pipfile.lock"). - WithParserByGlobs(parseSetup, "**/setup.py") + WithParserByGlobs(parseSetup, "**/setup.py"). + WithParserByGlobs(parseUvLock, "**/uv.lock") } // NewInstalledPackageCataloger returns a new cataloger for python packages within egg or wheel installation directories. diff --git a/syft/pkg/cataloger/python/cataloger_test.go b/syft/pkg/cataloger/python/cataloger_test.go index 49d7ec5a728..b3b1d424786 100644 --- a/syft/pkg/cataloger/python/cataloger_test.go +++ b/syft/pkg/cataloger/python/cataloger_test.go @@ -453,6 +453,7 @@ func Test_IndexCataloger_Globs(t *testing.T) { "src/setup.py", "src/poetry.lock", "src/Pipfile.lock", + "src/uv.lock", }, }, } @@ -497,19 +498,19 @@ func Test_PackageCataloger_Globs(t *testing.T) { } } -func Test_PoetryLockCataloger_Relationships(t *testing.T) { +func Test_PackageCataloger_Relationships(t *testing.T) { tests := []struct { name string fixture string expectedRelationships []string }{ { - name: "no dependencies", + name: "poetry - no dependencies", fixture: "test-fixtures/poetry/dev-deps", expectedRelationships: nil, }, { - name: "simple dependencies", + name: "poetry - simple dependencies", fixture: "test-fixtures/poetry/simple-deps", expectedRelationships: []string{ "certifi @ 2024.2.2 (.) [dependency-of] requests @ 2.32.2 (.)", @@ -519,7 +520,7 @@ func Test_PoetryLockCataloger_Relationships(t *testing.T) { }, }, { - name: "multiple extras", + name: "poetry - multiple extras", fixture: "test-fixtures/poetry/multiple-extras", expectedRelationships: []string{ "anyio @ 4.3.0 (.) [dependency-of] anyio @ 4.3.0 (.)", @@ -546,7 +547,7 @@ func Test_PoetryLockCataloger_Relationships(t *testing.T) { }, }, { - name: "nested extras", + name: "poetry - nested extras", fixture: "test-fixtures/poetry/nested-extras", expectedRelationships: []string{ "annotated-types @ 0.7.0 (.) [dependency-of] pydantic @ 2.7.1 (.)", @@ -626,7 +627,7 @@ func Test_PoetryLockCataloger_Relationships(t *testing.T) { }, }, { - name: "conflicting extras", + name: "poetry - conflicting extras", fixture: "test-fixtures/poetry/conflicting-with-extras", expectedRelationships: []string{ "anyio @ 4.3.0 (.) [dependency-of] anyio @ 4.3.0 (.)", @@ -679,6 +680,159 @@ func Test_PoetryLockCataloger_Relationships(t *testing.T) { "rich @ 0.3.3 (.) [dependency-of] httpx @ 0.27.0 (.)", }, }, + { + name: "uv - simple dependencies", + fixture: "test-fixtures/uv/simple-deps", + expectedRelationships: []string{ + "certifi @ 2025.1.31 (.) [dependency-of] requests @ 2.32.3 (.)", + "charset-normalizer @ 3.4.1 (.) [dependency-of] requests @ 2.32.3 (.)", + "idna @ 3.10 (.) [dependency-of] requests @ 2.32.3 (.)", + "requests @ 2.32.3 (.) [dependency-of] testpkg @ 0.1.0 (.)", + "urllib3 @ 2.3.0 (.) [dependency-of] requests @ 2.32.3 (.)", + }, + }, + { + name: "uv - multiple extras", + fixture: "test-fixtures/uv/multiple-extras", + expectedRelationships: []string{ + "anyio @ 4.9.0 (.) [dependency-of] httpx @ 0.28.1 (.)", + "brotli @ 1.1.0 (.) [dependency-of] httpx @ 0.28.1 (.)", + "brotlicffi @ 1.1.0.0 (.) [dependency-of] httpx @ 0.28.1 (.)", + "certifi @ 2025.1.31 (.) [dependency-of] httpcore @ 1.0.7 (.)", + "certifi @ 2025.1.31 (.) [dependency-of] httpx @ 0.28.1 (.)", + "cffi @ 1.17.1 (.) [dependency-of] brotlicffi @ 1.1.0.0 (.)", + "h11 @ 0.14.0 (.) [dependency-of] httpcore @ 1.0.7 (.)", + "h2 @ 4.2.0 (.) [dependency-of] httpx @ 0.28.1 (.)", + "hpack @ 4.1.0 (.) [dependency-of] h2 @ 4.2.0 (.)", + "httpcore @ 1.0.7 (.) [dependency-of] httpx @ 0.28.1 (.)", + "httpx @ 0.28.1 (.) [dependency-of] testpkg @ 0.1.0 (.)", + "hyperframe @ 6.1.0 (.) [dependency-of] h2 @ 4.2.0 (.)", + "idna @ 3.10 (.) [dependency-of] anyio @ 4.9.0 (.)", + "idna @ 3.10 (.) [dependency-of] httpx @ 0.28.1 (.)", + "pycparser @ 2.22 (.) [dependency-of] cffi @ 1.17.1 (.)", + "sniffio @ 1.3.1 (.) [dependency-of] anyio @ 4.9.0 (.)", + "socksio @ 1.0.0 (.) [dependency-of] httpx @ 0.28.1 (.)", + "typing-extensions @ 4.13.0 (.) [dependency-of] anyio @ 4.9.0 (.)", + }, + }, + { + name: "uv - nested extras", + fixture: "test-fixtures/uv/nested-extras", + expectedRelationships: []string{ + "annotated-types @ 0.7.0 (.) [dependency-of] pydantic @ 2.11.0 (.)", + "anyio @ 4.9.0 (.) [dependency-of] httpx @ 0.28.1 (.)", + "anyio @ 4.9.0 (.) [dependency-of] starlette @ 0.37.2 (.)", + "anyio @ 4.9.0 (.) [dependency-of] watchfiles @ 1.0.4 (.)", + "certifi @ 2025.1.31 (.) [dependency-of] httpcore @ 1.0.7 (.)", + "certifi @ 2025.1.31 (.) [dependency-of] httpx @ 0.28.1 (.)", + "click @ 8.1.8 (.) [dependency-of] rich-toolkit @ 0.14.0 (.)", + "click @ 8.1.8 (.) [dependency-of] typer @ 0.15.2 (.)", + "click @ 8.1.8 (.) [dependency-of] uvicorn @ 0.34.0 (.)", + "colorama @ 0.4.6 (.) [dependency-of] click @ 8.1.8 (.)", + "colorama @ 0.4.6 (.) [dependency-of] uvicorn @ 0.34.0 (.)", // proof of uvicorn[standard] + "dnspython @ 2.7.0 (.) [dependency-of] email-validator @ 2.2.0 (.)", + "email-validator @ 2.2.0 (.) [dependency-of] fastapi @ 0.111.1 (.)", + "fastapi @ 0.111.1 (.) [dependency-of] testpkg @ 0.1.0 (.)", + "fastapi-cli @ 0.0.7 (.) [dependency-of] fastapi @ 0.111.1 (.)", + "h11 @ 0.14.0 (.) [dependency-of] httpcore @ 1.0.7 (.)", + "h11 @ 0.14.0 (.) [dependency-of] uvicorn @ 0.34.0 (.)", + "httpcore @ 1.0.7 (.) [dependency-of] httpx @ 0.28.1 (.)", + "httptools @ 0.6.4 (.) [dependency-of] uvicorn @ 0.34.0 (.)", // proof of uvicorn[standard] + "httpx @ 0.28.1 (.) [dependency-of] fastapi @ 0.111.1 (.)", + "idna @ 3.10 (.) [dependency-of] anyio @ 4.9.0 (.)", + "idna @ 3.10 (.) [dependency-of] email-validator @ 2.2.0 (.)", + "idna @ 3.10 (.) [dependency-of] httpx @ 0.28.1 (.)", + "itsdangerous @ 2.2.0 (.) [dependency-of] fastapi @ 0.111.1 (.)", + "jinja2 @ 3.1.6 (.) [dependency-of] fastapi @ 0.111.1 (.)", + "markdown-it-py @ 3.0.0 (.) [dependency-of] rich @ 13.9.4 (.)", + "markupsafe @ 3.0.2 (.) [dependency-of] jinja2 @ 3.1.6 (.)", + "mdurl @ 0.1.2 (.) [dependency-of] markdown-it-py @ 3.0.0 (.)", + "orjson @ 3.10.16 (.) [dependency-of] fastapi @ 0.111.1 (.)", + "pydantic @ 2.11.0 (.) [dependency-of] fastapi @ 0.111.1 (.)", + "pydantic @ 2.11.0 (.) [dependency-of] pydantic-extra-types @ 2.10.3 (.)", + "pydantic @ 2.11.0 (.) [dependency-of] pydantic-settings @ 2.8.1 (.)", + "pydantic-core @ 2.33.0 (.) [dependency-of] pydantic @ 2.11.0 (.)", + "pydantic-extra-types @ 2.10.3 (.) [dependency-of] fastapi @ 0.111.1 (.)", + "pydantic-settings @ 2.8.1 (.) [dependency-of] fastapi @ 0.111.1 (.)", + "pygments @ 2.19.1 (.) [dependency-of] rich @ 13.9.4 (.)", + "python-dotenv @ 1.1.0 (.) [dependency-of] pydantic-settings @ 2.8.1 (.)", + "python-dotenv @ 1.1.0 (.) [dependency-of] uvicorn @ 0.34.0 (.)", // proof of uvicorn[standard] + "python-multipart @ 0.0.20 (.) [dependency-of] fastapi @ 0.111.1 (.)", + "pyyaml @ 6.0.2 (.) [dependency-of] fastapi @ 0.111.1 (.)", + "pyyaml @ 6.0.2 (.) [dependency-of] uvicorn @ 0.34.0 (.)", // proof of uvicorn[standard] + "rich @ 13.9.4 (.) [dependency-of] rich-toolkit @ 0.14.0 (.)", + "rich @ 13.9.4 (.) [dependency-of] typer @ 0.15.2 (.)", + "rich-toolkit @ 0.14.0 (.) [dependency-of] fastapi-cli @ 0.0.7 (.)", + "shellingham @ 1.5.4 (.) [dependency-of] typer @ 0.15.2 (.)", + "sniffio @ 1.3.1 (.) [dependency-of] anyio @ 4.9.0 (.)", + "starlette @ 0.37.2 (.) [dependency-of] fastapi @ 0.111.1 (.)", + "typer @ 0.15.2 (.) [dependency-of] fastapi-cli @ 0.0.7 (.)", + "typing-extensions @ 4.13.0 (.) [dependency-of] anyio @ 4.9.0 (.)", + "typing-extensions @ 4.13.0 (.) [dependency-of] fastapi @ 0.111.1 (.)", + "typing-extensions @ 4.13.0 (.) [dependency-of] pydantic @ 2.11.0 (.)", + "typing-extensions @ 4.13.0 (.) [dependency-of] pydantic-core @ 2.33.0 (.)", + "typing-extensions @ 4.13.0 (.) [dependency-of] pydantic-extra-types @ 2.10.3 (.)", + "typing-extensions @ 4.13.0 (.) [dependency-of] rich-toolkit @ 0.14.0 (.)", + "typing-extensions @ 4.13.0 (.) [dependency-of] typer @ 0.15.2 (.)", + "typing-extensions @ 4.13.0 (.) [dependency-of] typing-inspection @ 0.4.0 (.)", + "typing-inspection @ 0.4.0 (.) [dependency-of] pydantic @ 2.11.0 (.)", + "ujson @ 5.10.0 (.) [dependency-of] fastapi @ 0.111.1 (.)", + "uvicorn @ 0.34.0 (.) [dependency-of] fastapi @ 0.111.1 (.)", + "uvicorn @ 0.34.0 (.) [dependency-of] fastapi-cli @ 0.0.7 (.)", + "uvloop @ 0.21.0 (.) [dependency-of] uvicorn @ 0.34.0 (.)", // proof of uvicorn[standard] + "watchfiles @ 1.0.4 (.) [dependency-of] uvicorn @ 0.34.0 (.)", // proof of uvicorn[standard] + "websockets @ 15.0.1 (.) [dependency-of] uvicorn @ 0.34.0 (.)", // proof of uvicorn[standard] + }, + }, + { + name: "uv - conflicting extras", + fixture: "test-fixtures/uv/conflicting-with-extras", + expectedRelationships: []string{ + "anyio @ 4.6.2.post1 (.) [dependency-of] httpx @ 0.28.1 (.)", + "brotli @ 1.1.0 (.) [dependency-of] httpx @ 0.28.1 (.)", + "brotlicffi @ 1.1.0.0 (.) [dependency-of] httpx @ 0.28.1 (.)", + "certifi @ 2025.1.31 (.) [dependency-of] httpcore @ 1.0.7 (.)", + "certifi @ 2025.1.31 (.) [dependency-of] httpx @ 0.28.1 (.)", + "cffi @ 1.17.1 (.) [dependency-of] brotlicffi @ 1.1.0.0 (.)", + "colorama @ 0.4.6 (.) [dependency-of] rich @ 0.3.3 (.)", + "h11 @ 0.14.0 (.) [dependency-of] httpcore @ 1.0.7 (.)", + "h2 @ 4.2.0 (.) [dependency-of] httpx @ 0.28.1 (.)", + "hpack @ 4.1.0 (.) [dependency-of] h2 @ 4.2.0 (.)", + "httpcore @ 1.0.7 (.) [dependency-of] httpx @ 0.28.1 (.)", + "httpx @ 0.28.1 (.) [dependency-of] testpkg @ 0.1.0 (.)", + "hyperframe @ 6.1.0 (.) [dependency-of] h2 @ 4.2.0 (.)", + "idna @ 3.10 (.) [dependency-of] anyio @ 4.6.2.post1 (.)", + "idna @ 3.10 (.) [dependency-of] httpx @ 0.28.1 (.)", + "pprintpp @ 0.4.0 (.) [dependency-of] rich @ 0.3.3 (.)", + "pycparser @ 2.22 (.) [dependency-of] cffi @ 1.17.1 (.)", + "sniffio @ 1.3.1 (.) [dependency-of] anyio @ 4.6.2.post1 (.)", + "socksio @ 1.0.0 (.) [dependency-of] httpx @ 0.28.1 (.)", + "typing-extensions @ 3.10.0.2 (.) [dependency-of] rich @ 0.3.3 (.)", + // ideally we should NOT see these dependencies. However, they are technically installed in the environment + // and an import is present in httpx for each of these, so in theory they are actually dependencies even + // though our pyproject.toml looks like this: + // + // [tool.poetry.dependencies] + // python = "^3.11" + // httpx = {extras = ["brotli", "http2", "socks"], version = "^0.27.0"} + // pygments = "1.6" + // click = "<8" + // rich = "<10" + // + // note that pygments, click, and rich are installed outside of the allowable ranges for the given + // httpx package version constraints, per the poetry.lock: + // + // # for package httpx + // [package.extras] + // cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] + // + // note: the pyproject.toml and uv.lock state are consistent with each other (just with + // "uv sync" and nothing was forced!) + "click @ 7.1.2 (.) [dependency-of] testpkg @ 0.1.0 (.)", + "pygments @ 1.6 (.) [dependency-of] testpkg @ 0.1.0 (.)", + "rich @ 0.3.3 (.) [dependency-of] testpkg @ 0.1.0 (.)", + }, + }, } for _, test := range tests { diff --git a/syft/pkg/cataloger/python/dependency.go b/syft/pkg/cataloger/python/dependency.go index 53838098a6e..61a3c5d80da 100644 --- a/syft/pkg/cataloger/python/dependency.go +++ b/syft/pkg/cataloger/python/dependency.go @@ -15,7 +15,7 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/internal/dependency" ) -func poetryLockDependencySpecifier(p pkg.Package) dependency.Specification { +func poetryLockDependencySpecifier(p pkg.Package) dependency.Specification { //nolint:dupl // this is very similar to the uv lock dependency specifier, but should remain separate meta, ok := p.Metadata.(pkg.PythonPoetryLockEntry) if !ok { log.Tracef("cataloger failed to extract poetry lock metadata for package %+v", p.Name) diff --git a/syft/pkg/cataloger/python/parse_uv_lock.go b/syft/pkg/cataloger/python/parse_uv_lock.go new file mode 100644 index 00000000000..0890969ab8e --- /dev/null +++ b/syft/pkg/cataloger/python/parse_uv_lock.go @@ -0,0 +1,229 @@ +package python + +import ( + "bytes" + "context" + "fmt" + "io" + "sort" + "strings" + + "github.com/BurntSushi/toml" + + "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/unknown" + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/generic" + "github.com/anchore/syft/syft/pkg/cataloger/internal/dependency" +) + +// We use this to check for the version before we try to parse. +// The TOML library handily ignores everything that isn't mentioend in the struct. +type uvLockFileVersion struct { + Version int `toml:"version"` + Revision int `toml:"revision"` +} + +type uvLockFile struct { + Version int `toml:"version"` + Revision int `toml:"revision"` + RequiresPython string `toml:"requires-python"` + Packages []uvPackage `toml:"package"` +} + +type uvPackage struct { + Name string `toml:"name"` + Version string `toml:"version"` + Source map[string]string `toml:"source"` // Possible key values for Source are: registry, git, direct, path, directory, editable, virtual + Dependencies uvDependencies `toml:"dependencies"` + DevDependencies map[string]uvDependencies `toml:"dev-dependencies"` + OptionalDependencies map[string]uvDependencies `toml:"optional-dependencies"` + Sdist uvDistribution `toml:"sdist"` + Wheels []uvDistribution `toml:"wheels"` + Metadata uvMetadata `toml:"metadata"` +} + +type uvDependencies []struct { + Name string `toml:"name"` + Extras []string `toml:"extra"` + Markers string `toml:"marker"` +} + +type uvDistribution struct { + URL string `toml:"url"` + Hash string `toml:"hash"` + Size int `toml:"size"` +} + +type uvRequiresDist []struct { + Name string `toml:"name"` + Markers string `toml:"marker"` + Extras []string `toml:"extras"` + Specifier string `toml:"specifier"` +} + +type uvMetadata struct { + RequiresDist uvRequiresDist `toml:"requires-dist"` + ProvidesExtras []string `toml:"provides-extras"` +} + +// parseUvLock is a parser function for uv.lock contents, returning all the pakcages discovered +func parseUvLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + pkgs, err := uvLockPackages(reader) + if err != nil { + return nil, nil, err + } + + return pkgs, dependency.Resolve(uvLockDependencySpecifier, pkgs), err +} + +func extractUvIndex(p uvPackage) string { + // This is a map, but there should only be one key, value pair + var rvalue string + for _, value := range p.Source { + rvalue = value + } + + return rvalue +} + +func extractUvDependencies(p uvPackage) []pkg.PythonUvLockDependencyEntry { + var deps []pkg.PythonUvLockDependencyEntry + for _, d := range p.Dependencies { + deps = append(deps, pkg.PythonUvLockDependencyEntry{ + Name: d.Name, + Extras: d.Extras, + Markers: d.Markers, + }) + } + sort.Slice(deps, func(i, j int) bool { + return deps[i].Name < deps[j].Name + }) + return deps +} + +func extractUvExtras(p uvPackage) []pkg.PythonUvLockExtraEntry { + var extras []pkg.PythonUvLockExtraEntry + for name, depsStruct := range p.OptionalDependencies { + var extraDeps []string + for _, deps := range depsStruct { + extraDeps = append(extraDeps, deps.Name) + } + extras = append(extras, pkg.PythonUvLockExtraEntry{ + Name: name, + Dependencies: extraDeps, + }) + } + return extras +} + +func newPythonUvLockEntry(p uvPackage) pkg.PythonUvLockEntry { + return pkg.PythonUvLockEntry{ + Index: extractUvIndex(p), + Dependencies: extractUvDependencies(p), + Extras: extractUvExtras(p), + } +} + +func uvLockPackages(reader file.LocationReadCloser) ([]pkg.Package, error) { + var parsedLockFileVersion uvLockFileVersion + + // we cannot use the reader twice, so we read the contents first --uv.lock files tend to be small enough + contents, err := io.ReadAll(reader) + if err != nil { + return nil, unknown.New(reader.Location, fmt.Errorf("failed to read uv lock file: %w", err)) + } + + _, err = toml.NewDecoder(bytes.NewReader(contents)).Decode(&parsedLockFileVersion) + if err != nil { + return nil, fmt.Errorf("failed to read uv lock version: %w", err) + } + + // We will need to add some logic to parse and branch on different + // lock file versions should they arise, but this gets us + // started down this road for now. + if parsedLockFileVersion.Version > 1 { + return nil, fmt.Errorf("could not parse uv lock file version %d", parsedLockFileVersion.Version) + } + + var parsedLockFile uvLockFile + _, err = toml.NewDecoder(bytes.NewReader(contents)).Decode(&parsedLockFile) + + if err != nil { + return nil, fmt.Errorf("failed to parse uv lock packages: %w", err) + } + + // The uv lock file doesn't store the dependency version in the dependency structure. + // Thus, we need a name -> version map for invoking extractUvDependencies. + // We then, of course, have to pass it down the call stack. + var pkgVerMap = make(map[string]string) + for _, p := range parsedLockFile.Packages { + pkgVerMap[p.Name] = p.Version + } + + var pkgs []pkg.Package + for _, p := range parsedLockFile.Packages { + pkgs = append(pkgs, + newPackageForIndexWithMetadata( + p.Name, + p.Version, + newPythonUvLockEntry(p), + reader.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) + } + + return pkgs, unknown.IfEmptyf(pkgs, "unable to determine packages") +} + +func isDependencyForUvExtra(dep pkg.PythonUvLockDependencyEntry) bool { + return strings.Contains(dep.Markers, "extra ==") +} + +// This is identical to poetryLockDependencySpecifier since it operates on identical +// data structures. Keeping it separate for now since it's always possible for data +// structures to change down the line. +// It *is* possible we may be able to merge the Uv and Poetry data structures +func uvLockDependencySpecifier(p pkg.Package) dependency.Specification { //nolint:dupl // this is very similar to the poetry lock dependency specifier, but should remain separate + meta, ok := p.Metadata.(pkg.PythonUvLockEntry) + if !ok { + log.Tracef("cataloger failed to extract UV lock metadata for package %+v", p.Name) + return dependency.Specification{} + } + + provides := []string{packageRef(p.Name, "")} + + var requires []string + + for _, dep := range meta.Dependencies { + if isDependencyForUvExtra(dep) { + continue + } + + requires = append(requires, packageRef(dep.Name, "")) + + for _, extra := range dep.Extras { + requires = append(requires, packageRef(dep.Name, extra)) + } + } + + var variants []dependency.ProvidesRequires + for _, extra := range meta.Extras { + variants = append(variants, + dependency.ProvidesRequires{ + Provides: []string{packageRef(p.Name, extra.Name)}, + Requires: extractPackageNames(extra.Dependencies), + }, + ) + } + + return dependency.Specification{ + ProvidesRequires: dependency.ProvidesRequires{ + Provides: provides, + Requires: requires, + }, + Variants: variants, + } +} diff --git a/syft/pkg/cataloger/python/parse_uv_lock_test.go b/syft/pkg/cataloger/python/parse_uv_lock_test.go new file mode 100644 index 00000000000..506b9a722c7 --- /dev/null +++ b/syft/pkg/cataloger/python/parse_uv_lock_test.go @@ -0,0 +1,128 @@ +package python + +import ( + "testing" + + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" +) + +func TestParseUvLock(t *testing.T) { + fixture := "test-fixtures/uv/simple-deps/uv.lock" + + locations := file.NewLocationSet(file.NewLocation(fixture)) + + certifi := pkg.Package{ + Name: "certifi", + Version: "2025.1.31", + Locations: locations, + PURL: "pkg:pypi/certifi@2025.1.31", + Language: pkg.Python, + Type: pkg.PythonPkg, + Metadata: pkg.PythonUvLockEntry{Index: "https://pypi.org/simple"}, + } + + charsetNormalizer := pkg.Package{ + Name: "charset-normalizer", + Version: "3.4.1", + Locations: locations, + PURL: "pkg:pypi/charset-normalizer@3.4.1", + Language: pkg.Python, + Type: pkg.PythonPkg, + Metadata: pkg.PythonUvLockEntry{Index: "https://pypi.org/simple"}, + } + + idna := pkg.Package{ + Name: "idna", + Version: "3.10", + Locations: locations, + PURL: "pkg:pypi/idna@3.10", + Language: pkg.Python, + Type: pkg.PythonPkg, + Metadata: pkg.PythonUvLockEntry{Index: "https://pypi.org/simple"}, + } + + requests := pkg.Package{ + Name: "requests", + Version: "2.32.3", + Locations: locations, + PURL: "pkg:pypi/requests@2.32.3", + Language: pkg.Python, + Type: pkg.PythonPkg, + Metadata: pkg.PythonUvLockEntry{ + Index: "https://pypi.org/simple", + Dependencies: []pkg.PythonUvLockDependencyEntry{ + {Name: "certifi"}, + {Name: "charset-normalizer"}, + {Name: "idna"}, + {Name: "urllib3"}, + }, + }, + } + + testpkg := pkg.Package{ + Name: "testpkg", + Version: "0.1.0", + Locations: locations, + PURL: "pkg:pypi/testpkg@0.1.0", + Language: pkg.Python, + Type: pkg.PythonPkg, + Metadata: pkg.PythonUvLockEntry{ + Index: ".", // virtual + Dependencies: []pkg.PythonUvLockDependencyEntry{ + {Name: "requests"}, + }, + }, + } + + urllib3 := pkg.Package{ + Name: "urllib3", + Version: "2.3.0", + Locations: locations, + PURL: "pkg:pypi/urllib3@2.3.0", + Language: pkg.Python, + Type: pkg.PythonPkg, + Metadata: pkg.PythonUvLockEntry{Index: "https://pypi.org/simple"}, + } + + expectedPkgs := []pkg.Package{ + certifi, + charsetNormalizer, + idna, + requests, + testpkg, + urllib3, + } + + expectedRelationships := []artifact.Relationship{ + { + From: certifi, + To: requests, + Type: artifact.DependencyOfRelationship, + }, + { + From: charsetNormalizer, + To: requests, + Type: artifact.DependencyOfRelationship, + }, + { + From: idna, + To: requests, + Type: artifact.DependencyOfRelationship, + }, + { + From: requests, + To: testpkg, + Type: artifact.DependencyOfRelationship, + }, + { + From: urllib3, + To: requests, + Type: artifact.DependencyOfRelationship, + }, + } + + pkgtest.TestFileParser(t, fixture, parseUvLock, expectedPkgs, expectedRelationships) +} diff --git a/syft/pkg/cataloger/python/test-fixtures/glob-paths/src/uv.lock b/syft/pkg/cataloger/python/test-fixtures/glob-paths/src/uv.lock new file mode 100644 index 00000000000..5ffba7b57dc --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/glob-paths/src/uv.lock @@ -0,0 +1 @@ +bogus diff --git a/syft/pkg/cataloger/python/test-fixtures/uv/conflicting-with-extras/pyproject.toml b/syft/pkg/cataloger/python/test-fixtures/uv/conflicting-with-extras/pyproject.toml new file mode 100644 index 00000000000..03933b24eb3 --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/uv/conflicting-with-extras/pyproject.toml @@ -0,0 +1,11 @@ +# fixture is not under test, just used to produde the uv.lock +[project] +name = "testpkg" +version = "0.1.0" + +dependencies = [ + "httpx[brotli,http2,socks]>=0.27.0,<0.30.0", + "pygments==2.15.0", + "click<8", + "rich<10" +] diff --git a/syft/pkg/cataloger/python/test-fixtures/uv/conflicting-with-extras/uv.lock b/syft/pkg/cataloger/python/test-fixtures/uv/conflicting-with-extras/uv.lock new file mode 100644 index 00000000000..d526c333612 --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/uv/conflicting-with-extras/uv.lock @@ -0,0 +1,331 @@ +version = 1 +requires-python = ">=3.11" + +[[package]] +name = "anyio" +version = "4.6.2.post1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "sniffio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/09/45b9b7a6d4e45c6bcb5bf61d19e3ab87df68e0601fa8c5293de3542546cc/anyio-4.6.2.post1.tar.gz", hash = "sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c", size = 173422 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/f5/f2b75d2fc6f1a260f340f0e7c6a060f4dd2961cc16884ed851b0d18da06a/anyio-4.6.2.post1-py3-none-any.whl", hash = "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d", size = 90377 }, +] + +[[package]] +name = "brotli" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2f/c2/f9e977608bdf958650638c3f1e28f85a1b075f075ebbe77db8555463787b/Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724", size = 7372270 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/12/ad41e7fadd5db55459c4c401842b47f7fee51068f86dd2894dd0dcfc2d2a/Brotli-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc", size = 873068 }, + { url = "https://files.pythonhosted.org/packages/95/4e/5afab7b2b4b61a84e9c75b17814198ce515343a44e2ed4488fac314cd0a9/Brotli-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6", size = 446244 }, + { url = "https://files.pythonhosted.org/packages/9d/e6/f305eb61fb9a8580c525478a4a34c5ae1a9bcb12c3aee619114940bc513d/Brotli-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd", size = 2906500 }, + { url = "https://files.pythonhosted.org/packages/3e/4f/af6846cfbc1550a3024e5d3775ede1e00474c40882c7bf5b37a43ca35e91/Brotli-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf", size = 2943950 }, + { url = "https://files.pythonhosted.org/packages/b3/e7/ca2993c7682d8629b62630ebf0d1f3bb3d579e667ce8e7ca03a0a0576a2d/Brotli-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a469274ad18dc0e4d316eefa616d1d0c2ff9da369af19fa6f3daa4f09671fd61", size = 2918527 }, + { url = "https://files.pythonhosted.org/packages/b3/96/da98e7bedc4c51104d29cc61e5f449a502dd3dbc211944546a4cc65500d3/Brotli-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327", size = 2845489 }, + { url = "https://files.pythonhosted.org/packages/e8/ef/ccbc16947d6ce943a7f57e1a40596c75859eeb6d279c6994eddd69615265/Brotli-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd", size = 2914080 }, + { url = "https://files.pythonhosted.org/packages/80/d6/0bd38d758d1afa62a5524172f0b18626bb2392d717ff94806f741fcd5ee9/Brotli-1.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9", size = 2813051 }, + { url = "https://files.pythonhosted.org/packages/14/56/48859dd5d129d7519e001f06dcfbb6e2cf6db92b2702c0c2ce7d97e086c1/Brotli-1.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265", size = 2938172 }, + { url = "https://files.pythonhosted.org/packages/3d/77/a236d5f8cd9e9f4348da5acc75ab032ab1ab2c03cc8f430d24eea2672888/Brotli-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8", size = 2933023 }, + { url = "https://files.pythonhosted.org/packages/f1/87/3b283efc0f5cb35f7f84c0c240b1e1a1003a5e47141a4881bf87c86d0ce2/Brotli-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c247dd99d39e0338a604f8c2b3bc7061d5c2e9e2ac7ba9cc1be5a69cb6cd832f", size = 2935871 }, + { url = "https://files.pythonhosted.org/packages/f3/eb/2be4cc3e2141dc1a43ad4ca1875a72088229de38c68e842746b342667b2a/Brotli-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1b2c248cd517c222d89e74669a4adfa5577e06ab68771a529060cf5a156e9757", size = 2847784 }, + { url = "https://files.pythonhosted.org/packages/66/13/b58ddebfd35edde572ccefe6890cf7c493f0c319aad2a5badee134b4d8ec/Brotli-1.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2a24c50840d89ded6c9a8fdc7b6ed3692ed4e86f1c4a4a938e1e92def92933e0", size = 3034905 }, + { url = "https://files.pythonhosted.org/packages/84/9c/bc96b6c7db824998a49ed3b38e441a2cae9234da6fa11f6ed17e8cf4f147/Brotli-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f31859074d57b4639318523d6ffdca586ace54271a73ad23ad021acd807eb14b", size = 2929467 }, + { url = "https://files.pythonhosted.org/packages/e7/71/8f161dee223c7ff7fea9d44893fba953ce97cf2c3c33f78ba260a91bcff5/Brotli-1.1.0-cp311-cp311-win32.whl", hash = "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50", size = 333169 }, + { url = "https://files.pythonhosted.org/packages/02/8a/fece0ee1057643cb2a5bbf59682de13f1725f8482b2c057d4e799d7ade75/Brotli-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1", size = 357253 }, + { url = "https://files.pythonhosted.org/packages/5c/d0/5373ae13b93fe00095a58efcbce837fd470ca39f703a235d2a999baadfbc/Brotli-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:32d95b80260d79926f5fab3c41701dbb818fde1c9da590e77e571eefd14abe28", size = 815693 }, + { url = "https://files.pythonhosted.org/packages/8e/48/f6e1cdf86751300c288c1459724bfa6917a80e30dbfc326f92cea5d3683a/Brotli-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b760c65308ff1e462f65d69c12e4ae085cff3b332d894637f6273a12a482d09f", size = 422489 }, + { url = "https://files.pythonhosted.org/packages/06/88/564958cedce636d0f1bed313381dfc4b4e3d3f6015a63dae6146e1b8c65c/Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409", size = 873081 }, + { url = "https://files.pythonhosted.org/packages/58/79/b7026a8bb65da9a6bb7d14329fd2bd48d2b7f86d7329d5cc8ddc6a90526f/Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2", size = 446244 }, + { url = "https://files.pythonhosted.org/packages/e5/18/c18c32ecea41b6c0004e15606e274006366fe19436b6adccc1ae7b2e50c2/Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451", size = 2906505 }, + { url = "https://files.pythonhosted.org/packages/08/c8/69ec0496b1ada7569b62d85893d928e865df29b90736558d6c98c2031208/Brotli-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91", size = 2944152 }, + { url = "https://files.pythonhosted.org/packages/ab/fb/0517cea182219d6768113a38167ef6d4eb157a033178cc938033a552ed6d/Brotli-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408", size = 2919252 }, + { url = "https://files.pythonhosted.org/packages/c7/53/73a3431662e33ae61a5c80b1b9d2d18f58dfa910ae8dd696e57d39f1a2f5/Brotli-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0", size = 2845955 }, + { url = "https://files.pythonhosted.org/packages/55/ac/bd280708d9c5ebdbf9de01459e625a3e3803cce0784f47d633562cf40e83/Brotli-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc", size = 2914304 }, + { url = "https://files.pythonhosted.org/packages/76/58/5c391b41ecfc4527d2cc3350719b02e87cb424ef8ba2023fb662f9bf743c/Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180", size = 2814452 }, + { url = "https://files.pythonhosted.org/packages/c7/4e/91b8256dfe99c407f174924b65a01f5305e303f486cc7a2e8a5d43c8bec3/Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248", size = 2938751 }, + { url = "https://files.pythonhosted.org/packages/5a/a6/e2a39a5d3b412938362bbbeba5af904092bf3f95b867b4a3eb856104074e/Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966", size = 2933757 }, + { url = "https://files.pythonhosted.org/packages/13/f0/358354786280a509482e0e77c1a5459e439766597d280f28cb097642fc26/Brotli-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:87a3044c3a35055527ac75e419dfa9f4f3667a1e887ee80360589eb8c90aabb9", size = 2936146 }, + { url = "https://files.pythonhosted.org/packages/80/f7/daf538c1060d3a88266b80ecc1d1c98b79553b3f117a485653f17070ea2a/Brotli-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c5529b34c1c9d937168297f2c1fde7ebe9ebdd5e121297ff9c043bdb2ae3d6fb", size = 2848055 }, + { url = "https://files.pythonhosted.org/packages/ad/cf/0eaa0585c4077d3c2d1edf322d8e97aabf317941d3a72d7b3ad8bce004b0/Brotli-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ca63e1890ede90b2e4454f9a65135a4d387a4585ff8282bb72964fab893f2111", size = 3035102 }, + { url = "https://files.pythonhosted.org/packages/d8/63/1c1585b2aa554fe6dbce30f0c18bdbc877fa9a1bf5ff17677d9cca0ac122/Brotli-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e79e6520141d792237c70bcd7a3b122d00f2613769ae0cb61c52e89fd3443839", size = 2930029 }, + { url = "https://files.pythonhosted.org/packages/5f/3b/4e3fd1893eb3bbfef8e5a80d4508bec17a57bb92d586c85c12d28666bb13/Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0", size = 333276 }, + { url = "https://files.pythonhosted.org/packages/3d/d5/942051b45a9e883b5b6e98c041698b1eb2012d25e5948c58d6bf85b1bb43/Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951", size = 357255 }, + { url = "https://files.pythonhosted.org/packages/0a/9f/fb37bb8ffc52a8da37b1c03c459a8cd55df7a57bdccd8831d500e994a0ca/Brotli-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8bf32b98b75c13ec7cf774164172683d6e7891088f6316e54425fde1efc276d5", size = 815681 }, + { url = "https://files.pythonhosted.org/packages/06/b3/dbd332a988586fefb0aa49c779f59f47cae76855c2d00f450364bb574cac/Brotli-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7bc37c4d6b87fb1017ea28c9508b36bbcb0c3d18b4260fcdf08b200c74a6aee8", size = 422475 }, + { url = "https://files.pythonhosted.org/packages/bb/80/6aaddc2f63dbcf2d93c2d204e49c11a9ec93a8c7c63261e2b4bd35198283/Brotli-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c0ef38c7a7014ffac184db9e04debe495d317cc9c6fb10071f7fefd93100a4f", size = 2906173 }, + { url = "https://files.pythonhosted.org/packages/ea/1d/e6ca79c96ff5b641df6097d299347507d39a9604bde8915e76bf026d6c77/Brotli-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91d7cc2a76b5567591d12c01f019dd7afce6ba8cba6571187e21e2fc418ae648", size = 2943803 }, + { url = "https://files.pythonhosted.org/packages/ac/a3/d98d2472e0130b7dd3acdbb7f390d478123dbf62b7d32bda5c830a96116d/Brotli-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a93dde851926f4f2678e704fadeb39e16c35d8baebd5252c9fd94ce8ce68c4a0", size = 2918946 }, + { url = "https://files.pythonhosted.org/packages/c4/a5/c69e6d272aee3e1423ed005d8915a7eaa0384c7de503da987f2d224d0721/Brotli-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0db75f47be8b8abc8d9e31bc7aad0547ca26f24a54e6fd10231d623f183d089", size = 2845707 }, + { url = "https://files.pythonhosted.org/packages/58/9f/4149d38b52725afa39067350696c09526de0125ebfbaab5acc5af28b42ea/Brotli-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6967ced6730aed543b8673008b5a391c3b1076d834ca438bbd70635c73775368", size = 2936231 }, + { url = "https://files.pythonhosted.org/packages/5a/5a/145de884285611838a16bebfdb060c231c52b8f84dfbe52b852a15780386/Brotli-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7eedaa5d036d9336c95915035fb57422054014ebdeb6f3b42eac809928e40d0c", size = 2848157 }, + { url = "https://files.pythonhosted.org/packages/50/ae/408b6bfb8525dadebd3b3dd5b19d631da4f7d46420321db44cd99dcf2f2c/Brotli-1.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d487f5432bf35b60ed625d7e1b448e2dc855422e87469e3f450aa5552b0eb284", size = 3035122 }, + { url = "https://files.pythonhosted.org/packages/af/85/a94e5cfaa0ca449d8f91c3d6f78313ebf919a0dbd55a100c711c6e9655bc/Brotli-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:832436e59afb93e1836081a20f324cb185836c617659b07b129141a8426973c7", size = 2930206 }, + { url = "https://files.pythonhosted.org/packages/c2/f0/a61d9262cd01351df22e57ad7c34f66794709acab13f34be2675f45bf89d/Brotli-1.1.0-cp313-cp313-win32.whl", hash = "sha256:43395e90523f9c23a3d5bdf004733246fba087f2948f87ab28015f12359ca6a0", size = 333804 }, + { url = "https://files.pythonhosted.org/packages/7e/c1/ec214e9c94000d1c1974ec67ced1c970c148aa6b8d8373066123fc3dbf06/Brotli-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9011560a466d2eb3f5a6e4929cf4a09be405c64154e12df0dd72713f6500e32b", size = 358517 }, +] + +[[package]] +name = "brotlicffi" +version = "1.1.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/9d/70caa61192f570fcf0352766331b735afa931b4c6bc9a348a0925cc13288/brotlicffi-1.1.0.0.tar.gz", hash = "sha256:b77827a689905143f87915310b93b273ab17888fd43ef350d4832c4a71083c13", size = 465192 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/11/7b96009d3dcc2c931e828ce1e157f03824a69fb728d06bfd7b2fc6f93718/brotlicffi-1.1.0.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9b7ae6bd1a3f0df532b6d67ff674099a96d22bc0948955cb338488c31bfb8851", size = 453786 }, + { url = "https://files.pythonhosted.org/packages/d6/e6/a8f46f4a4ee7856fbd6ac0c6fb0dc65ed181ba46cd77875b8d9bbe494d9e/brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19ffc919fa4fc6ace69286e0a23b3789b4219058313cf9b45625016bf7ff996b", size = 2911165 }, + { url = "https://files.pythonhosted.org/packages/be/20/201559dff14e83ba345a5ec03335607e47467b6633c210607e693aefac40/brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9feb210d932ffe7798ee62e6145d3a757eb6233aa9a4e7db78dd3690d7755814", size = 2927895 }, + { url = "https://files.pythonhosted.org/packages/cd/15/695b1409264143be3c933f708a3f81d53c4a1e1ebbc06f46331decbf6563/brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84763dbdef5dd5c24b75597a77e1b30c66604725707565188ba54bab4f114820", size = 2851834 }, + { url = "https://files.pythonhosted.org/packages/b4/40/b961a702463b6005baf952794c2e9e0099bde657d0d7e007f923883b907f/brotlicffi-1.1.0.0-cp37-abi3-win32.whl", hash = "sha256:1b12b50e07c3911e1efa3a8971543e7648100713d4e0971b13631cce22c587eb", size = 341731 }, + { url = "https://files.pythonhosted.org/packages/1c/fa/5408a03c041114ceab628ce21766a4ea882aa6f6f0a800e04ee3a30ec6b9/brotlicffi-1.1.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:994a4f0681bb6c6c3b0925530a1926b7a189d878e6e5e38fae8efa47c5d9c613", size = 366783 }, +] + +[[package]] +name = "certifi" +version = "2025.1.31" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 }, +] + +[[package]] +name = "cffi" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264 }, + { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651 }, + { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259 }, + { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200 }, + { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235 }, + { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721 }, + { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242 }, + { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999 }, + { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242 }, + { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604 }, + { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727 }, + { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400 }, + { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 }, + { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 }, + { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 }, + { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850 }, + { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729 }, + { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256 }, + { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424 }, + { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568 }, + { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736 }, + { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 }, + { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 }, + { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989 }, + { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802 }, + { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792 }, + { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893 }, + { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810 }, + { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200 }, + { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447 }, + { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358 }, + { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469 }, + { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 }, + { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 }, +] + +[[package]] +name = "click" +version = "7.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/27/6f/be940c8b1f1d69daceeb0032fee6c34d7bd70e3e649ccac0951500b4720e/click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", size = 297279 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/3d/fa76db83bf75c4f8d338c2fd15c8d33fdd7ad23a9b5e57eb6c5de26b430e/click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc", size = 82780 }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, +] + +[[package]] +name = "h11" +version = "0.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, +] + +[[package]] +name = "h2" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "hpack" }, + { name = "hyperframe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1b/38/d7f80fd13e6582fb8e0df8c9a653dcc02b03ca34f4d72f34869298c5baf8/h2-4.2.0.tar.gz", hash = "sha256:c8a52129695e88b1a0578d8d2cc6842bbd79128ac685463b887ee278126ad01f", size = 2150682 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/9e/984486f2d0a0bd2b024bf4bc1c62688fcafa9e61991f041fb0e2def4a982/h2-4.2.0-py3-none-any.whl", hash = "sha256:479a53ad425bb29af087f3458a61d30780bc818e4ebcf01f0b536ba916462ed0", size = 60957 }, +] + +[[package]] +name = "hpack" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/48/71de9ed269fdae9c8057e5a4c0aa7402e8bb16f2c6e90b3aa53327b113f8/hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca", size = 51276 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/c6/80c95b1b2b94682a72cbdbfb85b81ae2daffa4291fbfa1b1464502ede10d/hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496", size = 34357 }, +] + +[[package]] +name = "httpcore" +version = "1.0.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6a/41/d7d0a89eb493922c37d343b607bc1b5da7f5be7e383740b4753ad8943e90/httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c", size = 85196 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/f5/72347bc88306acb359581ac4d52f23c0ef445b57157adedb9aee0cd689d2/httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd", size = 78551 }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 }, +] + +[package.optional-dependencies] +brotli = [ + { name = "brotli", marker = "platform_python_implementation == 'CPython'" }, + { name = "brotlicffi", marker = "platform_python_implementation != 'CPython'" }, +] +http2 = [ + { name = "h2" }, +] +socks = [ + { name = "socksio" }, +] + +[[package]] +name = "hyperframe" +version = "6.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/02/e7/94f8232d4a74cc99514c13a9f995811485a6903d48e5d952771ef6322e30/hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08", size = 26566 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/30/47d0bf6072f7252e6521f3447ccfa40b421b6824517f82854703d0f5a98b/hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5", size = 13007 }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, +] + +[[package]] +name = "pprintpp" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/06/1a/7737e7a0774da3c3824d654993cf57adc915cb04660212f03406334d8c0b/pprintpp-0.4.0.tar.gz", hash = "sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403", size = 17995 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/d1/e4ed95fdd3ef13b78630280d9e9e240aeb65cc7c544ec57106149c3942fb/pprintpp-0.4.0-py2.py3-none-any.whl", hash = "sha256:b6b4dcdd0c0c0d75e4d7b2f21a9e933e5b2ce62b26e1a54537f9651ae5a5c01d", size = 16952 }, +] + +[[package]] +name = "pycparser" +version = "2.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552 }, +] + +[[package]] +name = "pygments" +version = "1.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/90/992eb125901873d81440480a7cf40a40aa5f8b2e41a67fbc568db6c21595/Pygments-1.6.tar.gz", hash = "sha256:799ed4caf77516e54440806d8d9cd82a7607dfdf4e4fb643815171a4b5c921c0", size = 1423161 } + +[[package]] +name = "rich" +version = "0.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama" }, + { name = "pprintpp" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a5/c9/bc8ed45b392b94cb654a6463c9f6fbe341b6f2d64d332c6c975dbf6c6cae/rich-0.3.3.tar.gz", hash = "sha256:604edf76a2a7d40c7ecc9af5ae41cee3da3e99532c8d0aa54cc42e017ee7f63a", size = 80684 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/45/9eba49ebc4882d6a04d5a1059122848b1ee4614e40f4c8c485ba42d18726/rich-0.3.3-py3-none-any.whl", hash = "sha256:04f1016b1aba52499104b594c17b1481504bbc7314f8b9ba1a7a9dbf3e8869c4", size = 86726 }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, +] + +[[package]] +name = "socksio" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/5c/48a7d9495be3d1c651198fd99dbb6ce190e2274d0f28b9051307bdec6b85/socksio-1.0.0.tar.gz", hash = "sha256:f88beb3da5b5c38b9890469de67d0cb0f9d494b78b106ca1845f96c10b91c4ac", size = 19055 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/37/c3/6eeb6034408dac0fa653d126c9204ade96b819c936e136c5e8a6897eee9c/socksio-1.0.0-py3-none-any.whl", hash = "sha256:95dc1f15f9b34e8d7b16f06d74b8ccf48f609af32ab33c608d08761c5dcbb1f3", size = 12763 }, +] + +[[package]] +name = "testpkg" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "click" }, + { name = "httpx", extra = ["brotli", "http2", "socks"] }, + { name = "pygments" }, + { name = "rich" }, +] + +[package.metadata] +requires-dist = [ + { name = "click", specifier = "<8" }, + { name = "httpx", extras = ["brotli", "http2", "socks"], specifier = ">=0.27.0,<0.30.0" }, + { name = "pygments", specifier = "==1.6" }, + { name = "rich", specifier = "<10" }, +] + +[[package]] +name = "typing-extensions" +version = "3.10.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ed/12/c5079a15cf5c01d7f4252b473b00f7e68ee711be605b9f001528f0298b98/typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e", size = 46048 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/60/18783336cc7fcdd95dae91d73477830aa53f5d3181ae4fe20491d7fc3199/typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34", size = 26288 }, +] diff --git a/syft/pkg/cataloger/python/test-fixtures/uv/multiple-extras/pyproject.toml b/syft/pkg/cataloger/python/test-fixtures/uv/multiple-extras/pyproject.toml new file mode 100644 index 00000000000..340888799b1 --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/uv/multiple-extras/pyproject.toml @@ -0,0 +1,8 @@ +# fixture is not under test, just used to produde the uv.lock +[project] +name = "testpkg" +version = "0.1.0" + +dependencies = [ + "httpx[brotli,http2,socks]>=0.27.0<0.30.0" +] diff --git a/syft/pkg/cataloger/python/test-fixtures/uv/multiple-extras/uv.lock b/syft/pkg/cataloger/python/test-fixtures/uv/multiple-extras/uv.lock new file mode 100644 index 00000000000..282ec6ca02d --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/uv/multiple-extras/uv.lock @@ -0,0 +1,277 @@ +version = 1 +requires-python = ">=3.11" + +[[package]] +name = "anyio" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "sniffio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916 }, +] + +[[package]] +name = "brotli" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2f/c2/f9e977608bdf958650638c3f1e28f85a1b075f075ebbe77db8555463787b/Brotli-1.1.0.tar.gz", hash = "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724", size = 7372270 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/12/ad41e7fadd5db55459c4c401842b47f7fee51068f86dd2894dd0dcfc2d2a/Brotli-1.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc", size = 873068 }, + { url = "https://files.pythonhosted.org/packages/95/4e/5afab7b2b4b61a84e9c75b17814198ce515343a44e2ed4488fac314cd0a9/Brotli-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6", size = 446244 }, + { url = "https://files.pythonhosted.org/packages/9d/e6/f305eb61fb9a8580c525478a4a34c5ae1a9bcb12c3aee619114940bc513d/Brotli-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd", size = 2906500 }, + { url = "https://files.pythonhosted.org/packages/3e/4f/af6846cfbc1550a3024e5d3775ede1e00474c40882c7bf5b37a43ca35e91/Brotli-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf", size = 2943950 }, + { url = "https://files.pythonhosted.org/packages/b3/e7/ca2993c7682d8629b62630ebf0d1f3bb3d579e667ce8e7ca03a0a0576a2d/Brotli-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a469274ad18dc0e4d316eefa616d1d0c2ff9da369af19fa6f3daa4f09671fd61", size = 2918527 }, + { url = "https://files.pythonhosted.org/packages/b3/96/da98e7bedc4c51104d29cc61e5f449a502dd3dbc211944546a4cc65500d3/Brotli-1.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327", size = 2845489 }, + { url = "https://files.pythonhosted.org/packages/e8/ef/ccbc16947d6ce943a7f57e1a40596c75859eeb6d279c6994eddd69615265/Brotli-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd", size = 2914080 }, + { url = "https://files.pythonhosted.org/packages/80/d6/0bd38d758d1afa62a5524172f0b18626bb2392d717ff94806f741fcd5ee9/Brotli-1.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9", size = 2813051 }, + { url = "https://files.pythonhosted.org/packages/14/56/48859dd5d129d7519e001f06dcfbb6e2cf6db92b2702c0c2ce7d97e086c1/Brotli-1.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265", size = 2938172 }, + { url = "https://files.pythonhosted.org/packages/3d/77/a236d5f8cd9e9f4348da5acc75ab032ab1ab2c03cc8f430d24eea2672888/Brotli-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8", size = 2933023 }, + { url = "https://files.pythonhosted.org/packages/f1/87/3b283efc0f5cb35f7f84c0c240b1e1a1003a5e47141a4881bf87c86d0ce2/Brotli-1.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c247dd99d39e0338a604f8c2b3bc7061d5c2e9e2ac7ba9cc1be5a69cb6cd832f", size = 2935871 }, + { url = "https://files.pythonhosted.org/packages/f3/eb/2be4cc3e2141dc1a43ad4ca1875a72088229de38c68e842746b342667b2a/Brotli-1.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1b2c248cd517c222d89e74669a4adfa5577e06ab68771a529060cf5a156e9757", size = 2847784 }, + { url = "https://files.pythonhosted.org/packages/66/13/b58ddebfd35edde572ccefe6890cf7c493f0c319aad2a5badee134b4d8ec/Brotli-1.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2a24c50840d89ded6c9a8fdc7b6ed3692ed4e86f1c4a4a938e1e92def92933e0", size = 3034905 }, + { url = "https://files.pythonhosted.org/packages/84/9c/bc96b6c7db824998a49ed3b38e441a2cae9234da6fa11f6ed17e8cf4f147/Brotli-1.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f31859074d57b4639318523d6ffdca586ace54271a73ad23ad021acd807eb14b", size = 2929467 }, + { url = "https://files.pythonhosted.org/packages/e7/71/8f161dee223c7ff7fea9d44893fba953ce97cf2c3c33f78ba260a91bcff5/Brotli-1.1.0-cp311-cp311-win32.whl", hash = "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50", size = 333169 }, + { url = "https://files.pythonhosted.org/packages/02/8a/fece0ee1057643cb2a5bbf59682de13f1725f8482b2c057d4e799d7ade75/Brotli-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1", size = 357253 }, + { url = "https://files.pythonhosted.org/packages/5c/d0/5373ae13b93fe00095a58efcbce837fd470ca39f703a235d2a999baadfbc/Brotli-1.1.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:32d95b80260d79926f5fab3c41701dbb818fde1c9da590e77e571eefd14abe28", size = 815693 }, + { url = "https://files.pythonhosted.org/packages/8e/48/f6e1cdf86751300c288c1459724bfa6917a80e30dbfc326f92cea5d3683a/Brotli-1.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b760c65308ff1e462f65d69c12e4ae085cff3b332d894637f6273a12a482d09f", size = 422489 }, + { url = "https://files.pythonhosted.org/packages/06/88/564958cedce636d0f1bed313381dfc4b4e3d3f6015a63dae6146e1b8c65c/Brotli-1.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409", size = 873081 }, + { url = "https://files.pythonhosted.org/packages/58/79/b7026a8bb65da9a6bb7d14329fd2bd48d2b7f86d7329d5cc8ddc6a90526f/Brotli-1.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2", size = 446244 }, + { url = "https://files.pythonhosted.org/packages/e5/18/c18c32ecea41b6c0004e15606e274006366fe19436b6adccc1ae7b2e50c2/Brotli-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451", size = 2906505 }, + { url = "https://files.pythonhosted.org/packages/08/c8/69ec0496b1ada7569b62d85893d928e865df29b90736558d6c98c2031208/Brotli-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91", size = 2944152 }, + { url = "https://files.pythonhosted.org/packages/ab/fb/0517cea182219d6768113a38167ef6d4eb157a033178cc938033a552ed6d/Brotli-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408", size = 2919252 }, + { url = "https://files.pythonhosted.org/packages/c7/53/73a3431662e33ae61a5c80b1b9d2d18f58dfa910ae8dd696e57d39f1a2f5/Brotli-1.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0", size = 2845955 }, + { url = "https://files.pythonhosted.org/packages/55/ac/bd280708d9c5ebdbf9de01459e625a3e3803cce0784f47d633562cf40e83/Brotli-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc", size = 2914304 }, + { url = "https://files.pythonhosted.org/packages/76/58/5c391b41ecfc4527d2cc3350719b02e87cb424ef8ba2023fb662f9bf743c/Brotli-1.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180", size = 2814452 }, + { url = "https://files.pythonhosted.org/packages/c7/4e/91b8256dfe99c407f174924b65a01f5305e303f486cc7a2e8a5d43c8bec3/Brotli-1.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248", size = 2938751 }, + { url = "https://files.pythonhosted.org/packages/5a/a6/e2a39a5d3b412938362bbbeba5af904092bf3f95b867b4a3eb856104074e/Brotli-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966", size = 2933757 }, + { url = "https://files.pythonhosted.org/packages/13/f0/358354786280a509482e0e77c1a5459e439766597d280f28cb097642fc26/Brotli-1.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:87a3044c3a35055527ac75e419dfa9f4f3667a1e887ee80360589eb8c90aabb9", size = 2936146 }, + { url = "https://files.pythonhosted.org/packages/80/f7/daf538c1060d3a88266b80ecc1d1c98b79553b3f117a485653f17070ea2a/Brotli-1.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c5529b34c1c9d937168297f2c1fde7ebe9ebdd5e121297ff9c043bdb2ae3d6fb", size = 2848055 }, + { url = "https://files.pythonhosted.org/packages/ad/cf/0eaa0585c4077d3c2d1edf322d8e97aabf317941d3a72d7b3ad8bce004b0/Brotli-1.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ca63e1890ede90b2e4454f9a65135a4d387a4585ff8282bb72964fab893f2111", size = 3035102 }, + { url = "https://files.pythonhosted.org/packages/d8/63/1c1585b2aa554fe6dbce30f0c18bdbc877fa9a1bf5ff17677d9cca0ac122/Brotli-1.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e79e6520141d792237c70bcd7a3b122d00f2613769ae0cb61c52e89fd3443839", size = 2930029 }, + { url = "https://files.pythonhosted.org/packages/5f/3b/4e3fd1893eb3bbfef8e5a80d4508bec17a57bb92d586c85c12d28666bb13/Brotli-1.1.0-cp312-cp312-win32.whl", hash = "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0", size = 333276 }, + { url = "https://files.pythonhosted.org/packages/3d/d5/942051b45a9e883b5b6e98c041698b1eb2012d25e5948c58d6bf85b1bb43/Brotli-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951", size = 357255 }, + { url = "https://files.pythonhosted.org/packages/0a/9f/fb37bb8ffc52a8da37b1c03c459a8cd55df7a57bdccd8831d500e994a0ca/Brotli-1.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8bf32b98b75c13ec7cf774164172683d6e7891088f6316e54425fde1efc276d5", size = 815681 }, + { url = "https://files.pythonhosted.org/packages/06/b3/dbd332a988586fefb0aa49c779f59f47cae76855c2d00f450364bb574cac/Brotli-1.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7bc37c4d6b87fb1017ea28c9508b36bbcb0c3d18b4260fcdf08b200c74a6aee8", size = 422475 }, + { url = "https://files.pythonhosted.org/packages/bb/80/6aaddc2f63dbcf2d93c2d204e49c11a9ec93a8c7c63261e2b4bd35198283/Brotli-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c0ef38c7a7014ffac184db9e04debe495d317cc9c6fb10071f7fefd93100a4f", size = 2906173 }, + { url = "https://files.pythonhosted.org/packages/ea/1d/e6ca79c96ff5b641df6097d299347507d39a9604bde8915e76bf026d6c77/Brotli-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91d7cc2a76b5567591d12c01f019dd7afce6ba8cba6571187e21e2fc418ae648", size = 2943803 }, + { url = "https://files.pythonhosted.org/packages/ac/a3/d98d2472e0130b7dd3acdbb7f390d478123dbf62b7d32bda5c830a96116d/Brotli-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a93dde851926f4f2678e704fadeb39e16c35d8baebd5252c9fd94ce8ce68c4a0", size = 2918946 }, + { url = "https://files.pythonhosted.org/packages/c4/a5/c69e6d272aee3e1423ed005d8915a7eaa0384c7de503da987f2d224d0721/Brotli-1.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0db75f47be8b8abc8d9e31bc7aad0547ca26f24a54e6fd10231d623f183d089", size = 2845707 }, + { url = "https://files.pythonhosted.org/packages/58/9f/4149d38b52725afa39067350696c09526de0125ebfbaab5acc5af28b42ea/Brotli-1.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6967ced6730aed543b8673008b5a391c3b1076d834ca438bbd70635c73775368", size = 2936231 }, + { url = "https://files.pythonhosted.org/packages/5a/5a/145de884285611838a16bebfdb060c231c52b8f84dfbe52b852a15780386/Brotli-1.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7eedaa5d036d9336c95915035fb57422054014ebdeb6f3b42eac809928e40d0c", size = 2848157 }, + { url = "https://files.pythonhosted.org/packages/50/ae/408b6bfb8525dadebd3b3dd5b19d631da4f7d46420321db44cd99dcf2f2c/Brotli-1.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d487f5432bf35b60ed625d7e1b448e2dc855422e87469e3f450aa5552b0eb284", size = 3035122 }, + { url = "https://files.pythonhosted.org/packages/af/85/a94e5cfaa0ca449d8f91c3d6f78313ebf919a0dbd55a100c711c6e9655bc/Brotli-1.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:832436e59afb93e1836081a20f324cb185836c617659b07b129141a8426973c7", size = 2930206 }, + { url = "https://files.pythonhosted.org/packages/c2/f0/a61d9262cd01351df22e57ad7c34f66794709acab13f34be2675f45bf89d/Brotli-1.1.0-cp313-cp313-win32.whl", hash = "sha256:43395e90523f9c23a3d5bdf004733246fba087f2948f87ab28015f12359ca6a0", size = 333804 }, + { url = "https://files.pythonhosted.org/packages/7e/c1/ec214e9c94000d1c1974ec67ced1c970c148aa6b8d8373066123fc3dbf06/Brotli-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:9011560a466d2eb3f5a6e4929cf4a09be405c64154e12df0dd72713f6500e32b", size = 358517 }, +] + +[[package]] +name = "brotlicffi" +version = "1.1.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/9d/70caa61192f570fcf0352766331b735afa931b4c6bc9a348a0925cc13288/brotlicffi-1.1.0.0.tar.gz", hash = "sha256:b77827a689905143f87915310b93b273ab17888fd43ef350d4832c4a71083c13", size = 465192 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/11/7b96009d3dcc2c931e828ce1e157f03824a69fb728d06bfd7b2fc6f93718/brotlicffi-1.1.0.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9b7ae6bd1a3f0df532b6d67ff674099a96d22bc0948955cb338488c31bfb8851", size = 453786 }, + { url = "https://files.pythonhosted.org/packages/d6/e6/a8f46f4a4ee7856fbd6ac0c6fb0dc65ed181ba46cd77875b8d9bbe494d9e/brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19ffc919fa4fc6ace69286e0a23b3789b4219058313cf9b45625016bf7ff996b", size = 2911165 }, + { url = "https://files.pythonhosted.org/packages/be/20/201559dff14e83ba345a5ec03335607e47467b6633c210607e693aefac40/brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9feb210d932ffe7798ee62e6145d3a757eb6233aa9a4e7db78dd3690d7755814", size = 2927895 }, + { url = "https://files.pythonhosted.org/packages/cd/15/695b1409264143be3c933f708a3f81d53c4a1e1ebbc06f46331decbf6563/brotlicffi-1.1.0.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84763dbdef5dd5c24b75597a77e1b30c66604725707565188ba54bab4f114820", size = 2851834 }, + { url = "https://files.pythonhosted.org/packages/b4/40/b961a702463b6005baf952794c2e9e0099bde657d0d7e007f923883b907f/brotlicffi-1.1.0.0-cp37-abi3-win32.whl", hash = "sha256:1b12b50e07c3911e1efa3a8971543e7648100713d4e0971b13631cce22c587eb", size = 341731 }, + { url = "https://files.pythonhosted.org/packages/1c/fa/5408a03c041114ceab628ce21766a4ea882aa6f6f0a800e04ee3a30ec6b9/brotlicffi-1.1.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:994a4f0681bb6c6c3b0925530a1926b7a189d878e6e5e38fae8efa47c5d9c613", size = 366783 }, +] + +[[package]] +name = "certifi" +version = "2025.1.31" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 }, +] + +[[package]] +name = "cffi" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264 }, + { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651 }, + { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259 }, + { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200 }, + { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235 }, + { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721 }, + { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242 }, + { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999 }, + { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242 }, + { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604 }, + { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727 }, + { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400 }, + { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 }, + { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 }, + { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 }, + { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850 }, + { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729 }, + { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256 }, + { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424 }, + { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568 }, + { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736 }, + { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 }, + { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 }, + { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989 }, + { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802 }, + { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792 }, + { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893 }, + { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810 }, + { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200 }, + { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447 }, + { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358 }, + { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469 }, + { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 }, + { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 }, +] + +[[package]] +name = "h11" +version = "0.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, +] + +[[package]] +name = "h2" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "hpack" }, + { name = "hyperframe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1b/38/d7f80fd13e6582fb8e0df8c9a653dcc02b03ca34f4d72f34869298c5baf8/h2-4.2.0.tar.gz", hash = "sha256:c8a52129695e88b1a0578d8d2cc6842bbd79128ac685463b887ee278126ad01f", size = 2150682 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/9e/984486f2d0a0bd2b024bf4bc1c62688fcafa9e61991f041fb0e2def4a982/h2-4.2.0-py3-none-any.whl", hash = "sha256:479a53ad425bb29af087f3458a61d30780bc818e4ebcf01f0b536ba916462ed0", size = 60957 }, +] + +[[package]] +name = "hpack" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/48/71de9ed269fdae9c8057e5a4c0aa7402e8bb16f2c6e90b3aa53327b113f8/hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca", size = 51276 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/c6/80c95b1b2b94682a72cbdbfb85b81ae2daffa4291fbfa1b1464502ede10d/hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496", size = 34357 }, +] + +[[package]] +name = "httpcore" +version = "1.0.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6a/41/d7d0a89eb493922c37d343b607bc1b5da7f5be7e383740b4753ad8943e90/httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c", size = 85196 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/f5/72347bc88306acb359581ac4d52f23c0ef445b57157adedb9aee0cd689d2/httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd", size = 78551 }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 }, +] + +[package.optional-dependencies] +brotli = [ + { name = "brotli", marker = "platform_python_implementation == 'CPython'" }, + { name = "brotlicffi", marker = "platform_python_implementation != 'CPython'" }, +] +http2 = [ + { name = "h2" }, +] +socks = [ + { name = "socksio" }, +] + +[[package]] +name = "hyperframe" +version = "6.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/02/e7/94f8232d4a74cc99514c13a9f995811485a6903d48e5d952771ef6322e30/hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08", size = 26566 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/30/47d0bf6072f7252e6521f3447ccfa40b421b6824517f82854703d0f5a98b/hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5", size = 13007 }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, +] + +[[package]] +name = "pycparser" +version = "2.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552 }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, +] + +[[package]] +name = "socksio" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/5c/48a7d9495be3d1c651198fd99dbb6ce190e2274d0f28b9051307bdec6b85/socksio-1.0.0.tar.gz", hash = "sha256:f88beb3da5b5c38b9890469de67d0cb0f9d494b78b106ca1845f96c10b91c4ac", size = 19055 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/37/c3/6eeb6034408dac0fa653d126c9204ade96b819c936e136c5e8a6897eee9c/socksio-1.0.0-py3-none-any.whl", hash = "sha256:95dc1f15f9b34e8d7b16f06d74b8ccf48f609af32ab33c608d08761c5dcbb1f3", size = 12763 }, +] + +[[package]] +name = "testpkg" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "httpx", extra = ["brotli", "http2", "socks"] }, +] + +[package.metadata] +requires-dist = [{ name = "httpx", extras = ["brotli", "http2", "socks"], specifier = ">=0.27.0,<0.30.0" }] + +[[package]] +name = "typing-extensions" +version = "4.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0e/3e/b00a62db91a83fff600de219b6ea9908e6918664899a2d85db222f4fbf19/typing_extensions-4.13.0.tar.gz", hash = "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b", size = 106520 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/86/39b65d676ec5732de17b7e3c476e45bb80ec64eb50737a8dce1a4178aba1/typing_extensions-4.13.0-py3-none-any.whl", hash = "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5", size = 45683 }, +] diff --git a/syft/pkg/cataloger/python/test-fixtures/uv/nested-extras/pyproject.toml b/syft/pkg/cataloger/python/test-fixtures/uv/nested-extras/pyproject.toml new file mode 100644 index 00000000000..a09f8fd2dc4 --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/uv/nested-extras/pyproject.toml @@ -0,0 +1,8 @@ +# fixture is not under test, just used to produde the uv.lock +[project] +name = "testpkg" +version = "0.1.0" + +dependencies = [ + "fastapi[all]>=0.111.0<0.112.0" +] \ No newline at end of file diff --git a/syft/pkg/cataloger/python/test-fixtures/uv/nested-extras/uv.lock b/syft/pkg/cataloger/python/test-fixtures/uv/nested-extras/uv.lock new file mode 100644 index 00000000000..ee3b539ab0f --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/uv/nested-extras/uv.lock @@ -0,0 +1,791 @@ +version = 1 +requires-python = ">=3.11" + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, +] + +[[package]] +name = "anyio" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "sniffio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916 }, +] + +[[package]] +name = "certifi" +version = "2025.1.31" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 }, +] + +[[package]] +name = "click" +version = "8.1.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "platform_system == 'Windows'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, +] + +[[package]] +name = "dnspython" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b5/4a/263763cb2ba3816dd94b08ad3a33d5fdae34ecb856678773cc40a3605829/dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1", size = 345197 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/1b/e0a87d256e40e8c888847551b20a017a6b98139178505dc7ffb96f04e954/dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86", size = 313632 }, +] + +[[package]] +name = "email-validator" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dnspython" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/48/ce/13508a1ec3f8bb981ae4ca79ea40384becc868bfae97fd1c942bb3a001b1/email_validator-2.2.0.tar.gz", hash = "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7", size = 48967 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/ee/bf0adb559ad3c786f12bcbc9296b3f5675f529199bef03e2df281fa1fadb/email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631", size = 33521 }, +] + +[[package]] +name = "fastapi" +version = "0.111.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "email-validator" }, + { name = "fastapi-cli" }, + { name = "httpx" }, + { name = "jinja2" }, + { name = "pydantic" }, + { name = "python-multipart" }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "uvicorn", extra = ["standard"] }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a0/ab/9f461ced846964e01c7a6ab25ea79ce2f07743285697b03c8e0e83d72e3e/fastapi-0.111.1.tar.gz", hash = "sha256:ddd1ac34cb1f76c2e2d7f8545a4bcb5463bce4834e81abf0b189e0c359ab2413", size = 288903 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/d4/eb78f7c2648a3585095623f207d7e4b85a1be30347e01e0fdcd1d7d167a9/fastapi-0.111.1-py3-none-any.whl", hash = "sha256:4f51cfa25d72f9fbc3280832e84b32494cf186f50158d364a8765aabf22587bf", size = 92210 }, +] + +[package.optional-dependencies] +all = [ + { name = "email-validator" }, + { name = "httpx" }, + { name = "itsdangerous" }, + { name = "jinja2" }, + { name = "orjson" }, + { name = "pydantic-extra-types" }, + { name = "pydantic-settings" }, + { name = "python-multipart" }, + { name = "pyyaml" }, + { name = "ujson" }, + { name = "uvicorn", extra = ["standard"] }, +] + +[[package]] +name = "fastapi-cli" +version = "0.0.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "rich-toolkit" }, + { name = "typer" }, + { name = "uvicorn", extra = ["standard"] }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fe/73/82a5831fbbf8ed75905bacf5b2d9d3dfd6f04d6968b29fe6f72a5ae9ceb1/fastapi_cli-0.0.7.tar.gz", hash = "sha256:02b3b65956f526412515907a0793c9094abd4bfb5457b389f645b0ea6ba3605e", size = 16753 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a1/e6/5daefc851b514ce2287d8f5d358ae4341089185f78f3217a69d0ce3a390c/fastapi_cli-0.0.7-py3-none-any.whl", hash = "sha256:d549368ff584b2804336c61f192d86ddea080c11255f375959627911944804f4", size = 10705 }, +] + +[[package]] +name = "h11" +version = "0.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, +] + +[[package]] +name = "httpcore" +version = "1.0.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6a/41/d7d0a89eb493922c37d343b607bc1b5da7f5be7e383740b4753ad8943e90/httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c", size = 85196 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/f5/72347bc88306acb359581ac4d52f23c0ef445b57157adedb9aee0cd689d2/httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd", size = 78551 }, +] + +[[package]] +name = "httptools" +version = "0.6.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/9a/ce5e1f7e131522e6d3426e8e7a490b3a01f39a6696602e1c4f33f9e94277/httptools-0.6.4.tar.gz", hash = "sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c", size = 240639 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/26/bb526d4d14c2774fe07113ca1db7255737ffbb119315839af2065abfdac3/httptools-0.6.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f47f8ed67cc0ff862b84a1189831d1d33c963fb3ce1ee0c65d3b0cbe7b711069", size = 199029 }, + { url = "https://files.pythonhosted.org/packages/a6/17/3e0d3e9b901c732987a45f4f94d4e2c62b89a041d93db89eafb262afd8d5/httptools-0.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0614154d5454c21b6410fdf5262b4a3ddb0f53f1e1721cfd59d55f32138c578a", size = 103492 }, + { url = "https://files.pythonhosted.org/packages/b7/24/0fe235d7b69c42423c7698d086d4db96475f9b50b6ad26a718ef27a0bce6/httptools-0.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8787367fbdfccae38e35abf7641dafc5310310a5987b689f4c32cc8cc3ee975", size = 462891 }, + { url = "https://files.pythonhosted.org/packages/b1/2f/205d1f2a190b72da6ffb5f41a3736c26d6fa7871101212b15e9b5cd8f61d/httptools-0.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40b0f7fe4fd38e6a507bdb751db0379df1e99120c65fbdc8ee6c1d044897a636", size = 459788 }, + { url = "https://files.pythonhosted.org/packages/6e/4c/d09ce0eff09057a206a74575ae8f1e1e2f0364d20e2442224f9e6612c8b9/httptools-0.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:40a5ec98d3f49904b9fe36827dcf1aadfef3b89e2bd05b0e35e94f97c2b14721", size = 433214 }, + { url = "https://files.pythonhosted.org/packages/3e/d2/84c9e23edbccc4a4c6f96a1b8d99dfd2350289e94f00e9ccc7aadde26fb5/httptools-0.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dacdd3d10ea1b4ca9df97a0a303cbacafc04b5cd375fa98732678151643d4988", size = 434120 }, + { url = "https://files.pythonhosted.org/packages/d0/46/4d8e7ba9581416de1c425b8264e2cadd201eb709ec1584c381f3e98f51c1/httptools-0.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:288cd628406cc53f9a541cfaf06041b4c71d751856bab45e3702191f931ccd17", size = 88565 }, + { url = "https://files.pythonhosted.org/packages/bb/0e/d0b71465c66b9185f90a091ab36389a7352985fe857e352801c39d6127c8/httptools-0.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2", size = 200683 }, + { url = "https://files.pythonhosted.org/packages/e2/b8/412a9bb28d0a8988de3296e01efa0bd62068b33856cdda47fe1b5e890954/httptools-0.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44", size = 104337 }, + { url = "https://files.pythonhosted.org/packages/9b/01/6fb20be3196ffdc8eeec4e653bc2a275eca7f36634c86302242c4fbb2760/httptools-0.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1", size = 508796 }, + { url = "https://files.pythonhosted.org/packages/f7/d8/b644c44acc1368938317d76ac991c9bba1166311880bcc0ac297cb9d6bd7/httptools-0.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2", size = 510837 }, + { url = "https://files.pythonhosted.org/packages/52/d8/254d16a31d543073a0e57f1c329ca7378d8924e7e292eda72d0064987486/httptools-0.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81", size = 485289 }, + { url = "https://files.pythonhosted.org/packages/5f/3c/4aee161b4b7a971660b8be71a92c24d6c64372c1ab3ae7f366b3680df20f/httptools-0.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f", size = 489779 }, + { url = "https://files.pythonhosted.org/packages/12/b7/5cae71a8868e555f3f67a50ee7f673ce36eac970f029c0c5e9d584352961/httptools-0.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970", size = 88634 }, + { url = "https://files.pythonhosted.org/packages/94/a3/9fe9ad23fd35f7de6b91eeb60848986058bd8b5a5c1e256f5860a160cc3e/httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660", size = 197214 }, + { url = "https://files.pythonhosted.org/packages/ea/d9/82d5e68bab783b632023f2fa31db20bebb4e89dfc4d2293945fd68484ee4/httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083", size = 102431 }, + { url = "https://files.pythonhosted.org/packages/96/c1/cb499655cbdbfb57b577734fde02f6fa0bbc3fe9fb4d87b742b512908dff/httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3", size = 473121 }, + { url = "https://files.pythonhosted.org/packages/af/71/ee32fd358f8a3bb199b03261f10921716990808a675d8160b5383487a317/httptools-0.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071", size = 473805 }, + { url = "https://files.pythonhosted.org/packages/8a/0a/0d4df132bfca1507114198b766f1737d57580c9ad1cf93c1ff673e3387be/httptools-0.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5", size = 448858 }, + { url = "https://files.pythonhosted.org/packages/1e/6a/787004fdef2cabea27bad1073bf6a33f2437b4dbd3b6fb4a9d71172b1c7c/httptools-0.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0", size = 452042 }, + { url = "https://files.pythonhosted.org/packages/4d/dc/7decab5c404d1d2cdc1bb330b1bf70e83d6af0396fd4fc76fc60c0d522bf/httptools-0.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8", size = 87682 }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, +] + +[[package]] +name = "itsdangerous" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234 }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899 }, +] + +[[package]] +name = "markdown-it-py" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 }, +] + +[[package]] +name = "markupsafe" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", size = 14353 }, + { url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", size = 12392 }, + { url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", size = 23984 }, + { url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", size = 23120 }, + { url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", size = 23032 }, + { url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", size = 24057 }, + { url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", size = 23359 }, + { url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", size = 23306 }, + { url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", size = 15094 }, + { url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", size = 15521 }, + { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274 }, + { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348 }, + { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149 }, + { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118 }, + { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993 }, + { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178 }, + { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319 }, + { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352 }, + { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097 }, + { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601 }, + { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274 }, + { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352 }, + { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122 }, + { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085 }, + { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978 }, + { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208 }, + { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357 }, + { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344 }, + { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101 }, + { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603 }, + { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510 }, + { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486 }, + { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480 }, + { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914 }, + { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796 }, + { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473 }, + { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114 }, + { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098 }, + { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208 }, + { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, +] + +[[package]] +name = "orjson" +version = "3.10.16" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/c7/03913cc4332174071950acf5b0735463e3f63760c80585ef369270c2b372/orjson-3.10.16.tar.gz", hash = "sha256:d2aaa5c495e11d17b9b93205f5fa196737ee3202f000aaebf028dc9a73750f10", size = 5410415 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/29/43f91a5512b5d2535594438eb41c5357865fd5e64dec745d90a588820c75/orjson-3.10.16-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:44fcbe1a1884f8bc9e2e863168b0f84230c3d634afe41c678637d2728ea8e739", size = 249180 }, + { url = "https://files.pythonhosted.org/packages/0c/36/2a72d55e266473c19a86d97b7363bb8bf558ab450f75205689a287d5ce61/orjson-3.10.16-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78177bf0a9d0192e0b34c3d78bcff7fe21d1b5d84aeb5ebdfe0dbe637b885225", size = 138510 }, + { url = "https://files.pythonhosted.org/packages/bb/ad/f86d6f55c1a68b57ff6ea7966bce5f4e5163f2e526ddb7db9fc3c2c8d1c4/orjson-3.10.16-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:12824073a010a754bb27330cad21d6e9b98374f497f391b8707752b96f72e741", size = 132373 }, + { url = "https://files.pythonhosted.org/packages/5e/8b/d18f2711493a809f3082a88fda89342bc8e16767743b909cd3c34989fba3/orjson-3.10.16-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddd41007e56284e9867864aa2f29f3136bb1dd19a49ca43c0b4eda22a579cf53", size = 136773 }, + { url = "https://files.pythonhosted.org/packages/a1/dc/ce025f002f8e0749e3f057c4d773a4d4de32b7b4c1fc5a50b429e7532586/orjson-3.10.16-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0877c4d35de639645de83666458ca1f12560d9fa7aa9b25d8bb8f52f61627d14", size = 138029 }, + { url = "https://files.pythonhosted.org/packages/0e/1b/cf9df85852b91160029d9f26014230366a2b4deb8cc51fabe68e250a8c1a/orjson-3.10.16-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9a09a539e9cc3beead3e7107093b4ac176d015bec64f811afb5965fce077a03c", size = 142677 }, + { url = "https://files.pythonhosted.org/packages/92/18/5b1e1e995bffad49dc4311a0bdfd874bc6f135fd20f0e1f671adc2c9910e/orjson-3.10.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31b98bc9b40610fec971d9a4d67bb2ed02eec0a8ae35f8ccd2086320c28526ca", size = 132800 }, + { url = "https://files.pythonhosted.org/packages/d6/eb/467f25b580e942fcca1344adef40633b7f05ac44a65a63fc913f9a805d58/orjson-3.10.16-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0ce243f5a8739f3a18830bc62dc2e05b69a7545bafd3e3249f86668b2bcd8e50", size = 135451 }, + { url = "https://files.pythonhosted.org/packages/8d/4b/9d10888038975cb375982e9339d9495bac382d5c976c500b8d6f2c8e2e4e/orjson-3.10.16-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:64792c0025bae049b3074c6abe0cf06f23c8e9f5a445f4bab31dc5ca23dbf9e1", size = 412358 }, + { url = "https://files.pythonhosted.org/packages/3b/e2/cfbcfcc4fbe619e0ca9bdbbfccb2d62b540bbfe41e0ee77d44a628594f59/orjson-3.10.16-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ea53f7e68eec718b8e17e942f7ca56c6bd43562eb19db3f22d90d75e13f0431d", size = 152772 }, + { url = "https://files.pythonhosted.org/packages/b9/d6/627a1b00569be46173007c11dde3da4618c9bfe18409325b0e3e2a82fe29/orjson-3.10.16-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a741ba1a9488c92227711bde8c8c2b63d7d3816883268c808fbeada00400c164", size = 137225 }, + { url = "https://files.pythonhosted.org/packages/0a/7b/a73c67b505021af845b9f05c7c848793258ea141fa2058b52dd9b067c2b4/orjson-3.10.16-cp311-cp311-win32.whl", hash = "sha256:c7ed2c61bb8226384c3fdf1fb01c51b47b03e3f4536c985078cccc2fd19f1619", size = 141733 }, + { url = "https://files.pythonhosted.org/packages/f4/22/5e8217c48d68c0adbfb181e749d6a733761074e598b083c69a1383d18147/orjson-3.10.16-cp311-cp311-win_amd64.whl", hash = "sha256:cd67d8b3e0e56222a2e7b7f7da9031e30ecd1fe251c023340b9f12caca85ab60", size = 133784 }, + { url = "https://files.pythonhosted.org/packages/5d/15/67ce9d4c959c83f112542222ea3b9209c1d424231d71d74c4890ea0acd2b/orjson-3.10.16-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6d3444abbfa71ba21bb042caa4b062535b122248259fdb9deea567969140abca", size = 249325 }, + { url = "https://files.pythonhosted.org/packages/da/2c/1426b06f30a1b9ada74b6f512c1ddf9d2760f53f61cdb59efeb9ad342133/orjson-3.10.16-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:30245c08d818fdcaa48b7d5b81499b8cae09acabb216fe61ca619876b128e184", size = 133621 }, + { url = "https://files.pythonhosted.org/packages/9e/88/18d26130954bc73bee3be10f95371ea1dfb8679e0e2c46b0f6d8c6289402/orjson-3.10.16-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0ba1d0baa71bf7579a4ccdcf503e6f3098ef9542106a0eca82395898c8a500a", size = 138270 }, + { url = "https://files.pythonhosted.org/packages/4f/f9/6d8b64fcd58fae072e80ee7981be8ba0d7c26ace954e5cd1d027fc80518f/orjson-3.10.16-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb0beefa5ef3af8845f3a69ff2a4aa62529b5acec1cfe5f8a6b4141033fd46ef", size = 132346 }, + { url = "https://files.pythonhosted.org/packages/16/3f/2513fd5bc786f40cd12af569c23cae6381aeddbefeed2a98f0a666eb5d0d/orjson-3.10.16-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6daa0e1c9bf2e030e93c98394de94506f2a4d12e1e9dadd7c53d5e44d0f9628e", size = 136845 }, + { url = "https://files.pythonhosted.org/packages/6d/42/b0e7b36720f5ab722b48e8ccf06514d4f769358dd73c51abd8728ef58d0b/orjson-3.10.16-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9da9019afb21e02410ef600e56666652b73eb3e4d213a0ec919ff391a7dd52aa", size = 138078 }, + { url = "https://files.pythonhosted.org/packages/a3/a8/d220afb8a439604be74fc755dbc740bded5ed14745ca536b304ed32eb18a/orjson-3.10.16-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:daeb3a1ee17b69981d3aae30c3b4e786b0f8c9e6c71f2b48f1aef934f63f38f4", size = 142712 }, + { url = "https://files.pythonhosted.org/packages/8c/88/7e41e9883c00f84f92fe357a8371edae816d9d7ef39c67b5106960c20389/orjson-3.10.16-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80fed80eaf0e20a31942ae5d0728849862446512769692474be5e6b73123a23b", size = 133136 }, + { url = "https://files.pythonhosted.org/packages/e9/ca/61116095307ad0be828ea26093febaf59e38596d84a9c8d765c3c5e4934f/orjson-3.10.16-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:73390ed838f03764540a7bdc4071fe0123914c2cc02fb6abf35182d5fd1b7a42", size = 135258 }, + { url = "https://files.pythonhosted.org/packages/dc/1b/09493cf7d801505f094c9295f79c98c1e0af2ac01c7ed8d25b30fcb19ada/orjson-3.10.16-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a22bba012a0c94ec02a7768953020ab0d3e2b884760f859176343a36c01adf87", size = 412326 }, + { url = "https://files.pythonhosted.org/packages/ea/02/125d7bbd7f7a500190ddc8ae5d2d3c39d87ed3ed28f5b37cfe76962c678d/orjson-3.10.16-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5385bbfdbc90ff5b2635b7e6bebf259652db00a92b5e3c45b616df75b9058e88", size = 152800 }, + { url = "https://files.pythonhosted.org/packages/f9/09/7658a9e3e793d5b3b00598023e0fb6935d0e7bbb8ff72311c5415a8ce677/orjson-3.10.16-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:02c6279016346e774dd92625d46c6c40db687b8a0d685aadb91e26e46cc33e1e", size = 137516 }, + { url = "https://files.pythonhosted.org/packages/29/87/32b7a4831e909d347278101a48d4cf9f3f25901b2295e7709df1651f65a1/orjson-3.10.16-cp312-cp312-win32.whl", hash = "sha256:7ca55097a11426db80f79378e873a8c51f4dde9ffc22de44850f9696b7eb0e8c", size = 141759 }, + { url = "https://files.pythonhosted.org/packages/35/ce/81a27e7b439b807bd393585271364cdddf50dc281fc57c4feef7ccb186a6/orjson-3.10.16-cp312-cp312-win_amd64.whl", hash = "sha256:86d127efdd3f9bf5f04809b70faca1e6836556ea3cc46e662b44dab3fe71f3d6", size = 133944 }, + { url = "https://files.pythonhosted.org/packages/87/b9/ff6aa28b8c86af9526160905593a2fe8d004ac7a5e592ee0b0ff71017511/orjson-3.10.16-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:148a97f7de811ba14bc6dbc4a433e0341ffd2cc285065199fb5f6a98013744bd", size = 249289 }, + { url = "https://files.pythonhosted.org/packages/6c/81/6d92a586149b52684ab8fd70f3623c91d0e6a692f30fd8c728916ab2263c/orjson-3.10.16-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:1d960c1bf0e734ea36d0adc880076de3846aaec45ffad29b78c7f1b7962516b8", size = 133640 }, + { url = "https://files.pythonhosted.org/packages/c2/88/b72443f4793d2e16039ab85d0026677932b15ab968595fb7149750d74134/orjson-3.10.16-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a318cd184d1269f68634464b12871386808dc8b7c27de8565234d25975a7a137", size = 138286 }, + { url = "https://files.pythonhosted.org/packages/c3/3c/72a22d4b28c076c4016d5a52bd644a8e4d849d3bb0373d9e377f9e3b2250/orjson-3.10.16-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df23f8df3ef9223d1d6748bea63fca55aae7da30a875700809c500a05975522b", size = 132307 }, + { url = "https://files.pythonhosted.org/packages/8a/a2/f1259561bdb6ad7061ff1b95dab082fe32758c4bc143ba8d3d70831f0a06/orjson-3.10.16-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b94dda8dd6d1378f1037d7f3f6b21db769ef911c4567cbaa962bb6dc5021cf90", size = 136739 }, + { url = "https://files.pythonhosted.org/packages/3d/af/c7583c4b34f33d8b8b90cfaab010ff18dd64e7074cc1e117a5f1eff20dcf/orjson-3.10.16-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f12970a26666a8775346003fd94347d03ccb98ab8aa063036818381acf5f523e", size = 138076 }, + { url = "https://files.pythonhosted.org/packages/d7/59/d7fc7fbdd3d4a64c2eae4fc7341a5aa39cf9549bd5e2d7f6d3c07f8b715b/orjson-3.10.16-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15a1431a245d856bd56e4d29ea0023eb4d2c8f71efe914beb3dee8ab3f0cd7fb", size = 142643 }, + { url = "https://files.pythonhosted.org/packages/92/0e/3bd8f2197d27601f16b4464ae948826da2bcf128af31230a9dbbad7ceb57/orjson-3.10.16-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c83655cfc247f399a222567d146524674a7b217af7ef8289c0ff53cfe8db09f0", size = 133168 }, + { url = "https://files.pythonhosted.org/packages/af/a8/351fd87b664b02f899f9144d2c3dc848b33ac04a5df05234cbfb9e2a7540/orjson-3.10.16-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fa59ae64cb6ddde8f09bdbf7baf933c4cd05734ad84dcf4e43b887eb24e37652", size = 135271 }, + { url = "https://files.pythonhosted.org/packages/ba/b0/a6d42a7d412d867c60c0337d95123517dd5a9370deea705ea1be0f89389e/orjson-3.10.16-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ca5426e5aacc2e9507d341bc169d8af9c3cbe88f4cd4c1cf2f87e8564730eb56", size = 412444 }, + { url = "https://files.pythonhosted.org/packages/79/ec/7572cd4e20863f60996f3f10bc0a6da64a6fd9c35954189a914cec0b7377/orjson-3.10.16-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6fd5da4edf98a400946cd3a195680de56f1e7575109b9acb9493331047157430", size = 152737 }, + { url = "https://files.pythonhosted.org/packages/a9/19/ceb9e8fed5403b2e76a8ac15f581b9d25780a3be3c9b3aa54b7777a210d5/orjson-3.10.16-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:980ecc7a53e567169282a5e0ff078393bac78320d44238da4e246d71a4e0e8f5", size = 137482 }, + { url = "https://files.pythonhosted.org/packages/1b/78/a78bb810f3786579dbbbd94768284cbe8f2fd65167cd7020260679665c17/orjson-3.10.16-cp313-cp313-win32.whl", hash = "sha256:28f79944dd006ac540a6465ebd5f8f45dfdf0948ff998eac7a908275b4c1add6", size = 141714 }, + { url = "https://files.pythonhosted.org/packages/81/9c/b66ce9245ff319df2c3278acd351a3f6145ef34b4a2d7f4b0f739368370f/orjson-3.10.16-cp313-cp313-win_amd64.whl", hash = "sha256:fe0a145e96d51971407cb8ba947e63ead2aa915db59d6631a355f5f2150b56b7", size = 133954 }, +] + +[[package]] +name = "pydantic" +version = "2.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/82/2a/4ba34614269b1e12a28b9fe54710983f5c3679f945797e86250c6269263f/pydantic-2.11.0.tar.gz", hash = "sha256:d6a287cd6037dee72f0597229256dfa246c4d61567a250e99f86b7b4626e2f41", size = 782184 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/09/2c/3a0a1b022bb028e4cd455c69a17ceaad809bf6763c110d093efc0d8f67aa/pydantic-2.11.0-py3-none-any.whl", hash = "sha256:d52535bb7aba33c2af820eaefd866f3322daf39319d03374921cd17fbbdf28f9", size = 442591 }, +] + +[[package]] +name = "pydantic-core" +version = "2.33.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/05/91ce14dfd5a3a99555fce436318cc0fd1f08c4daa32b3248ad63669ea8b4/pydantic_core-2.33.0.tar.gz", hash = "sha256:40eb8af662ba409c3cbf4a8150ad32ae73514cd7cb1f1a2113af39763dd616b3", size = 434080 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f0/93/9e97af2619b4026596487a79133e425c7d3c374f0a7f100f3d76bcdf9c83/pydantic_core-2.33.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a608a75846804271cf9c83e40bbb4dab2ac614d33c6fd5b0c6187f53f5c593ef", size = 2042784 }, + { url = "https://files.pythonhosted.org/packages/42/b4/0bba8412fd242729feeb80e7152e24f0e1a1c19f4121ca3d4a307f4e6222/pydantic_core-2.33.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e1c69aa459f5609dec2fa0652d495353accf3eda5bdb18782bc5a2ae45c9273a", size = 1858179 }, + { url = "https://files.pythonhosted.org/packages/69/1f/c1c40305d929bd08af863df64b0a26203b70b352a1962d86f3bcd52950fe/pydantic_core-2.33.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9ec80eb5a5f45a2211793f1c4aeddff0c3761d1c70d684965c1807e923a588b", size = 1909396 }, + { url = "https://files.pythonhosted.org/packages/0f/99/d2e727375c329c1e652b5d450fbb9d56e8c3933a397e4bd46e67c68c2cd5/pydantic_core-2.33.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e925819a98318d17251776bd3d6aa9f3ff77b965762155bdad15d1a9265c4cfd", size = 1998264 }, + { url = "https://files.pythonhosted.org/packages/9c/2e/3119a33931278d96ecc2e9e1b9d50c240636cfeb0c49951746ae34e4de74/pydantic_core-2.33.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5bf68bb859799e9cec3d9dd8323c40c00a254aabb56fe08f907e437005932f2b", size = 2140588 }, + { url = "https://files.pythonhosted.org/packages/35/bd/9267bd1ba55f17c80ef6cb7e07b3890b4acbe8eb6014f3102092d53d9300/pydantic_core-2.33.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1b2ea72dea0825949a045fa4071f6d5b3d7620d2a208335207793cf29c5a182d", size = 2746296 }, + { url = "https://files.pythonhosted.org/packages/6f/ed/ef37de6478a412ee627cbebd73e7b72a680f45bfacce9ff1199de6e17e88/pydantic_core-2.33.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1583539533160186ac546b49f5cde9ffc928062c96920f58bd95de32ffd7bffd", size = 2005555 }, + { url = "https://files.pythonhosted.org/packages/dd/84/72c8d1439585d8ee7bc35eb8f88a04a4d302ee4018871f1f85ae1b0c6625/pydantic_core-2.33.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:23c3e77bf8a7317612e5c26a3b084c7edeb9552d645742a54a5867635b4f2453", size = 2124452 }, + { url = "https://files.pythonhosted.org/packages/a7/8f/cb13de30c6a3e303423751a529a3d1271c2effee4b98cf3e397a66ae8498/pydantic_core-2.33.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a7a7f2a3f628d2f7ef11cb6188bcf0b9e1558151d511b974dfea10a49afe192b", size = 2087001 }, + { url = "https://files.pythonhosted.org/packages/83/d0/e93dc8884bf288a63fedeb8040ac8f29cb71ca52e755f48e5170bb63e55b/pydantic_core-2.33.0-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:f1fb026c575e16f673c61c7b86144517705865173f3d0907040ac30c4f9f5915", size = 2261663 }, + { url = "https://files.pythonhosted.org/packages/4c/ba/4b7739c95efa0b542ee45fd872c8f6b1884ab808cf04ce7ac6621b6df76e/pydantic_core-2.33.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:635702b2fed997e0ac256b2cfbdb4dd0bf7c56b5d8fba8ef03489c03b3eb40e2", size = 2257786 }, + { url = "https://files.pythonhosted.org/packages/cc/98/73cbca1d2360c27752cfa2fcdcf14d96230e92d7d48ecd50499865c56bf7/pydantic_core-2.33.0-cp311-cp311-win32.whl", hash = "sha256:07b4ced28fccae3f00626eaa0c4001aa9ec140a29501770a88dbbb0966019a86", size = 1925697 }, + { url = "https://files.pythonhosted.org/packages/9a/26/d85a40edeca5d8830ffc33667d6fef329fd0f4bc0c5181b8b0e206cfe488/pydantic_core-2.33.0-cp311-cp311-win_amd64.whl", hash = "sha256:4927564be53239a87770a5f86bdc272b8d1fbb87ab7783ad70255b4ab01aa25b", size = 1949859 }, + { url = "https://files.pythonhosted.org/packages/7e/0b/5a381605f0b9870465b805f2c86c06b0a7c191668ebe4117777306c2c1e5/pydantic_core-2.33.0-cp311-cp311-win_arm64.whl", hash = "sha256:69297418ad644d521ea3e1aa2e14a2a422726167e9ad22b89e8f1130d68e1e9a", size = 1907978 }, + { url = "https://files.pythonhosted.org/packages/a9/c4/c9381323cbdc1bb26d352bc184422ce77c4bc2f2312b782761093a59fafc/pydantic_core-2.33.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6c32a40712e3662bebe524abe8abb757f2fa2000028d64cc5a1006016c06af43", size = 2025127 }, + { url = "https://files.pythonhosted.org/packages/6f/bd/af35278080716ecab8f57e84515c7dc535ed95d1c7f52c1c6f7b313a9dab/pydantic_core-2.33.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8ec86b5baa36f0a0bfb37db86c7d52652f8e8aa076ab745ef7725784183c3fdd", size = 1851687 }, + { url = "https://files.pythonhosted.org/packages/12/e4/a01461225809c3533c23bd1916b1e8c2e21727f0fea60ab1acbffc4e2fca/pydantic_core-2.33.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4deac83a8cc1d09e40683be0bc6d1fa4cde8df0a9bf0cda5693f9b0569ac01b6", size = 1892232 }, + { url = "https://files.pythonhosted.org/packages/51/17/3d53d62a328fb0a49911c2962036b9e7a4f781b7d15e9093c26299e5f76d/pydantic_core-2.33.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:175ab598fb457a9aee63206a1993874badf3ed9a456e0654273e56f00747bbd6", size = 1977896 }, + { url = "https://files.pythonhosted.org/packages/30/98/01f9d86e02ec4a38f4b02086acf067f2c776b845d43f901bd1ee1c21bc4b/pydantic_core-2.33.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5f36afd0d56a6c42cf4e8465b6441cf546ed69d3a4ec92724cc9c8c61bd6ecf4", size = 2127717 }, + { url = "https://files.pythonhosted.org/packages/3c/43/6f381575c61b7c58b0fd0b92134c5a1897deea4cdfc3d47567b3ff460a4e/pydantic_core-2.33.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a98257451164666afafc7cbf5fb00d613e33f7e7ebb322fbcd99345695a9a61", size = 2680287 }, + { url = "https://files.pythonhosted.org/packages/01/42/c0d10d1451d161a9a0da9bbef023b8005aa26e9993a8cc24dc9e3aa96c93/pydantic_core-2.33.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecc6d02d69b54a2eb83ebcc6f29df04957f734bcf309d346b4f83354d8376862", size = 2008276 }, + { url = "https://files.pythonhosted.org/packages/20/ca/e08df9dba546905c70bae44ced9f3bea25432e34448d95618d41968f40b7/pydantic_core-2.33.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a69b7596c6603afd049ce7f3835bcf57dd3892fc7279f0ddf987bebed8caa5a", size = 2115305 }, + { url = "https://files.pythonhosted.org/packages/03/1f/9b01d990730a98833113581a78e595fd40ed4c20f9693f5a658fb5f91eff/pydantic_core-2.33.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ea30239c148b6ef41364c6f51d103c2988965b643d62e10b233b5efdca8c0099", size = 2068999 }, + { url = "https://files.pythonhosted.org/packages/20/18/fe752476a709191148e8b1e1139147841ea5d2b22adcde6ee6abb6c8e7cf/pydantic_core-2.33.0-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:abfa44cf2f7f7d7a199be6c6ec141c9024063205545aa09304349781b9a125e6", size = 2241488 }, + { url = "https://files.pythonhosted.org/packages/81/22/14738ad0a0bf484b928c9e52004f5e0b81dd8dabbdf23b843717b37a71d1/pydantic_core-2.33.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:20d4275f3c4659d92048c70797e5fdc396c6e4446caf517ba5cad2db60cd39d3", size = 2248430 }, + { url = "https://files.pythonhosted.org/packages/e8/27/be7571e215ac8d321712f2433c445b03dbcd645366a18f67b334df8912bc/pydantic_core-2.33.0-cp312-cp312-win32.whl", hash = "sha256:918f2013d7eadea1d88d1a35fd4a1e16aaf90343eb446f91cb091ce7f9b431a2", size = 1908353 }, + { url = "https://files.pythonhosted.org/packages/be/3a/be78f28732f93128bd0e3944bdd4b3970b389a1fbd44907c97291c8dcdec/pydantic_core-2.33.0-cp312-cp312-win_amd64.whl", hash = "sha256:aec79acc183865bad120b0190afac467c20b15289050648b876b07777e67ea48", size = 1955956 }, + { url = "https://files.pythonhosted.org/packages/21/26/b8911ac74faa994694b76ee6a22875cc7a4abea3c381fdba4edc6c6bef84/pydantic_core-2.33.0-cp312-cp312-win_arm64.whl", hash = "sha256:5461934e895968655225dfa8b3be79e7e927e95d4bd6c2d40edd2fa7052e71b6", size = 1903259 }, + { url = "https://files.pythonhosted.org/packages/79/20/de2ad03ce8f5b3accf2196ea9b44f31b0cd16ac6e8cfc6b21976ed45ec35/pydantic_core-2.33.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f00e8b59e1fc8f09d05594aa7d2b726f1b277ca6155fc84c0396db1b373c4555", size = 2032214 }, + { url = "https://files.pythonhosted.org/packages/f9/af/6817dfda9aac4958d8b516cbb94af507eb171c997ea66453d4d162ae8948/pydantic_core-2.33.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a73be93ecef45786d7d95b0c5e9b294faf35629d03d5b145b09b81258c7cd6d", size = 1852338 }, + { url = "https://files.pythonhosted.org/packages/44/f3/49193a312d9c49314f2b953fb55740b7c530710977cabe7183b8ef111b7f/pydantic_core-2.33.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff48a55be9da6930254565ff5238d71d5e9cd8c5487a191cb85df3bdb8c77365", size = 1896913 }, + { url = "https://files.pythonhosted.org/packages/06/e0/c746677825b2e29a2fa02122a8991c83cdd5b4c5f638f0664d4e35edd4b2/pydantic_core-2.33.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:26a4ea04195638dcd8c53dadb545d70badba51735b1594810e9768c2c0b4a5da", size = 1986046 }, + { url = "https://files.pythonhosted.org/packages/11/ec/44914e7ff78cef16afb5e5273d480c136725acd73d894affdbe2a1bbaad5/pydantic_core-2.33.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41d698dcbe12b60661f0632b543dbb119e6ba088103b364ff65e951610cb7ce0", size = 2128097 }, + { url = "https://files.pythonhosted.org/packages/fe/f5/c6247d424d01f605ed2e3802f338691cae17137cee6484dce9f1ac0b872b/pydantic_core-2.33.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ae62032ef513fe6281ef0009e30838a01057b832dc265da32c10469622613885", size = 2681062 }, + { url = "https://files.pythonhosted.org/packages/f0/85/114a2113b126fdd7cf9a9443b1b1fe1b572e5bd259d50ba9d5d3e1927fa9/pydantic_core-2.33.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f225f3a3995dbbc26affc191d0443c6c4aa71b83358fd4c2b7d63e2f6f0336f9", size = 2007487 }, + { url = "https://files.pythonhosted.org/packages/e6/40/3c05ed28d225c7a9acd2b34c5c8010c279683a870219b97e9f164a5a8af0/pydantic_core-2.33.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5bdd36b362f419c78d09630cbaebc64913f66f62bda6d42d5fbb08da8cc4f181", size = 2121382 }, + { url = "https://files.pythonhosted.org/packages/8a/22/e70c086f41eebd323e6baa92cc906c3f38ddce7486007eb2bdb3b11c8f64/pydantic_core-2.33.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:2a0147c0bef783fd9abc9f016d66edb6cac466dc54a17ec5f5ada08ff65caf5d", size = 2072473 }, + { url = "https://files.pythonhosted.org/packages/3e/84/d1614dedd8fe5114f6a0e348bcd1535f97d76c038d6102f271433cd1361d/pydantic_core-2.33.0-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:c860773a0f205926172c6644c394e02c25421dc9a456deff16f64c0e299487d3", size = 2249468 }, + { url = "https://files.pythonhosted.org/packages/b0/c0/787061eef44135e00fddb4b56b387a06c303bfd3884a6df9bea5cb730230/pydantic_core-2.33.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:138d31e3f90087f42aa6286fb640f3c7a8eb7bdae829418265e7e7474bd2574b", size = 2254716 }, + { url = "https://files.pythonhosted.org/packages/ae/e2/27262eb04963201e89f9c280f1e10c493a7a37bc877e023f31aa72d2f911/pydantic_core-2.33.0-cp313-cp313-win32.whl", hash = "sha256:d20cbb9d3e95114325780f3cfe990f3ecae24de7a2d75f978783878cce2ad585", size = 1916450 }, + { url = "https://files.pythonhosted.org/packages/13/8d/25ff96f1e89b19e0b70b3cd607c9ea7ca27e1dcb810a9cd4255ed6abf869/pydantic_core-2.33.0-cp313-cp313-win_amd64.whl", hash = "sha256:ca1103d70306489e3d006b0f79db8ca5dd3c977f6f13b2c59ff745249431a606", size = 1956092 }, + { url = "https://files.pythonhosted.org/packages/1b/64/66a2efeff657b04323ffcd7b898cb0354d36dae3a561049e092134a83e9c/pydantic_core-2.33.0-cp313-cp313-win_arm64.whl", hash = "sha256:6291797cad239285275558e0a27872da735b05c75d5237bbade8736f80e4c225", size = 1908367 }, + { url = "https://files.pythonhosted.org/packages/52/54/295e38769133363d7ec4a5863a4d579f331728c71a6644ff1024ee529315/pydantic_core-2.33.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7b79af799630af263eca9ec87db519426d8c9b3be35016eddad1832bac812d87", size = 1813331 }, + { url = "https://files.pythonhosted.org/packages/4c/9c/0c8ea02db8d682aa1ef48938abae833c1d69bdfa6e5ec13b21734b01ae70/pydantic_core-2.33.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eabf946a4739b5237f4f56d77fa6668263bc466d06a8036c055587c130a46f7b", size = 1986653 }, + { url = "https://files.pythonhosted.org/packages/8e/4f/3fb47d6cbc08c7e00f92300e64ba655428c05c56b8ab6723bd290bae6458/pydantic_core-2.33.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8a1d581e8cdbb857b0e0e81df98603376c1a5c34dc5e54039dcc00f043df81e7", size = 1931234 }, + { url = "https://files.pythonhosted.org/packages/2b/b2/553e42762e7b08771fca41c0230c1ac276f9e79e78f57628e1b7d328551d/pydantic_core-2.33.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5d8dc9f63a26f7259b57f46a7aab5af86b2ad6fbe48487500bb1f4b27e051e4c", size = 2041207 }, + { url = "https://files.pythonhosted.org/packages/85/81/a91a57bbf3efe53525ab75f65944b8950e6ef84fe3b9a26c1ec173363263/pydantic_core-2.33.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:30369e54d6d0113d2aa5aee7a90d17f225c13d87902ace8fcd7bbf99b19124db", size = 1873736 }, + { url = "https://files.pythonhosted.org/packages/9c/d2/5ab52e9f551cdcbc1ee99a0b3ef595f56d031f66f88e5ca6726c49f9ce65/pydantic_core-2.33.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3eb479354c62067afa62f53bb387827bee2f75c9c79ef25eef6ab84d4b1ae3b", size = 1903794 }, + { url = "https://files.pythonhosted.org/packages/2f/5f/a81742d3f3821b16f1265f057d6e0b68a3ab13a814fe4bffac536a1f26fd/pydantic_core-2.33.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0310524c833d91403c960b8a3cf9f46c282eadd6afd276c8c5edc617bd705dc9", size = 2083457 }, + { url = "https://files.pythonhosted.org/packages/b5/2f/e872005bc0fc47f9c036b67b12349a8522d32e3bda928e82d676e2a594d1/pydantic_core-2.33.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:eddb18a00bbb855325db27b4c2a89a4ba491cd6a0bd6d852b225172a1f54b36c", size = 2119537 }, + { url = "https://files.pythonhosted.org/packages/d3/13/183f13ce647202eaf3dada9e42cdfc59cbb95faedd44d25f22b931115c7f/pydantic_core-2.33.0-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:ade5dbcf8d9ef8f4b28e682d0b29f3008df9842bb5ac48ac2c17bc55771cc976", size = 2080069 }, + { url = "https://files.pythonhosted.org/packages/23/8b/b6be91243da44a26558d9c3a9007043b3750334136c6550551e8092d6d96/pydantic_core-2.33.0-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:2c0afd34f928383e3fd25740f2050dbac9d077e7ba5adbaa2227f4d4f3c8da5c", size = 2251618 }, + { url = "https://files.pythonhosted.org/packages/aa/c5/fbcf1977035b834f63eb542e74cd6c807177f383386175b468f0865bcac4/pydantic_core-2.33.0-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7da333f21cd9df51d5731513a6d39319892947604924ddf2e24a4612975fb936", size = 2255374 }, + { url = "https://files.pythonhosted.org/packages/2f/f8/66f328e411f1c9574b13c2c28ab01f308b53688bbbe6ca8fb981e6cabc42/pydantic_core-2.33.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:4b6d77c75a57f041c5ee915ff0b0bb58eabb78728b69ed967bc5b780e8f701b8", size = 2082099 }, +] + +[[package]] +name = "pydantic-extra-types" +version = "2.10.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/53/fa/6b268a47839f8af46ffeb5bb6aee7bded44fbad54e6bf826c11f17aef91a/pydantic_extra_types-2.10.3.tar.gz", hash = "sha256:dcc0a7b90ac9ef1b58876c9b8fdede17fbdde15420de9d571a9fccde2ae175bb", size = 95128 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/0a/f6f8e5f79d188e2f3fa9ecfccfa72538b685985dd5c7c2886c67af70e685/pydantic_extra_types-2.10.3-py3-none-any.whl", hash = "sha256:e8b372752b49019cd8249cc192c62a820d8019f5382a8789d0f887338a59c0f3", size = 37175 }, +] + +[[package]] +name = "pydantic-settings" +version = "2.8.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "python-dotenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/88/82/c79424d7d8c29b994fb01d277da57b0a9b09cc03c3ff875f9bd8a86b2145/pydantic_settings-2.8.1.tar.gz", hash = "sha256:d5c663dfbe9db9d5e1c646b2e161da12f0d734d422ee56f567d0ea2cee4e8585", size = 83550 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/53/a64f03044927dc47aafe029c42a5b7aabc38dfb813475e0e1bf71c4a59d0/pydantic_settings-2.8.1-py3-none-any.whl", hash = "sha256:81942d5ac3d905f7f3ee1a70df5dfb62d5569c12f51a5a647defc1c3d9ee2e9c", size = 30839 }, +] + +[[package]] +name = "pygments" +version = "2.19.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, +] + +[[package]] +name = "python-dotenv" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/88/2c/7bb1416c5620485aa793f2de31d3df393d3686aa8a8506d11e10e13c5baf/python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", size = 39920 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/18/98a99ad95133c6a6e2005fe89faedf294a748bd5dc803008059409ac9b1e/python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d", size = 20256 }, +] + +[[package]] +name = "python-multipart" +version = "0.0.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/87/f44d7c9f274c7ee665a29b885ec97089ec5dc034c7f3fafa03da9e39a09e/python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13", size = 37158 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546 }, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612 }, + { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040 }, + { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829 }, + { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167 }, + { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952 }, + { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301 }, + { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638 }, + { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850 }, + { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980 }, + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, +] + +[[package]] +name = "rich" +version = "13.9.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, +] + +[[package]] +name = "rich-toolkit" +version = "0.14.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "rich" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bc/88/965bb2da72bc68cd3425e5be70b1cfb74c9c1cb93168317e07205c0d42c5/rich_toolkit-0.14.0.tar.gz", hash = "sha256:569c61522e0e24fc4e9a58191fd97b64aa4e1376856666bae6122a7362bbf32d", size = 104309 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/a2/dc0ae0b61d5fce9eec3763c98d5a471f7b07c891a2cbfb3fd6a0f632a9a1/rich_toolkit-0.14.0-py3-none-any.whl", hash = "sha256:75ff4b3e70e27e9cb145164bfe8d8e56758162fa3f87594067f4d85630b98bf9", size = 24062 }, +] + +[[package]] +name = "shellingham" +version = "1.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, +] + +[[package]] +name = "starlette" +version = "0.37.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/b5/6bceb93ff20bd7ca36e6f7c540581abb18f53130fabb30ba526e26fd819b/starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823", size = 2843736 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/18/31fa32ed6c68ba66220204ef0be798c349d0a20c1901f9d4a794e08c76d8/starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee", size = 71908 }, +] + +[[package]] +name = "testpkg" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "fastapi", extra = ["all"] }, +] + +[package.metadata] +requires-dist = [{ name = "fastapi", extras = ["all"], specifier = ">=0.111.0,<0.112.0" }] + +[[package]] +name = "typer" +version = "0.15.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "rich" }, + { name = "shellingham" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8b/6f/3991f0f1c7fcb2df31aef28e0594d8d54b05393a0e4e34c65e475c2a5d41/typer-0.15.2.tar.gz", hash = "sha256:ab2fab47533a813c49fe1f16b1a370fd5819099c00b119e0633df65f22144ba5", size = 100711 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/fc/5b29fea8cee020515ca82cc68e3b8e1e34bb19a3535ad854cac9257b414c/typer-0.15.2-py3-none-any.whl", hash = "sha256:46a499c6107d645a9c13f7ee46c5d5096cae6f5fc57dd11eccbbb9ae3e44ddfc", size = 45061 }, +] + +[[package]] +name = "typing-extensions" +version = "4.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0e/3e/b00a62db91a83fff600de219b6ea9908e6918664899a2d85db222f4fbf19/typing_extensions-4.13.0.tar.gz", hash = "sha256:0a4ac55a5820789d87e297727d229866c9650f6521b64206413c4fbada24d95b", size = 106520 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/86/39b65d676ec5732de17b7e3c476e45bb80ec64eb50737a8dce1a4178aba1/typing_extensions-4.13.0-py3-none-any.whl", hash = "sha256:c8dd92cc0d6425a97c18fbb9d1954e5ff92c1ca881a309c45f06ebc0b79058e5", size = 45683 }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125 }, +] + +[[package]] +name = "ujson" +version = "5.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f0/00/3110fd566786bfa542adb7932d62035e0c0ef662a8ff6544b6643b3d6fd7/ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1", size = 7154885 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/ec/3c551ecfe048bcb3948725251fb0214b5844a12aa60bee08d78315bb1c39/ujson-5.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00", size = 55353 }, + { url = "https://files.pythonhosted.org/packages/8d/9f/4731ef0671a0653e9f5ba18db7c4596d8ecbf80c7922dd5fe4150f1aea76/ujson-5.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126", size = 51813 }, + { url = "https://files.pythonhosted.org/packages/1f/2b/44d6b9c1688330bf011f9abfdb08911a9dc74f76926dde74e718d87600da/ujson-5.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8", size = 51988 }, + { url = "https://files.pythonhosted.org/packages/29/45/f5f5667427c1ec3383478092a414063ddd0dfbebbcc533538fe37068a0a3/ujson-5.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b", size = 53561 }, + { url = "https://files.pythonhosted.org/packages/26/21/a0c265cda4dd225ec1be595f844661732c13560ad06378760036fc622587/ujson-5.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9", size = 58497 }, + { url = "https://files.pythonhosted.org/packages/28/36/8fde862094fd2342ccc427a6a8584fed294055fdee341661c78660f7aef3/ujson-5.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f", size = 997877 }, + { url = "https://files.pythonhosted.org/packages/90/37/9208e40d53baa6da9b6a1c719e0670c3f474c8fc7cc2f1e939ec21c1bc93/ujson-5.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4", size = 1140632 }, + { url = "https://files.pythonhosted.org/packages/89/d5/2626c87c59802863d44d19e35ad16b7e658e4ac190b0dead17ff25460b4c/ujson-5.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1", size = 1043513 }, + { url = "https://files.pythonhosted.org/packages/2f/ee/03662ce9b3f16855770f0d70f10f0978ba6210805aa310c4eebe66d36476/ujson-5.10.0-cp311-cp311-win32.whl", hash = "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f", size = 38616 }, + { url = "https://files.pythonhosted.org/packages/3e/20/952dbed5895835ea0b82e81a7be4ebb83f93b079d4d1ead93fcddb3075af/ujson-5.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720", size = 42071 }, + { url = "https://files.pythonhosted.org/packages/e8/a6/fd3f8bbd80842267e2d06c3583279555e8354c5986c952385199d57a5b6c/ujson-5.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5", size = 55642 }, + { url = "https://files.pythonhosted.org/packages/a8/47/dd03fd2b5ae727e16d5d18919b383959c6d269c7b948a380fdd879518640/ujson-5.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e", size = 51807 }, + { url = "https://files.pythonhosted.org/packages/25/23/079a4cc6fd7e2655a473ed9e776ddbb7144e27f04e8fc484a0fb45fe6f71/ujson-5.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043", size = 51972 }, + { url = "https://files.pythonhosted.org/packages/04/81/668707e5f2177791869b624be4c06fb2473bf97ee33296b18d1cf3092af7/ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1", size = 53686 }, + { url = "https://files.pythonhosted.org/packages/bd/50/056d518a386d80aaf4505ccf3cee1c40d312a46901ed494d5711dd939bc3/ujson-5.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3", size = 58591 }, + { url = "https://files.pythonhosted.org/packages/fc/d6/aeaf3e2d6fb1f4cfb6bf25f454d60490ed8146ddc0600fae44bfe7eb5a72/ujson-5.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21", size = 997853 }, + { url = "https://files.pythonhosted.org/packages/f8/d5/1f2a5d2699f447f7d990334ca96e90065ea7f99b142ce96e85f26d7e78e2/ujson-5.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2", size = 1140689 }, + { url = "https://files.pythonhosted.org/packages/f2/2c/6990f4ccb41ed93744aaaa3786394bca0875503f97690622f3cafc0adfde/ujson-5.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e", size = 1043576 }, + { url = "https://files.pythonhosted.org/packages/14/f5/a2368463dbb09fbdbf6a696062d0c0f62e4ae6fa65f38f829611da2e8fdd/ujson-5.10.0-cp312-cp312-win32.whl", hash = "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e", size = 38764 }, + { url = "https://files.pythonhosted.org/packages/59/2d/691f741ffd72b6c84438a93749ac57bf1a3f217ac4b0ea4fd0e96119e118/ujson-5.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc", size = 42211 }, + { url = "https://files.pythonhosted.org/packages/0d/69/b3e3f924bb0e8820bb46671979770c5be6a7d51c77a66324cdb09f1acddb/ujson-5.10.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287", size = 55646 }, + { url = "https://files.pythonhosted.org/packages/32/8a/9b748eb543c6cabc54ebeaa1f28035b1bd09c0800235b08e85990734c41e/ujson-5.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e", size = 51806 }, + { url = "https://files.pythonhosted.org/packages/39/50/4b53ea234413b710a18b305f465b328e306ba9592e13a791a6a6b378869b/ujson-5.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557", size = 51975 }, + { url = "https://files.pythonhosted.org/packages/b4/9d/8061934f960cdb6dd55f0b3ceeff207fcc48c64f58b43403777ad5623d9e/ujson-5.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988", size = 53693 }, + { url = "https://files.pythonhosted.org/packages/f5/be/7bfa84b28519ddbb67efc8410765ca7da55e6b93aba84d97764cd5794dbc/ujson-5.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816", size = 58594 }, + { url = "https://files.pythonhosted.org/packages/48/eb/85d465abafb2c69d9699cfa5520e6e96561db787d36c677370e066c7e2e7/ujson-5.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20", size = 997853 }, + { url = "https://files.pythonhosted.org/packages/9f/76/2a63409fc05d34dd7d929357b7a45e3a2c96f22b4225cd74becd2ba6c4cb/ujson-5.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0", size = 1140694 }, + { url = "https://files.pythonhosted.org/packages/45/ed/582c4daba0f3e1688d923b5cb914ada1f9defa702df38a1916c899f7c4d1/ujson-5.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f", size = 1043580 }, + { url = "https://files.pythonhosted.org/packages/d7/0c/9837fece153051e19c7bade9f88f9b409e026b9525927824cdf16293b43b/ujson-5.10.0-cp313-cp313-win32.whl", hash = "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165", size = 38766 }, + { url = "https://files.pythonhosted.org/packages/d7/72/6cb6728e2738c05bbe9bd522d6fc79f86b9a28402f38663e85a28fddd4a0/ujson-5.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539", size = 42212 }, +] + +[[package]] +name = "uvicorn" +version = "0.34.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4b/4d/938bd85e5bf2edeec766267a5015ad969730bb91e31b44021dfe8b22df6c/uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9", size = 76568 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4", size = 62315 }, +] + +[package.optional-dependencies] +standard = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "httptools" }, + { name = "python-dotenv" }, + { name = "pyyaml" }, + { name = "uvloop", marker = "platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32'" }, + { name = "watchfiles" }, + { name = "websockets" }, +] + +[[package]] +name = "uvloop" +version = "0.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/c0/854216d09d33c543f12a44b393c402e89a920b1a0a7dc634c42de91b9cf6/uvloop-0.21.0.tar.gz", hash = "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3", size = 2492741 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/57/a7/4cf0334105c1160dd6819f3297f8700fda7fc30ab4f61fbf3e725acbc7cc/uvloop-0.21.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c0f3fa6200b3108919f8bdabb9a7f87f20e7097ea3c543754cabc7d717d95cf8", size = 1447410 }, + { url = "https://files.pythonhosted.org/packages/8c/7c/1517b0bbc2dbe784b563d6ab54f2ef88c890fdad77232c98ed490aa07132/uvloop-0.21.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0878c2640cf341b269b7e128b1a5fed890adc4455513ca710d77d5e93aa6d6a0", size = 805476 }, + { url = "https://files.pythonhosted.org/packages/ee/ea/0bfae1aceb82a503f358d8d2fa126ca9dbdb2ba9c7866974faec1cb5875c/uvloop-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9fb766bb57b7388745d8bcc53a359b116b8a04c83a2288069809d2b3466c37e", size = 3960855 }, + { url = "https://files.pythonhosted.org/packages/8a/ca/0864176a649838b838f36d44bf31c451597ab363b60dc9e09c9630619d41/uvloop-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a375441696e2eda1c43c44ccb66e04d61ceeffcd76e4929e527b7fa401b90fb", size = 3973185 }, + { url = "https://files.pythonhosted.org/packages/30/bf/08ad29979a936d63787ba47a540de2132169f140d54aa25bc8c3df3e67f4/uvloop-0.21.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:baa0e6291d91649c6ba4ed4b2f982f9fa165b5bbd50a9e203c416a2797bab3c6", size = 3820256 }, + { url = "https://files.pythonhosted.org/packages/da/e2/5cf6ef37e3daf2f06e651aae5ea108ad30df3cb269102678b61ebf1fdf42/uvloop-0.21.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4509360fcc4c3bd2c70d87573ad472de40c13387f5fda8cb58350a1d7475e58d", size = 3937323 }, + { url = "https://files.pythonhosted.org/packages/8c/4c/03f93178830dc7ce8b4cdee1d36770d2f5ebb6f3d37d354e061eefc73545/uvloop-0.21.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c", size = 1471284 }, + { url = "https://files.pythonhosted.org/packages/43/3e/92c03f4d05e50f09251bd8b2b2b584a2a7f8fe600008bcc4523337abe676/uvloop-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2", size = 821349 }, + { url = "https://files.pythonhosted.org/packages/a6/ef/a02ec5da49909dbbfb1fd205a9a1ac4e88ea92dcae885e7c961847cd51e2/uvloop-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d", size = 4580089 }, + { url = "https://files.pythonhosted.org/packages/06/a7/b4e6a19925c900be9f98bec0a75e6e8f79bb53bdeb891916609ab3958967/uvloop-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc", size = 4693770 }, + { url = "https://files.pythonhosted.org/packages/ce/0c/f07435a18a4b94ce6bd0677d8319cd3de61f3a9eeb1e5f8ab4e8b5edfcb3/uvloop-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb", size = 4451321 }, + { url = "https://files.pythonhosted.org/packages/8f/eb/f7032be105877bcf924709c97b1bf3b90255b4ec251f9340cef912559f28/uvloop-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f", size = 4659022 }, + { url = "https://files.pythonhosted.org/packages/3f/8d/2cbef610ca21539f0f36e2b34da49302029e7c9f09acef0b1c3b5839412b/uvloop-0.21.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281", size = 1468123 }, + { url = "https://files.pythonhosted.org/packages/93/0d/b0038d5a469f94ed8f2b2fce2434a18396d8fbfb5da85a0a9781ebbdec14/uvloop-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af", size = 819325 }, + { url = "https://files.pythonhosted.org/packages/50/94/0a687f39e78c4c1e02e3272c6b2ccdb4e0085fda3b8352fecd0410ccf915/uvloop-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6", size = 4582806 }, + { url = "https://files.pythonhosted.org/packages/d2/19/f5b78616566ea68edd42aacaf645adbf71fbd83fc52281fba555dc27e3f1/uvloop-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816", size = 4701068 }, + { url = "https://files.pythonhosted.org/packages/47/57/66f061ee118f413cd22a656de622925097170b9380b30091b78ea0c6ea75/uvloop-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc", size = 4454428 }, + { url = "https://files.pythonhosted.org/packages/63/9a/0962b05b308494e3202d3f794a6e85abe471fe3cafdbcf95c2e8c713aabd/uvloop-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553", size = 4660018 }, +] + +[[package]] +name = "watchfiles" +version = "1.0.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f5/26/c705fc77d0a9ecdb9b66f1e2976d95b81df3cae518967431e7dbf9b5e219/watchfiles-1.0.4.tar.gz", hash = "sha256:6ba473efd11062d73e4f00c2b730255f9c1bdd73cd5f9fe5b5da8dbd4a717205", size = 94625 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/bb/8461adc4b1fed009546fb797fc0d5698dcfe5e289cb37e1b8f16a93cdc30/watchfiles-1.0.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:2a9f93f8439639dc244c4d2902abe35b0279102bca7bbcf119af964f51d53c19", size = 394869 }, + { url = "https://files.pythonhosted.org/packages/55/88/9ebf36b3547176d1709c320de78c1fa3263a46be31b5b1267571d9102686/watchfiles-1.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9eea33ad8c418847dd296e61eb683cae1c63329b6d854aefcd412e12d94ee235", size = 384905 }, + { url = "https://files.pythonhosted.org/packages/03/8a/04335ce23ef78d8c69f0913e8b20cf7d9233e3986543aeef95ef2d6e43d2/watchfiles-1.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31f1a379c9dcbb3f09cf6be1b7e83b67c0e9faabed0471556d9438a4a4e14202", size = 449944 }, + { url = "https://files.pythonhosted.org/packages/17/4e/c8d5dcd14fe637f4633616dabea8a4af0a10142dccf3b43e0f081ba81ab4/watchfiles-1.0.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ab594e75644421ae0a2484554832ca5895f8cab5ab62de30a1a57db460ce06c6", size = 456020 }, + { url = "https://files.pythonhosted.org/packages/5e/74/3e91e09e1861dd7fbb1190ce7bd786700dc0fbc2ccd33bb9fff5de039229/watchfiles-1.0.4-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc2eb5d14a8e0d5df7b36288979176fbb39672d45184fc4b1c004d7c3ce29317", size = 482983 }, + { url = "https://files.pythonhosted.org/packages/a1/3d/e64de2d1ce4eb6a574fd78ce3a28c279da263be9ef3cfcab6f708df192f2/watchfiles-1.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f68d8e9d5a321163ddacebe97091000955a1b74cd43724e346056030b0bacee", size = 520320 }, + { url = "https://files.pythonhosted.org/packages/2c/bd/52235f7063b57240c66a991696ed27e2a18bd6fcec8a1ea5a040b70d0611/watchfiles-1.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9ce064e81fe79faa925ff03b9f4c1a98b0bbb4a1b8c1b015afa93030cb21a49", size = 500988 }, + { url = "https://files.pythonhosted.org/packages/3a/b0/ff04194141a5fe650c150400dd9e42667916bc0f52426e2e174d779b8a74/watchfiles-1.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b77d5622ac5cc91d21ae9c2b284b5d5c51085a0bdb7b518dba263d0af006132c", size = 452573 }, + { url = "https://files.pythonhosted.org/packages/3d/9d/966164332c5a178444ae6d165082d4f351bd56afd9c3ec828eecbf190e6a/watchfiles-1.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1941b4e39de9b38b868a69b911df5e89dc43767feeda667b40ae032522b9b5f1", size = 615114 }, + { url = "https://files.pythonhosted.org/packages/94/df/f569ae4c1877f96ad4086c153a8eee5a19a3b519487bf5c9454a3438c341/watchfiles-1.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4f8c4998506241dedf59613082d1c18b836e26ef2a4caecad0ec41e2a15e4226", size = 613076 }, + { url = "https://files.pythonhosted.org/packages/15/ae/8ce5f29e65d5fa5790e3c80c289819c55e12be2e1b9f5b6a0e55e169b97d/watchfiles-1.0.4-cp311-cp311-win32.whl", hash = "sha256:4ebbeca9360c830766b9f0df3640b791be569d988f4be6c06d6fae41f187f105", size = 271013 }, + { url = "https://files.pythonhosted.org/packages/a4/c6/79dc4a7c598a978e5fafa135090aaf7bbb03b8dec7bada437dfbe578e7ed/watchfiles-1.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:05d341c71f3d7098920f8551d4df47f7b57ac5b8dad56558064c3431bdfc0b74", size = 284229 }, + { url = "https://files.pythonhosted.org/packages/37/3d/928633723211753f3500bfb138434f080363b87a1b08ca188b1ce54d1e05/watchfiles-1.0.4-cp311-cp311-win_arm64.whl", hash = "sha256:32b026a6ab64245b584acf4931fe21842374da82372d5c039cba6bf99ef722f3", size = 276824 }, + { url = "https://files.pythonhosted.org/packages/5b/1a/8f4d9a1461709756ace48c98f07772bc6d4519b1e48b5fa24a4061216256/watchfiles-1.0.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:229e6ec880eca20e0ba2f7e2249c85bae1999d330161f45c78d160832e026ee2", size = 391345 }, + { url = "https://files.pythonhosted.org/packages/bc/d2/6750b7b3527b1cdaa33731438432e7238a6c6c40a9924049e4cebfa40805/watchfiles-1.0.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5717021b199e8353782dce03bd8a8f64438832b84e2885c4a645f9723bf656d9", size = 381515 }, + { url = "https://files.pythonhosted.org/packages/4e/17/80500e42363deef1e4b4818729ed939aaddc56f82f4e72b2508729dd3c6b/watchfiles-1.0.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0799ae68dfa95136dde7c472525700bd48777875a4abb2ee454e3ab18e9fc712", size = 449767 }, + { url = "https://files.pythonhosted.org/packages/10/37/1427fa4cfa09adbe04b1e97bced19a29a3462cc64c78630787b613a23f18/watchfiles-1.0.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:43b168bba889886b62edb0397cab5b6490ffb656ee2fcb22dec8bfeb371a9e12", size = 455677 }, + { url = "https://files.pythonhosted.org/packages/c5/7a/39e9397f3a19cb549a7d380412fd9e507d4854eddc0700bfad10ef6d4dba/watchfiles-1.0.4-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb2c46e275fbb9f0c92e7654b231543c7bbfa1df07cdc4b99fa73bedfde5c844", size = 482219 }, + { url = "https://files.pythonhosted.org/packages/45/2d/7113931a77e2ea4436cad0c1690c09a40a7f31d366f79c6f0a5bc7a4f6d5/watchfiles-1.0.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:857f5fc3aa027ff5e57047da93f96e908a35fe602d24f5e5d8ce64bf1f2fc733", size = 518830 }, + { url = "https://files.pythonhosted.org/packages/f9/1b/50733b1980fa81ef3c70388a546481ae5fa4c2080040100cd7bf3bf7b321/watchfiles-1.0.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55ccfd27c497b228581e2838d4386301227fc0cb47f5a12923ec2fe4f97b95af", size = 497997 }, + { url = "https://files.pythonhosted.org/packages/2b/b4/9396cc61b948ef18943e7c85ecfa64cf940c88977d882da57147f62b34b1/watchfiles-1.0.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c11ea22304d17d4385067588123658e9f23159225a27b983f343fcffc3e796a", size = 452249 }, + { url = "https://files.pythonhosted.org/packages/fb/69/0c65a5a29e057ad0dc691c2fa6c23b2983c7dabaa190ba553b29ac84c3cc/watchfiles-1.0.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:74cb3ca19a740be4caa18f238298b9d472c850f7b2ed89f396c00a4c97e2d9ff", size = 614412 }, + { url = "https://files.pythonhosted.org/packages/7f/b9/319fcba6eba5fad34327d7ce16a6b163b39741016b1996f4a3c96b8dd0e1/watchfiles-1.0.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c7cce76c138a91e720d1df54014a047e680b652336e1b73b8e3ff3158e05061e", size = 611982 }, + { url = "https://files.pythonhosted.org/packages/f1/47/143c92418e30cb9348a4387bfa149c8e0e404a7c5b0585d46d2f7031b4b9/watchfiles-1.0.4-cp312-cp312-win32.whl", hash = "sha256:b045c800d55bc7e2cadd47f45a97c7b29f70f08a7c2fa13241905010a5493f94", size = 271822 }, + { url = "https://files.pythonhosted.org/packages/ea/94/b0165481bff99a64b29e46e07ac2e0df9f7a957ef13bec4ceab8515f44e3/watchfiles-1.0.4-cp312-cp312-win_amd64.whl", hash = "sha256:c2acfa49dd0ad0bf2a9c0bb9a985af02e89345a7189be1efc6baa085e0f72d7c", size = 285441 }, + { url = "https://files.pythonhosted.org/packages/11/de/09fe56317d582742d7ca8c2ca7b52a85927ebb50678d9b0fa8194658f536/watchfiles-1.0.4-cp312-cp312-win_arm64.whl", hash = "sha256:22bb55a7c9e564e763ea06c7acea24fc5d2ee5dfc5dafc5cfbedfe58505e9f90", size = 277141 }, + { url = "https://files.pythonhosted.org/packages/08/98/f03efabec64b5b1fa58c0daab25c68ef815b0f320e54adcacd0d6847c339/watchfiles-1.0.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:8012bd820c380c3d3db8435e8cf7592260257b378b649154a7948a663b5f84e9", size = 390954 }, + { url = "https://files.pythonhosted.org/packages/16/09/4dd49ba0a32a45813debe5fb3897955541351ee8142f586303b271a02b40/watchfiles-1.0.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa216f87594f951c17511efe5912808dfcc4befa464ab17c98d387830ce07b60", size = 381133 }, + { url = "https://files.pythonhosted.org/packages/76/59/5aa6fc93553cd8d8ee75c6247763d77c02631aed21551a97d94998bf1dae/watchfiles-1.0.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c9953cf85529c05b24705639ffa390f78c26449e15ec34d5339e8108c7c407", size = 449516 }, + { url = "https://files.pythonhosted.org/packages/4c/aa/df4b6fe14b6317290b91335b23c96b488d365d65549587434817e06895ea/watchfiles-1.0.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7cf684aa9bba4cd95ecb62c822a56de54e3ae0598c1a7f2065d51e24637a3c5d", size = 454820 }, + { url = "https://files.pythonhosted.org/packages/5e/71/185f8672f1094ce48af33252c73e39b48be93b761273872d9312087245f6/watchfiles-1.0.4-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f44a39aee3cbb9b825285ff979ab887a25c5d336e5ec3574f1506a4671556a8d", size = 481550 }, + { url = "https://files.pythonhosted.org/packages/85/d7/50ebba2c426ef1a5cb17f02158222911a2e005d401caf5d911bfca58f4c4/watchfiles-1.0.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38320582736922be8c865d46520c043bff350956dfc9fbaee3b2df4e1740a4b", size = 518647 }, + { url = "https://files.pythonhosted.org/packages/f0/7a/4c009342e393c545d68987e8010b937f72f47937731225b2b29b7231428f/watchfiles-1.0.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39f4914548b818540ef21fd22447a63e7be6e24b43a70f7642d21f1e73371590", size = 497547 }, + { url = "https://files.pythonhosted.org/packages/0f/7c/1cf50b35412d5c72d63b2bf9a4fffee2e1549a245924960dd087eb6a6de4/watchfiles-1.0.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f12969a3765909cf5dc1e50b2436eb2c0e676a3c75773ab8cc3aa6175c16e902", size = 452179 }, + { url = "https://files.pythonhosted.org/packages/d6/a9/3db1410e1c1413735a9a472380e4f431ad9a9e81711cda2aaf02b7f62693/watchfiles-1.0.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:0986902677a1a5e6212d0c49b319aad9cc48da4bd967f86a11bde96ad9676ca1", size = 614125 }, + { url = "https://files.pythonhosted.org/packages/f2/e1/0025d365cf6248c4d1ee4c3d2e3d373bdd3f6aff78ba4298f97b4fad2740/watchfiles-1.0.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:308ac265c56f936636e3b0e3f59e059a40003c655228c131e1ad439957592303", size = 611911 }, + { url = "https://files.pythonhosted.org/packages/55/55/035838277d8c98fc8c917ac9beeb0cd6c59d675dc2421df5f9fcf44a0070/watchfiles-1.0.4-cp313-cp313-win32.whl", hash = "sha256:aee397456a29b492c20fda2d8961e1ffb266223625346ace14e4b6d861ba9c80", size = 271152 }, + { url = "https://files.pythonhosted.org/packages/f0/e5/96b8e55271685ddbadc50ce8bc53aa2dff278fb7ac4c2e473df890def2dc/watchfiles-1.0.4-cp313-cp313-win_amd64.whl", hash = "sha256:d6097538b0ae5c1b88c3b55afa245a66793a8fec7ada6755322e465fb1a0e8cc", size = 285216 }, +] + +[[package]] +name = "websockets" +version = "15.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9f/32/18fcd5919c293a398db67443acd33fde142f283853076049824fc58e6f75/websockets-15.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431", size = 175423 }, + { url = "https://files.pythonhosted.org/packages/76/70/ba1ad96b07869275ef42e2ce21f07a5b0148936688c2baf7e4a1f60d5058/websockets-15.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57", size = 173082 }, + { url = "https://files.pythonhosted.org/packages/86/f2/10b55821dd40eb696ce4704a87d57774696f9451108cff0d2824c97e0f97/websockets-15.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905", size = 173330 }, + { url = "https://files.pythonhosted.org/packages/a5/90/1c37ae8b8a113d3daf1065222b6af61cc44102da95388ac0018fcb7d93d9/websockets-15.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562", size = 182878 }, + { url = "https://files.pythonhosted.org/packages/8e/8d/96e8e288b2a41dffafb78e8904ea7367ee4f891dafc2ab8d87e2124cb3d3/websockets-15.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792", size = 181883 }, + { url = "https://files.pythonhosted.org/packages/93/1f/5d6dbf551766308f6f50f8baf8e9860be6182911e8106da7a7f73785f4c4/websockets-15.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413", size = 182252 }, + { url = "https://files.pythonhosted.org/packages/d4/78/2d4fed9123e6620cbf1706c0de8a1632e1a28e7774d94346d7de1bba2ca3/websockets-15.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8", size = 182521 }, + { url = "https://files.pythonhosted.org/packages/e7/3b/66d4c1b444dd1a9823c4a81f50231b921bab54eee2f69e70319b4e21f1ca/websockets-15.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3", size = 181958 }, + { url = "https://files.pythonhosted.org/packages/08/ff/e9eed2ee5fed6f76fdd6032ca5cd38c57ca9661430bb3d5fb2872dc8703c/websockets-15.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf", size = 181918 }, + { url = "https://files.pythonhosted.org/packages/d8/75/994634a49b7e12532be6a42103597b71098fd25900f7437d6055ed39930a/websockets-15.0.1-cp311-cp311-win32.whl", hash = "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85", size = 176388 }, + { url = "https://files.pythonhosted.org/packages/98/93/e36c73f78400a65f5e236cd376713c34182e6663f6889cd45a4a04d8f203/websockets-15.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065", size = 176828 }, + { url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437 }, + { url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096 }, + { url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332 }, + { url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152 }, + { url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096 }, + { url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523 }, + { url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790 }, + { url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165 }, + { url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160 }, + { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395 }, + { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841 }, + { url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440 }, + { url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098 }, + { url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329 }, + { url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111 }, + { url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054 }, + { url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496 }, + { url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829 }, + { url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217 }, + { url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195 }, + { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393 }, + { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837 }, + { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743 }, +] diff --git a/syft/pkg/cataloger/python/test-fixtures/uv/simple-deps/pyproject.toml b/syft/pkg/cataloger/python/test-fixtures/uv/simple-deps/pyproject.toml new file mode 100644 index 00000000000..2037837ede6 --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/uv/simple-deps/pyproject.toml @@ -0,0 +1,8 @@ +# fixture is not under test, just used to produde the uv.lock +[project] +name = "testpkg" +version = "0.1.0" + +dependencies = [ + "requests>=2.32.2<3" +] diff --git a/syft/pkg/cataloger/python/test-fixtures/uv/simple-deps/uv.lock b/syft/pkg/cataloger/python/test-fixtures/uv/simple-deps/uv.lock new file mode 100644 index 00000000000..a7db7a062c9 --- /dev/null +++ b/syft/pkg/cataloger/python/test-fixtures/uv/simple-deps/uv.lock @@ -0,0 +1,103 @@ +version = 1 +requires-python = ">=3.11" + +[[package]] +name = "certifi" +version = "2025.1.31" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/80/41ef5d5a7935d2d3a773e3eaebf0a9350542f2cab4eac59a7a4741fbbbbe/charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125", size = 194995 }, + { url = "https://files.pythonhosted.org/packages/7a/28/0b9fefa7b8b080ec492110af6d88aa3dea91c464b17d53474b6e9ba5d2c5/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1", size = 139471 }, + { url = "https://files.pythonhosted.org/packages/71/64/d24ab1a997efb06402e3fc07317e94da358e2585165930d9d59ad45fcae2/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3", size = 149831 }, + { url = "https://files.pythonhosted.org/packages/37/ed/be39e5258e198655240db5e19e0b11379163ad7070962d6b0c87ed2c4d39/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd", size = 142335 }, + { url = "https://files.pythonhosted.org/packages/88/83/489e9504711fa05d8dde1574996408026bdbdbd938f23be67deebb5eca92/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00", size = 143862 }, + { url = "https://files.pythonhosted.org/packages/c6/c7/32da20821cf387b759ad24627a9aca289d2822de929b8a41b6241767b461/charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12", size = 145673 }, + { url = "https://files.pythonhosted.org/packages/68/85/f4288e96039abdd5aeb5c546fa20a37b50da71b5cf01e75e87f16cd43304/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77", size = 140211 }, + { url = "https://files.pythonhosted.org/packages/28/a3/a42e70d03cbdabc18997baf4f0227c73591a08041c149e710045c281f97b/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146", size = 148039 }, + { url = "https://files.pythonhosted.org/packages/85/e4/65699e8ab3014ecbe6f5c71d1a55d810fb716bbfd74f6283d5c2aa87febf/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd", size = 151939 }, + { url = "https://files.pythonhosted.org/packages/b1/82/8e9fe624cc5374193de6860aba3ea8070f584c8565ee77c168ec13274bd2/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6", size = 149075 }, + { url = "https://files.pythonhosted.org/packages/3d/7b/82865ba54c765560c8433f65e8acb9217cb839a9e32b42af4aa8e945870f/charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8", size = 144340 }, + { url = "https://files.pythonhosted.org/packages/b5/b6/9674a4b7d4d99a0d2df9b215da766ee682718f88055751e1e5e753c82db0/charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b", size = 95205 }, + { url = "https://files.pythonhosted.org/packages/1e/ab/45b180e175de4402dcf7547e4fb617283bae54ce35c27930a6f35b6bef15/charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76", size = 102441 }, + { url = "https://files.pythonhosted.org/packages/0a/9a/dd1e1cdceb841925b7798369a09279bd1cf183cef0f9ddf15a3a6502ee45/charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545", size = 196105 }, + { url = "https://files.pythonhosted.org/packages/d3/8c/90bfabf8c4809ecb648f39794cf2a84ff2e7d2a6cf159fe68d9a26160467/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7", size = 140404 }, + { url = "https://files.pythonhosted.org/packages/ad/8f/e410d57c721945ea3b4f1a04b74f70ce8fa800d393d72899f0a40526401f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757", size = 150423 }, + { url = "https://files.pythonhosted.org/packages/f0/b8/e6825e25deb691ff98cf5c9072ee0605dc2acfca98af70c2d1b1bc75190d/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa", size = 143184 }, + { url = "https://files.pythonhosted.org/packages/3e/a2/513f6cbe752421f16d969e32f3583762bfd583848b763913ddab8d9bfd4f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d", size = 145268 }, + { url = "https://files.pythonhosted.org/packages/74/94/8a5277664f27c3c438546f3eb53b33f5b19568eb7424736bdc440a88a31f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616", size = 147601 }, + { url = "https://files.pythonhosted.org/packages/7c/5f/6d352c51ee763623a98e31194823518e09bfa48be2a7e8383cf691bbb3d0/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b", size = 141098 }, + { url = "https://files.pythonhosted.org/packages/78/d4/f5704cb629ba5ab16d1d3d741396aec6dc3ca2b67757c45b0599bb010478/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d", size = 149520 }, + { url = "https://files.pythonhosted.org/packages/c5/96/64120b1d02b81785f222b976c0fb79a35875457fa9bb40827678e54d1bc8/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a", size = 152852 }, + { url = "https://files.pythonhosted.org/packages/84/c9/98e3732278a99f47d487fd3468bc60b882920cef29d1fa6ca460a1fdf4e6/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9", size = 150488 }, + { url = "https://files.pythonhosted.org/packages/13/0e/9c8d4cb99c98c1007cc11eda969ebfe837bbbd0acdb4736d228ccaabcd22/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1", size = 146192 }, + { url = "https://files.pythonhosted.org/packages/b2/21/2b6b5b860781a0b49427309cb8670785aa543fb2178de875b87b9cc97746/charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35", size = 95550 }, + { url = "https://files.pythonhosted.org/packages/21/5b/1b390b03b1d16c7e382b561c5329f83cc06623916aab983e8ab9239c7d5c/charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f", size = 102785 }, + { url = "https://files.pythonhosted.org/packages/38/94/ce8e6f63d18049672c76d07d119304e1e2d7c6098f0841b51c666e9f44a0/charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", size = 195698 }, + { url = "https://files.pythonhosted.org/packages/24/2e/dfdd9770664aae179a96561cc6952ff08f9a8cd09a908f259a9dfa063568/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", size = 140162 }, + { url = "https://files.pythonhosted.org/packages/24/4e/f646b9093cff8fc86f2d60af2de4dc17c759de9d554f130b140ea4738ca6/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", size = 150263 }, + { url = "https://files.pythonhosted.org/packages/5e/67/2937f8d548c3ef6e2f9aab0f6e21001056f692d43282b165e7c56023e6dd/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", size = 142966 }, + { url = "https://files.pythonhosted.org/packages/52/ed/b7f4f07de100bdb95c1756d3a4d17b90c1a3c53715c1a476f8738058e0fa/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", size = 144992 }, + { url = "https://files.pythonhosted.org/packages/96/2c/d49710a6dbcd3776265f4c923bb73ebe83933dfbaa841c5da850fe0fd20b/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", size = 147162 }, + { url = "https://files.pythonhosted.org/packages/b4/41/35ff1f9a6bd380303dea55e44c4933b4cc3c4850988927d4082ada230273/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", size = 140972 }, + { url = "https://files.pythonhosted.org/packages/fb/43/c6a0b685fe6910d08ba971f62cd9c3e862a85770395ba5d9cad4fede33ab/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", size = 149095 }, + { url = "https://files.pythonhosted.org/packages/4c/ff/a9a504662452e2d2878512115638966e75633519ec11f25fca3d2049a94a/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", size = 152668 }, + { url = "https://files.pythonhosted.org/packages/6c/71/189996b6d9a4b932564701628af5cee6716733e9165af1d5e1b285c530ed/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", size = 150073 }, + { url = "https://files.pythonhosted.org/packages/e4/93/946a86ce20790e11312c87c75ba68d5f6ad2208cfb52b2d6a2c32840d922/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", size = 145732 }, + { url = "https://files.pythonhosted.org/packages/cd/e5/131d2fb1b0dddafc37be4f3a2fa79aa4c037368be9423061dccadfd90091/charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", size = 95391 }, + { url = "https://files.pythonhosted.org/packages/27/f2/4f9a69cc7712b9b5ad8fdb87039fd89abba997ad5cbe690d1835d40405b0/charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", size = 102702 }, + { url = "https://files.pythonhosted.org/packages/0e/f6/65ecc6878a89bb1c23a086ea335ad4bf21a588990c3f535a227b9eea9108/charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", size = 49767 }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, +] + +[[package]] +name = "requests" +version = "2.32.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 }, +] + +[[package]] +name = "testpkg" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "requests" }, +] + +[package.metadata] +requires-dist = [{ name = "requests", specifier = ">=2.32.2,<3" }] + +[[package]] +name = "urllib3" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 }, +] diff --git a/syft/pkg/cataloger/redhat/cataloger.go b/syft/pkg/cataloger/redhat/cataloger.go index f2d1c142836..ba065695b9b 100644 --- a/syft/pkg/cataloger/redhat/cataloger.go +++ b/syft/pkg/cataloger/redhat/cataloger.go @@ -5,8 +5,8 @@ package redhat import ( "database/sql" + "fmt" - "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/generic" @@ -15,15 +15,11 @@ import ( // NewDBCataloger returns a new RPM DB cataloger object. func NewDBCataloger() pkg.Cataloger { - // check if a sqlite driver is available - if !isSqliteDriverAvailable() { - log.Debugf("sqlite driver is not available, newer RPM databases might not be cataloged") - } - return generic.NewCataloger("rpm-db-cataloger"). WithParserByGlobs(parseRpmDB, pkg.RpmDBGlob). WithParserByGlobs(parseRpmManifest, pkg.RpmManifestGlob). - WithProcessors(dependency.Processor(dbEntryDependencySpecifier), denySelfReferences) + WithProcessors(dependency.Processor(dbEntryDependencySpecifier), denySelfReferences). + WithChecks(ensureSqliteDriverAvailable) } func denySelfReferences(pkgs []pkg.Package, rels []artifact.Relationship, err error) ([]pkg.Package, []artifact.Relationship, error) { @@ -47,11 +43,11 @@ func NewArchiveCataloger() pkg.Cataloger { WithParserByGlobs(parseRpmArchive, "**/*.rpm") } -func isSqliteDriverAvailable() bool { +func ensureSqliteDriverAvailable() error { db, err := sql.Open("sqlite", ":memory:") if err != nil { - return false + return fmt.Errorf("sqlite driver is required for cataloging newer RPM databases, none registered: %v", err) } _ = db.Close() - return true + return nil } diff --git a/syft/pkg/cataloger/redhat/sqlitetest/no_sqlite_driver_test.go b/syft/pkg/cataloger/redhat/sqlitetest/no_sqlite_driver_test.go new file mode 100644 index 00000000000..f1a3f17e411 --- /dev/null +++ b/syft/pkg/cataloger/redhat/sqlitetest/no_sqlite_driver_test.go @@ -0,0 +1,22 @@ +package sqlitetest + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/anchore/syft/syft/internal/fileresolver" + "github.com/anchore/syft/syft/pkg/cataloger/redhat" +) + +func Test_noSQLiteDriverError(t *testing.T) { + // this test package does must not import the sqlite library + file := "../test-fixtures/Packages" + resolver, err := fileresolver.NewFromFile(file, file) + require.NoError(t, err) + + cataloger := redhat.NewDBCataloger() + _, _, err = cataloger.Catalog(context.TODO(), resolver) + require.ErrorContains(t, err, "sqlite") +} diff --git a/syft/pkg/cataloger/snap/cataloger.go b/syft/pkg/cataloger/snap/cataloger.go new file mode 100644 index 00000000000..5afdd3ef465 --- /dev/null +++ b/syft/pkg/cataloger/snap/cataloger.go @@ -0,0 +1,28 @@ +/* +Package snap provides a concrete Cataloger implementation for snap packages, extracting metadata +from different types of snap files (base, kernel, system/gadget, snapd) rather than just scanning +the filesystem. +*/ +package snap + +import ( + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/generic" +) + +const catalogerName = "snap-cataloger" + +// NewCataloger returns a new Snap cataloger object that can parse snap package metadata. +func NewCataloger() pkg.Cataloger { + return generic.NewCataloger(catalogerName). + // Look for snap.yaml to identify snap type and base snap info + WithParserByGlobs(parseSnapYaml, "**/meta/snap.yaml"). + // Base snaps: dpkg.yaml files containing package manifests + WithParserByGlobs(parseBaseDpkgYaml, "**/usr/share/snappy/dpkg.yaml"). + // Kernel snaps: changelog files for kernel version info + WithParserByGlobs(parseKernelChangelog, "**/doc/linux-modules-*/changelog.Debian.gz"). + // System/Gadget snaps: manifest files with primed-stage-packages + WithParserByGlobs(parseSystemManifest, "**/snap/manifest.yaml"). + // Snapd snaps: snapcraft.yaml files + WithParserByGlobs(parseSnapdSnapcraft, "**/snap/snapcraft.yaml") +} diff --git a/syft/pkg/cataloger/snap/cataloger_test.go b/syft/pkg/cataloger/snap/cataloger_test.go new file mode 100644 index 00000000000..bc4addace5f --- /dev/null +++ b/syft/pkg/cataloger/snap/cataloger_test.go @@ -0,0 +1,36 @@ +package snap + +import ( + "testing" + + "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" +) + +func TestCataloger_Globs(t *testing.T) { + tests := []struct { + name string + fixture string + }{ + { + name: "base snap with dpkg.yaml", + fixture: "test-fixtures/glob-paths/base", + }, + { + name: "system snap with manifest.yaml", + fixture: "test-fixtures/glob-paths/system", + }, + { + name: "snap with meta/snap.yaml", + fixture: "test-fixtures/glob-paths/meta", + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + pkgtest.NewCatalogTester(). + FromDirectory(t, test.fixture). + IgnoreUnfulfilledPathResponses("**/meta/snap.yaml", "**/usr/share/snappy/dpkg.yaml", "**/doc/linux-modules-*/changelog.Debian.gz", "**/snap/manifest.yaml", "**/snap/snapcraft.yaml"). + TestCataloger(t, NewCataloger()) + }) + } +} diff --git a/syft/pkg/cataloger/snap/integration_test.go b/syft/pkg/cataloger/snap/integration_test.go new file mode 100644 index 00000000000..128aad402d1 --- /dev/null +++ b/syft/pkg/cataloger/snap/integration_test.go @@ -0,0 +1,55 @@ +package snap + +import ( + "context" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/generic" +) + +func TestRealDpkgYamlParsing(t *testing.T) { + fixture := "test-fixtures/real-dpkg.yaml" + + // Open the file + f, err := os.Open(fixture) + require.NoError(t, err) + defer f.Close() + + reader := file.LocationReadCloser{ + Location: file.NewLocation(fixture), + ReadCloser: f, + } + + // Parse using our function + packages, relationships, err := parseBaseDpkgYaml(context.Background(), nil, &generic.Environment{}, reader) + + require.NoError(t, err) + assert.Nil(t, relationships) // relationships should be nil for this parser + + // We should have 10 packages from the fixture + assert.Equal(t, 10, len(packages)) + + // Check some specific packages + foundPackages := make(map[string]pkg.Package) + for _, p := range packages { + foundPackages[p.Name] = p + } + + // Verify key packages exist + require.Contains(t, foundPackages, "adduser") + require.Contains(t, foundPackages, "systemd") + require.Contains(t, foundPackages, "gcc-10-base") + + // Check that architecture is parsed correctly from package names + gccPkg := foundPackages["gcc-10-base"] + metadata, ok := gccPkg.Metadata.(pkg.SnapEntry) + require.True(t, ok) + assert.Equal(t, "amd64", metadata.Architecture) + assert.Equal(t, pkg.SnapTypeBase, metadata.SnapType) +} diff --git a/syft/pkg/cataloger/snap/package.go b/syft/pkg/cataloger/snap/package.go new file mode 100644 index 00000000000..997906c727a --- /dev/null +++ b/syft/pkg/cataloger/snap/package.go @@ -0,0 +1,94 @@ +package snap + +import ( + "github.com/anchore/packageurl-go" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" +) + +// newPackage creates a new Package from snap metadata +func newPackage(name, version string, metadata pkg.SnapEntry, locations ...file.Location) pkg.Package { + p := pkg.Package{ + Name: name, + Version: version, + Locations: file.NewLocationSet(locations...), + PURL: packageURL(name, version, metadata), + Type: pkg.DebPkg, // Use Debian package type for compatibility + Metadata: metadata, + } + + p.SetID() + + return p +} + +// packageURL returns the PURL for a snap package +func packageURL(name, version string, metadata pkg.SnapEntry) string { + var qualifiers packageurl.Qualifiers + + if metadata.Architecture != "" { + qualifiers = append(qualifiers, packageurl.Qualifier{ + Key: "arch", + Value: metadata.Architecture, + }) + } + + if metadata.Base != "" { + qualifiers = append(qualifiers, packageurl.Qualifier{ + Key: "base", + Value: metadata.Base, + }) + } + + if metadata.SnapType != "" { + qualifiers = append(qualifiers, packageurl.Qualifier{ + Key: "type", + Value: metadata.SnapType, + }) + } + + return packageurl.NewPackageURL( + packageurl.TypeGeneric, + "snap", + name, + version, + qualifiers, + "", + ).ToString() +} + +// newDebianPackageFromSnap creates a Debian-style package entry from snap manifest data +func newDebianPackageFromSnap(name, version string, snapMetadata pkg.SnapEntry, locations ...file.Location) pkg.Package { + p := pkg.Package{ + Name: name, + Version: version, + Locations: file.NewLocationSet(locations...), + Type: pkg.DebPkg, + PURL: debianPackageURL(name, version, snapMetadata.Architecture), + Metadata: snapMetadata, + } + + p.SetID() + return p +} + +// debianPackageURL creates a PURL for Debian packages found in snaps +func debianPackageURL(name, version, architecture string) string { + var qualifiers packageurl.Qualifiers + + if architecture != "" { + qualifiers = append(qualifiers, packageurl.Qualifier{ + Key: "arch", + Value: architecture, + }) + } + + return packageurl.NewPackageURL( + packageurl.TypeDebian, + "ubuntu", // Assume Ubuntu since most snaps are built on Ubuntu + name, + version, + qualifiers, + "", + ).ToString() +} diff --git a/syft/pkg/cataloger/snap/parse_base_dpkg.go b/syft/pkg/cataloger/snap/parse_base_dpkg.go new file mode 100644 index 00000000000..b73f82555a6 --- /dev/null +++ b/syft/pkg/cataloger/snap/parse_base_dpkg.go @@ -0,0 +1,80 @@ +package snap + +import ( + "context" + "fmt" + "strings" + + "gopkg.in/yaml.v3" + + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/generic" +) + +// dpkgYaml represents the structure of dpkg.yaml files found in base snaps +type dpkgYaml struct { + PackageRepositories []packageRepository `yaml:"package-repositories"` + Packages []string `yaml:"packages"` +} + +type packageRepository struct { + Type string `yaml:"type"` + PPA string `yaml:"ppa,omitempty"` + URL string `yaml:"url,omitempty"` +} + +// parseBaseDpkgYaml parses dpkg.yaml files from base snaps +func parseBaseDpkgYaml(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + var dpkg dpkgYaml + + decoder := yaml.NewDecoder(reader) + if err := decoder.Decode(&dpkg); err != nil { + return nil, nil, fmt.Errorf("failed to parse dpkg.yaml: %w", err) + } + + var packages []pkg.Package + + snapMetadata := pkg.SnapEntry{ + SnapType: pkg.SnapTypeBase, + } + + // Parse each package entry in "name=version" format + for _, pkgEntry := range dpkg.Packages { + if !strings.Contains(pkgEntry, "=") { + continue // Skip malformed entries + } + + parts := strings.SplitN(pkgEntry, "=", 2) + if len(parts) != 2 { + continue + } + + name := strings.TrimSpace(parts[0]) + version := strings.TrimSpace(parts[1]) + + // Skip empty names or versions + if name == "" || version == "" { + continue + } + + // Handle architecture suffixes (e.g., "libssl1.1:amd64") + if strings.Contains(name, ":") { + archParts := strings.SplitN(name, ":", 2) + name = archParts[0] + snapMetadata.Architecture = archParts[1] + } + + debPkg := newDebianPackageFromSnap( + name, + version, + snapMetadata, + reader.Location, + ) + + packages = append(packages, debPkg) + } + + return packages, nil, nil +} diff --git a/syft/pkg/cataloger/snap/parse_base_dpkg_test.go b/syft/pkg/cataloger/snap/parse_base_dpkg_test.go new file mode 100644 index 00000000000..b9e4c7ab635 --- /dev/null +++ b/syft/pkg/cataloger/snap/parse_base_dpkg_test.go @@ -0,0 +1,50 @@ +package snap + +import ( + "testing" + + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" +) + +func TestParseBaseDpkgYaml(t *testing.T) { + fixture := "test-fixtures/dpkg.yaml" + locations := file.NewLocationSet(file.NewLocation(fixture)) + + expected := []pkg.Package{ + { + Name: "adduser", + Version: "3.118ubuntu2", + Type: pkg.DebPkg, + PURL: "pkg:deb/ubuntu/adduser@3.118ubuntu2", + Locations: locations, + Metadata: pkg.SnapEntry{ + SnapType: pkg.SnapTypeBase, + }, + }, + { + Name: "apparmor", + Version: "2.13.3-7ubuntu5.3", + Type: pkg.DebPkg, + PURL: "pkg:deb/ubuntu/apparmor@2.13.3-7ubuntu5.3", + Locations: locations, + Metadata: pkg.SnapEntry{ + SnapType: pkg.SnapTypeBase, + }, + }, + { + Name: "gcc-10-base", + Version: "10.5.0-1ubuntu1~20.04", + Type: pkg.DebPkg, + PURL: "pkg:deb/ubuntu/gcc-10-base@10.5.0-1ubuntu1~20.04?arch=amd64", + Locations: locations, + Metadata: pkg.SnapEntry{ + SnapType: pkg.SnapTypeBase, + Architecture: "amd64", // from package name suffix + }, + }, + } + + pkgtest.TestFileParser(t, fixture, parseBaseDpkgYaml, expected, nil) +} diff --git a/syft/pkg/cataloger/snap/parse_integration_test.go b/syft/pkg/cataloger/snap/parse_integration_test.go new file mode 100644 index 00000000000..b7039ba28e2 --- /dev/null +++ b/syft/pkg/cataloger/snap/parse_integration_test.go @@ -0,0 +1,71 @@ +package snap + +import ( + "testing" + + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" +) + +func TestParseSnapYaml(t *testing.T) { + fixture := "test-fixtures/snap.yaml" + locations := file.NewLocationSet(file.NewLocation(fixture)) + + expected := []pkg.Package{ + { + Name: "test-snap", + Version: "1.0.0", + Type: pkg.DebPkg, + PURL: "pkg:generic/snap/test-snap@1.0.0?arch=amd64&base=core20&type=app", + Locations: locations, + Metadata: pkg.SnapEntry{ + SnapType: pkg.SnapTypeApp, + Base: "core20", + SnapName: "test-snap", + SnapVersion: "1.0.0", + Architecture: "amd64", + }, + }, + } + + pkgtest.TestFileParser(t, fixture, parseSnapYaml, expected, nil) +} + +func TestParseSystemManifest(t *testing.T) { + fixture := "test-fixtures/manifest.yaml" + locations := file.NewLocationSet(file.NewLocation(fixture)) + + expected := []pkg.Package{ + { + Name: "grub-efi-amd64-signed", + Version: "1.202+2.12-1ubuntu7", + Type: pkg.DebPkg, + PURL: "pkg:deb/ubuntu/grub-efi-amd64-signed@1.202%2B2.12-1ubuntu7?arch=amd64", // URL encoded + Locations: locations, + Metadata: pkg.SnapEntry{ + SnapType: pkg.SnapTypeApp, // Default type when gadget not detected from name + Base: "core24", + SnapName: "pc", + SnapVersion: "24-0.1", + Architecture: "amd64", // From architectures array + }, + }, + { + Name: "shim-signed", + Version: "1.56+15.7-0ubuntu1", + Type: pkg.DebPkg, + PURL: "pkg:deb/ubuntu/shim-signed@1.56%2B15.7-0ubuntu1?arch=amd64", // URL encoded + Locations: locations, + Metadata: pkg.SnapEntry{ + SnapType: pkg.SnapTypeApp, // Default type when gadget not detected from name + Base: "core24", + SnapName: "pc", + SnapVersion: "24-0.1", + Architecture: "amd64", // From architectures array + }, + }, + } + + pkgtest.TestFileParser(t, fixture, parseSystemManifest, expected, nil) +} diff --git a/syft/pkg/cataloger/snap/parse_kernel_changelog.go b/syft/pkg/cataloger/snap/parse_kernel_changelog.go new file mode 100644 index 00000000000..06700981d10 --- /dev/null +++ b/syft/pkg/cataloger/snap/parse_kernel_changelog.go @@ -0,0 +1,160 @@ +package snap + +import ( + "compress/gzip" + "context" + "fmt" + "regexp" + "strings" + + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/generic" +) + +// kernelVersionInfo holds parsed kernel version information +type kernelVersionInfo struct { + baseVersion string // e.g., "5.4.0-195" + releaseVersion string // e.g., "215" + fullVersion string // e.g., "5.4.0-195.215" + majorVersion string // e.g., "5.4" +} + +// parseKernelChangelog parses changelog files from kernel snaps to extract kernel version +func parseKernelChangelog(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + // The file should be gzipped + lines, err := readChangelogLines(reader) + if err != nil { + return nil, nil, err + } + + // pull from first line + versionInfo, err := extractKernelVersion(lines[0]) + if err != nil { + return nil, nil, err + } + + snapMetadata := pkg.SnapEntry{ + SnapType: pkg.SnapTypeKernel, + } + + packages := createMainKernelPackage(versionInfo, snapMetadata, reader.Location) + + // Check for base kernel package + basePackage := findBaseKernelPackage(lines, versionInfo, snapMetadata, reader.Location) + if basePackage != nil { + packages = append(packages, *basePackage) + } + + return packages, nil, nil +} + +// readChangelogLines reads and decompresses the changelog content +func readChangelogLines(reader file.LocationReadCloser) ([]string, error) { + gzReader, err := gzip.NewReader(reader) + if err != nil { + return nil, fmt.Errorf("failed to create gzip reader for changelog: %w", err) + } + defer gzReader.Close() + + content, err := readAll(gzReader) + if err != nil { + return nil, fmt.Errorf("failed to read changelog content: %w", err) + } + + lines := strings.Split(string(content), "\n") + if len(lines) == 0 { + return nil, fmt.Errorf("changelog file is empty") + } + + // Parse the first line to extract kernel version information + // Format: "linux (5.4.0-195.215) focal; urgency=medium" + return lines, nil +} + +// extractKernelVersion parses version information from the first changelog line +func extractKernelVersion(firstLine string) (*kernelVersionInfo, error) { + // Format: "linux (5.4.0-195.215) focal; urgency=medium" + kernelVersionRegex := regexp.MustCompile(`linux \(([0-9]+\.[0-9]+\.[0-9]+-[0-9]+)\.([0-9]+)\)`) + matches := kernelVersionRegex.FindStringSubmatch(firstLine) + + if len(matches) < 3 { + return nil, fmt.Errorf("could not parse kernel version from changelog: %s", firstLine) + } + + info := &kernelVersionInfo{ + baseVersion: matches[1], // e.g., "5.4.0-195" + releaseVersion: matches[2], // eg., "215" + } + // eg "5.4.0-195.215" + info.fullVersion = fmt.Sprintf("%s.%s", info.baseVersion, info.releaseVersion) + + // Extract major version; package naming + majorVersionRegex := regexp.MustCompile(`([0-9]+\.[0-9]+)\.[0-9]+-[0-9]+`) + majorMatches := majorVersionRegex.FindStringSubmatch(info.baseVersion) + + if len(majorMatches) >= 2 { + info.majorVersion = majorMatches[1] + } else { + info.majorVersion = info.baseVersion + } + + return info, nil +} + +// createMainKernelPackage creates the main kernel package +func createMainKernelPackage(versionInfo *kernelVersionInfo, snapMetadata pkg.SnapEntry, location file.Location) []pkg.Package { + kernelPackageName := fmt.Sprintf("linux-image-%s-generic", versionInfo.baseVersion) + kernelPkg := newDebianPackageFromSnap( + kernelPackageName, + versionInfo.fullVersion, + snapMetadata, + location, + ) + + return []pkg.Package{kernelPkg} +} + +// findBaseKernelPackage searches for and creates base kernel package if present +func findBaseKernelPackage(lines []string, versionInfo *kernelVersionInfo, snapMetadata pkg.SnapEntry, location file.Location) *pkg.Package { + baseKernelEntry := fmt.Sprintf("%s/linux:", strings.ReplaceAll(versionInfo.releaseVersion, ";", "/")) + + for _, line := range lines { + if strings.Contains(line, baseKernelEntry) { + return parseBaseKernelLine(line, versionInfo.majorVersion, snapMetadata, location) + } + } + + return nil +} + +// parseBaseKernelLine extracts base kernel version from a changelog line +func parseBaseKernelLine(line string, majorVersion string, snapMetadata pkg.SnapEntry, location file.Location) *pkg.Package { + baseKernelRegex := regexp.MustCompile(fmt.Sprintf(`(%s-[0-9]+)\.?[0-9]*`, regexp.QuoteMeta(majorVersion))) + baseMatches := baseKernelRegex.FindStringSubmatch(line) + + if len(baseMatches) < 2 { + return nil + } + + baseKernelVersion := baseMatches[1] + baseKernelFullRegex := regexp.MustCompile(fmt.Sprintf(`(%s-[0-9]+\.[0-9]+)`, regexp.QuoteMeta(majorVersion))) + baseFullMatches := baseKernelFullRegex.FindStringSubmatch(line) + + var baseFullVersion string + if len(baseFullMatches) >= 2 { + baseFullVersion = baseFullMatches[1] + } else { + baseFullVersion = baseKernelVersion + } + + baseKernelPkg := newDebianPackageFromSnap( + fmt.Sprintf("linux-image-%s-generic", baseKernelVersion), + baseFullVersion, + snapMetadata, + location, + ) + + return &baseKernelPkg +} diff --git a/syft/pkg/cataloger/snap/parse_snap_yaml.go b/syft/pkg/cataloger/snap/parse_snap_yaml.go new file mode 100644 index 00000000000..e9897dafab4 --- /dev/null +++ b/syft/pkg/cataloger/snap/parse_snap_yaml.go @@ -0,0 +1,68 @@ +package snap + +import ( + "context" + "fmt" + "io" + + "gopkg.in/yaml.v3" + + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/generic" +) + +// snapYaml represents the structure of meta/snap.yaml files +type snapYaml struct { + Name string `yaml:"name"` + Version string `yaml:"version"` + Base string `yaml:"base"` + Type string `yaml:"type"` + Architecture string `yaml:"architecture"` + Summary string `yaml:"summary"` + Description string `yaml:"description"` +} + +// parseSnapYaml parses meta/snap.yaml files to identify snap type and basic metadata +func parseSnapYaml(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + var snap snapYaml + + decoder := yaml.NewDecoder(reader) + if err := decoder.Decode(&snap); err != nil { + return nil, nil, fmt.Errorf("failed to parse snap.yaml: %w", err) + } + + if snap.Name == "" { + return nil, nil, fmt.Errorf("snap.yaml missing required 'name' field") + } + + // Determine snap type - default to "app" if not specified + snapType := snap.Type + if snapType == "" { + snapType = pkg.SnapTypeApp + } + + metadata := pkg.SnapEntry{ + SnapType: snapType, + Base: snap.Base, + SnapName: snap.Name, + SnapVersion: snap.Version, + Architecture: snap.Architecture, + } + + // Create a package representing the snap itself + snapPkg := newPackage( + snap.Name, + snap.Version, + metadata, + reader.Location, + ) + + return []pkg.Package{snapPkg}, nil, nil +} + +// readAll reads all content from a reader and returns it as bytes +func readAll(r io.Reader) ([]byte, error) { + return io.ReadAll(r) +} diff --git a/syft/pkg/cataloger/snap/parse_snapd_snapcraft.go b/syft/pkg/cataloger/snap/parse_snapd_snapcraft.go new file mode 100644 index 00000000000..8a085f9abcb --- /dev/null +++ b/syft/pkg/cataloger/snap/parse_snapd_snapcraft.go @@ -0,0 +1,188 @@ +package snap + +import ( + "context" + "fmt" + "strings" + + "gopkg.in/yaml.v3" + + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/generic" +) + +// snapcraftYaml represents the structure of snapcraft.yaml files found in snapd snaps +type snapcraftYaml struct { + Name string `yaml:"name"` + Version string `yaml:"version"` + Summary string `yaml:"summary"` + Description string `yaml:"description"` + Base string `yaml:"base"` + Grade string `yaml:"grade"` + Confinement string `yaml:"confinement"` + Architectures []string `yaml:"architectures"` + Parts map[string]snapcraftPart `yaml:"parts"` +} + +// snapcraftPart represents a part in a snapcraft.yaml file +type snapcraftPart struct { + Plugin string `yaml:"plugin"` + Source string `yaml:"source"` + SourceType string `yaml:"source-type"` + SourceTag string `yaml:"source-tag"` + SourceCommit string `yaml:"source-commit"` + BuildPackages []string `yaml:"build-packages"` + StagePackages []string `yaml:"stage-packages"` + BuildSnaps []string `yaml:"build-snaps"` + StageSnaps []string `yaml:"stage-snaps"` + BuildEnvironment []map[string]string `yaml:"build-environment"` + Override map[string]string `yaml:"override-build"` +} + +// parseSnapdSnapcraft parses snapcraft.yaml files from snapd snaps +func parseSnapdSnapcraft(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + var snapcraft snapcraftYaml + + decoder := yaml.NewDecoder(reader) + if err := decoder.Decode(&snapcraft); err != nil { + return nil, nil, fmt.Errorf("failed to parse snapcraft.yaml: %w", err) + } + + snapMetadata := createMetadata(snapcraft) + packages := extractPackagesFromParts(snapcraft, snapMetadata, reader.Location) + + return packages, nil, nil +} + +// createMetadata creates metadata from snapcraft.yaml +func createMetadata(snapcraft snapcraftYaml) pkg.SnapEntry { + metadata := pkg.SnapEntry{ + SnapType: pkg.SnapTypeSnapd, + Base: snapcraft.Base, + SnapName: snapcraft.Name, + SnapVersion: snapcraft.Version, + } + + if len(snapcraft.Architectures) > 0 { + metadata.Architecture = snapcraft.Architectures[0] + } + + return metadata +} + +// extractPackagesFromParts processes all parts to extract packages +func extractPackagesFromParts(snapcraft snapcraftYaml, baseMetadata pkg.SnapEntry, location file.Location) []pkg.Package { + var packages []pkg.Package + + for _, part := range snapcraft.Parts { + buildPackages := processBuildPackages(part.BuildPackages, baseMetadata, location) + packages = append(packages, buildPackages...) + + stagePackages := processStagePackages(part.StagePackages, baseMetadata, location) + packages = append(packages, stagePackages...) + + snapPackages := processSnapPackages(part.BuildSnaps, part.StageSnaps, baseMetadata, location) + packages = append(packages, snapPackages...) + } + + return packages +} + +// processBuildPackages creates packages from build-packages list +func processBuildPackages(buildPackages []string, metadata pkg.SnapEntry, location file.Location) []pkg.Package { + var packages []pkg.Package + + for _, pkgName := range buildPackages { + if pkgName == "" { + continue + } + + buildPkg := newDebianPackageFromSnap( + pkgName, + "unknown", + metadata, + location, + ) + packages = append(packages, buildPkg) + } + + return packages +} + +// processStagePackages creates packages from stage-packages list with version parsing +func processStagePackages(stagePackages []string, metadata pkg.SnapEntry, location file.Location) []pkg.Package { + var packages []pkg.Package + + for _, pkgEntry := range stagePackages { + if pkgEntry == "" { + continue + } + + name, version := parsePackageWithVersion(pkgEntry) + stagePkg := newDebianPackageFromSnap( + name, + version, + metadata, + location, + ) + packages = append(packages, stagePkg) + } + + return packages +} + +// parsePackageWithVersion extracts package name and version from version-constrained entries +func parsePackageWithVersion(pkgEntry string) (string, string) { + name := pkgEntry + version := "unknown" + + if !strings.ContainsAny(pkgEntry, "=<>") { + return name, version + } + + // Try to split on version operators + operators := []string{">=", "<=", "==", "!=", "=", ">", "<"} + for _, op := range operators { + if strings.Contains(pkgEntry, op) { + parts := strings.SplitN(pkgEntry, op, 2) + if len(parts) == 2 { + return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]) + } + } + } + + return name, version +} + +// processSnapPackages creates packages from snap dependencies +func processSnapPackages(buildSnaps, stageSnaps []string, baseMetadata pkg.SnapEntry, location file.Location) []pkg.Package { + var packages []pkg.Package + allSnaps := make([]string, 0, len(buildSnaps)+len(stageSnaps)) + allSnaps = append(allSnaps, buildSnaps...) + allSnaps = append(allSnaps, stageSnaps...) + + for _, snapName := range allSnaps { + if snapName == "" { + continue + } + + snapMetadata := pkg.SnapEntry{ + SnapType: pkg.SnapTypeApp, + SnapName: snapName, + SnapVersion: "unknown", + Architecture: baseMetadata.Architecture, + } + + snapPkg := newPackage( + snapName, + "unknown", + snapMetadata, + location, + ) + packages = append(packages, snapPkg) + } + + return packages +} diff --git a/syft/pkg/cataloger/snap/parse_system_manifest.go b/syft/pkg/cataloger/snap/parse_system_manifest.go new file mode 100644 index 00000000000..ee7159c8324 --- /dev/null +++ b/syft/pkg/cataloger/snap/parse_system_manifest.go @@ -0,0 +1,102 @@ +package snap + +import ( + "context" + "fmt" + "strings" + + "gopkg.in/yaml.v3" + + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/file" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/generic" +) + +// systemManifest represents the structure of manifest.yaml files found in system/gadget snaps +type systemManifest struct { + Name string `yaml:"name"` + Version string `yaml:"version"` + Base string `yaml:"base"` + Grade string `yaml:"grade"` + Confinement string `yaml:"confinement"` + PrimedStagePackages []string `yaml:"primed-stage-packages"` + Architectures []string `yaml:"architectures"` + SnapcraftVersion string `yaml:"snapcraft-version"` + SnapcraftOSReleaseID string `yaml:"snapcraft-os-release-id"` +} + +// parseSystemManifest parses manifest.yaml files from system/gadget snaps +func parseSystemManifest(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { + var manifest systemManifest + + decoder := yaml.NewDecoder(reader) + if err := decoder.Decode(&manifest); err != nil { + return nil, nil, fmt.Errorf("failed to parse manifest.yaml: %w", err) + } + + var packages []pkg.Package + + // Determine snap type - could be system, gadget, or app + snapType := pkg.SnapTypeApp // Default + if manifest.Name != "" { + // Try to infer type from name patterns or content + switch { + case strings.Contains(strings.ToLower(manifest.Name), "gadget"): + snapType = pkg.SnapTypeGadget + default: + snapType = pkg.SnapTypeApp // System snaps are often just regular apps + } + } + + snapMetadata := pkg.SnapEntry{ + SnapType: snapType, + Base: manifest.Base, + SnapName: manifest.Name, + SnapVersion: manifest.Version, + } + + // Set architecture if available + if len(manifest.Architectures) > 0 { + snapMetadata.Architecture = manifest.Architectures[0] + } + + // Parse primed-stage-packages entries + for _, pkgEntry := range manifest.PrimedStagePackages { + if !strings.Contains(pkgEntry, "=") { + continue // Skip malformed entries + } + + parts := strings.SplitN(pkgEntry, "=", 2) + if len(parts) != 2 { + continue + } + + name := strings.TrimSpace(parts[0]) + version := strings.TrimSpace(parts[1]) + + // Skip empty names or versions + if name == "" || version == "" { + continue + } + + // Handle architecture suffixes if present + currentMetadata := snapMetadata + if strings.Contains(name, ":") { + archParts := strings.SplitN(name, ":", 2) + name = archParts[0] + currentMetadata.Architecture = archParts[1] + } + + debPkg := newDebianPackageFromSnap( + name, + version, + currentMetadata, + reader.Location, + ) + + packages = append(packages, debPkg) + } + + return packages, nil, nil +} diff --git a/syft/pkg/cataloger/snap/test-fixtures/dpkg.yaml b/syft/pkg/cataloger/snap/test-fixtures/dpkg.yaml new file mode 100644 index 00000000000..497e7cada56 --- /dev/null +++ b/syft/pkg/cataloger/snap/test-fixtures/dpkg.yaml @@ -0,0 +1,7 @@ +package-repositories: +- type: apt + ppa: ucdev/ubuntu/base-ppa +packages: +- adduser=3.118ubuntu2 +- apparmor=2.13.3-7ubuntu5.3 +- gcc-10-base:amd64=10.5.0-1ubuntu1~20.04 \ No newline at end of file diff --git a/syft/pkg/cataloger/snap/test-fixtures/glob-paths/base/usr/share/snappy/dpkg.yaml b/syft/pkg/cataloger/snap/test-fixtures/glob-paths/base/usr/share/snappy/dpkg.yaml new file mode 100644 index 00000000000..14a2c130548 --- /dev/null +++ b/syft/pkg/cataloger/snap/test-fixtures/glob-paths/base/usr/share/snappy/dpkg.yaml @@ -0,0 +1,2 @@ +packages: +- test-package=1.0.0 \ No newline at end of file diff --git a/syft/pkg/cataloger/snap/test-fixtures/glob-paths/meta/meta/snap.yaml b/syft/pkg/cataloger/snap/test-fixtures/glob-paths/meta/meta/snap.yaml new file mode 100644 index 00000000000..a160d352222 --- /dev/null +++ b/syft/pkg/cataloger/snap/test-fixtures/glob-paths/meta/meta/snap.yaml @@ -0,0 +1,3 @@ +name: test-snap +version: 1.0 +type: app \ No newline at end of file diff --git a/syft/pkg/cataloger/snap/test-fixtures/glob-paths/system/snap/manifest.yaml b/syft/pkg/cataloger/snap/test-fixtures/glob-paths/system/snap/manifest.yaml new file mode 100644 index 00000000000..8d7f87e7b00 --- /dev/null +++ b/syft/pkg/cataloger/snap/test-fixtures/glob-paths/system/snap/manifest.yaml @@ -0,0 +1,4 @@ +name: test-snap +version: 1.0 +primed-stage-packages: +- test-package=1.0.0 \ No newline at end of file diff --git a/syft/pkg/cataloger/snap/test-fixtures/manifest.yaml b/syft/pkg/cataloger/snap/test-fixtures/manifest.yaml new file mode 100644 index 00000000000..fbe8c932c3a --- /dev/null +++ b/syft/pkg/cataloger/snap/test-fixtures/manifest.yaml @@ -0,0 +1,17 @@ +snapcraft-version: 8.2.1.post5+git07b4ee15 +snapcraft-started-at: '2024-04-29T06:47:56.067540Z' +snapcraft-os-release-id: ubuntu +snapcraft-os-release-version-id: '24.04' +name: pc +version: 24-0.1 +summary: PC gadget for generic devices +description: | + This gadget enables generic pc devices to work with Ubuntu Core +base: core24 +grade: stable +confinement: strict +architectures: +- amd64 +primed-stage-packages: +- grub-efi-amd64-signed=1.202+2.12-1ubuntu7 +- shim-signed=1.56+15.7-0ubuntu1 \ No newline at end of file diff --git a/syft/pkg/cataloger/snap/test-fixtures/real-dpkg.yaml b/syft/pkg/cataloger/snap/test-fixtures/real-dpkg.yaml new file mode 100644 index 00000000000..ab95331bbc9 --- /dev/null +++ b/syft/pkg/cataloger/snap/test-fixtures/real-dpkg.yaml @@ -0,0 +1,14 @@ +package-repositories: +- type: apt + ppa: ucdev/ubuntu/base-ppa +packages: +- adduser=3.118ubuntu2 +- apparmor=2.13.3-7ubuntu5.3 +- apt=2.0.10 +- bash=5.0-6ubuntu1.2 +- coreutils=8.30-3ubuntu2 +- dpkg=1.19.7ubuntu3.2 +- gcc-10-base:amd64=10.5.0-1ubuntu1~20.04 +- libc6:amd64=2.31-0ubuntu9.16 +- systemd=245.4-4ubuntu3.23 +- ubuntu-keyring=2020.02.11.4 \ No newline at end of file diff --git a/syft/pkg/cataloger/snap/test-fixtures/snap.yaml b/syft/pkg/cataloger/snap/test-fixtures/snap.yaml new file mode 100644 index 00000000000..b377efce4e6 --- /dev/null +++ b/syft/pkg/cataloger/snap/test-fixtures/snap.yaml @@ -0,0 +1,7 @@ +name: test-snap +version: 1.0.0 +summary: A test snap +description: This is a test snap for testing purposes +base: core20 +type: app +architecture: amd64 \ No newline at end of file diff --git a/syft/pkg/cataloger/swift/parse_podfile_lock.go b/syft/pkg/cataloger/swift/parse_podfile_lock.go index 10730af67fd..86ab560d269 100644 --- a/syft/pkg/cataloger/swift/parse_podfile_lock.go +++ b/syft/pkg/cataloger/swift/parse_podfile_lock.go @@ -6,7 +6,7 @@ import ( "io" "strings" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" "github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/syft/artifact" diff --git a/syft/pkg/cocoapods.go b/syft/pkg/cocoapods.go index 58ce99c5cc7..6789e981fdb 100644 --- a/syft/pkg/cocoapods.go +++ b/syft/pkg/cocoapods.go @@ -2,5 +2,6 @@ package pkg // CocoaPodfileLockEntry represents a single entry from the "Pods" section of a Podfile.lock file. type CocoaPodfileLockEntry struct { + // Checksum is the SHA-1 hash of the podspec file for integrity verification (generated via `pod ipc spec ... | openssl sha1`), ensuring all team members use the same pod specification version Checksum string `mapstructure:"checksum" json:"checksum"` } diff --git a/syft/pkg/conan.go b/syft/pkg/conan.go index 87cdb9c9d52..a1be8f6fdcf 100644 --- a/syft/pkg/conan.go +++ b/syft/pkg/conan.go @@ -2,35 +2,69 @@ package pkg // ConanV1LockEntry represents a single "node" entry from a conan.lock V1 file. type ConanV1LockEntry struct { - Ref string `json:"ref"` - PackageID string `json:"package_id,omitempty"` - Prev string `json:"prev,omitempty"` - Requires []string `json:"requires,omitempty"` - BuildRequires []string `json:"build_requires,omitempty"` - PythonRequires []string `json:"py_requires,omitempty"` - Options KeyValues `json:"options,omitempty"` - Path string `json:"path,omitempty"` - Context string `json:"context,omitempty"` + // Ref is the package reference string in format name/version@user/channel + Ref string `json:"ref"` + + // PackageID is a unique package variant identifier computed from settings/options (static hash in Conan 1.x, can have collisions with complex dependency graphs) + PackageID string `json:"package_id,omitempty"` + + // Prev is the previous lock entry reference for versioning + Prev string `json:"prev,omitempty"` + + // Requires are the runtime package dependencies + Requires []string `json:"requires,omitempty"` + + // BuildRequires are the build-time dependencies (e.g. cmake, compilers) + BuildRequires []string `json:"build_requires,omitempty"` + + // PythonRequires are the Python dependencies needed for Conan recipes + PythonRequires []string `json:"py_requires,omitempty"` + + // Options are package configuration options as key-value pairs (e.g. shared=True, fPIC=True) + Options KeyValues `json:"options,omitempty"` + + // Path is the filesystem path to the package in Conan cache + Path string `json:"path,omitempty"` + + // Context is the build context information + Context string `json:"context,omitempty"` } // ConanV2LockEntry represents a single "node" entry from a conan.lock V2 file. type ConanV2LockEntry struct { - Ref string `json:"ref"` - PackageID string `json:"packageID,omitempty"` - Username string `json:"username,omitempty"` - Channel string `json:"channel,omitempty"` - RecipeRevision string `json:"recipeRevision,omitempty"` + // Ref is the package reference string in format name/version@user/channel + Ref string `json:"ref"` + + // PackageID is a unique package variant identifier (dynamic in Conan 2.0, more accurate than V1) + PackageID string `json:"packageID,omitempty"` + + // Username is the Conan user/organization name + Username string `json:"username,omitempty"` + + // Channel is the Conan channel name indicating stability/purpose (e.g. stable, testing, experimental) + Channel string `json:"channel,omitempty"` + + // RecipeRevision is a git-like revision hash (RREV) of the recipe + RecipeRevision string `json:"recipeRevision,omitempty"` + + // PackageRevision is a git-like revision hash of the built binary package PackageRevision string `json:"packageRevision,omitempty"` - TimeStamp string `json:"timestamp,omitempty"` + + // TimeStamp is when this package was built/locked + TimeStamp string `json:"timestamp,omitempty"` } // ConanfileEntry represents a single "Requires" entry from a conanfile.txt. type ConanfileEntry struct { + // Ref is the package reference string in format name/version@user/channel Ref string `mapstructure:"ref" json:"ref"` } // ConaninfoEntry represents a single "full_requires" entry from a conaninfo.txt. type ConaninfoEntry struct { - Ref string `json:"ref"` + // Ref is the package reference string in format name/version@user/channel + Ref string `json:"ref"` + + // PackageID is a unique package variant identifier PackageID string `json:"package_id,omitempty"` } diff --git a/syft/pkg/conda.go b/syft/pkg/conda.go new file mode 100644 index 00000000000..aacd3e25149 --- /dev/null +++ b/syft/pkg/conda.go @@ -0,0 +1,121 @@ +package pkg + +import ( + "sort" + + "github.com/scylladb/go-set/strset" +) + +// CondaPathData represents metadata for a single file within a Conda package from the paths.json file. +type CondaPathData struct { + // Path is the file path relative to the Conda environment root. + Path string `json:"_path"` + + // PathType indicates the link type for the file (e.g., "hardlink", "softlink", "directory"). + PathType string `json:"path_type"` + + // SHA256 is the SHA-256 hash of the file contents. + SHA256 string `json:"sha256"` + + // SHA256InPrefix is the SHA-256 hash of the file after prefix replacement during installation. + SHA256InPrefix string `json:"sha256_in_prefix"` + + // SizeInBytes is the file size in bytes. + SizeInBytes int64 `json:"size_in_bytes"` +} + +// CondaPathsData represents the paths.json file structure from a Conda package containing file metadata. +type CondaPathsData struct { + // PathsVersion is the schema version of the paths data format. + PathsVersion int `json:"paths_version"` + + // Paths is the list of file metadata entries for all files in the package. + Paths []CondaPathData `json:"paths"` +} + +// CondaLink represents link metadata from a Conda package's link.json file describing package installation source. +type CondaLink struct { + // Source is the original path where the package was extracted from cache. + Source string `json:"source"` + + // Type indicates the link type (1 for hard link, 2 for soft link, 3 for copy). + Type int `json:"type"` +} + +// CondaMetaPackage represents metadata for a Conda package extracted from the conda-meta/*.json files. +type CondaMetaPackage struct { + // Arch is the target CPU architecture for the package (e.g., "arm64", "x86_64"). + Arch string `json:"arch,omitempty"` + + // Name is the package name as found in the conda-meta JSON file. + Name string `json:"name"` + + // Version is the package version as found in the conda-meta JSON file. + Version string `json:"version"` + + // Build is the build string identifier (e.g., "h90dfc92_1014"). + Build string `json:"build"` + + // BuildNumber is the sequential build number for this version. + BuildNumber int `json:"build_number"` + + // Channel is the Conda channel URL where the package was retrieved from. + Channel string `json:"channel,omitempty"` + + // Subdir is the subdirectory within the channel (e.g., "osx-arm64", "linux-64"). + Subdir string `json:"subdir,omitempty"` + + // Noarch indicates if the package is platform-independent (e.g., "python", "generic"). + Noarch string `json:"noarch,omitempty"` + + // License is the package license identifier. + License string `json:"license,omitempty"` + + // LicenseFamily is the general license category (e.g., "MIT", "Apache", "GPL"). + LicenseFamily string `json:"license_family,omitempty"` + + // MD5 is the MD5 hash of the package archive. + MD5 string `json:"md5,omitempty"` + + // SHA256 is the SHA-256 hash of the package archive. + SHA256 string `json:"sha256,omitempty"` + + // Size is the package archive size in bytes. + Size int64 `json:"size,omitempty"` + + // Timestamp is the Unix timestamp when the package was built. + Timestamp int64 `json:"timestamp,omitempty"` + + // Filename is the original package archive filename (e.g., "zlib-1.2.11-h90dfc92_1014.tar.bz2"). + Filename string `json:"fn,omitempty"` + + // URL is the full download URL for the package archive. + URL string `json:"url,omitempty"` + + // ExtractedPackageDir is the local cache directory where the package was extracted. + ExtractedPackageDir string `json:"extracted_package_dir,omitempty"` + + // Depends is the list of runtime dependencies with version constraints. + Depends []string `json:"depends,omitempty"` + + // Files is the list of files installed by this package. + Files []string `json:"files,omitempty"` + + // PathsData contains detailed file metadata from the paths.json file. + PathsData *CondaPathsData `json:"paths_data,omitempty"` + + // Link contains installation source metadata from the link.json file. + Link *CondaLink `json:"link,omitempty"` +} + +func (m CondaMetaPackage) OwnedFiles() (result []string) { + s := strset.New() + for _, f := range m.Files { + if f != "" { + s.Add(f) + } + } + result = s.List() + sort.Strings(result) + return result +} diff --git a/syft/pkg/dart.go b/syft/pkg/dart.go index cff51c421c2..d15a23a351d 100644 --- a/syft/pkg/dart.go +++ b/syft/pkg/dart.go @@ -2,24 +2,48 @@ package pkg // DartPubspecLockEntry is a struct that represents a single entry found in the "packages" section in a Dart pubspec.lock file. type DartPubspecLockEntry struct { - Name string `mapstructure:"name" json:"name"` - Version string `mapstructure:"version" json:"version"` + // Name is the package name as found in the pubspec.lock file + Name string `mapstructure:"name" json:"name"` + + // Version is the package version as found in the pubspec.lock file + Version string `mapstructure:"version" json:"version"` + + // HostedURL is the URL of the package repository for hosted packages (typically pub.dev, but can be custom repository identified by hosted-url). When PUB_HOSTED_URL environment variable changes, lockfile tracks the source. HostedURL string `mapstructure:"hosted_url" json:"hosted_url,omitempty"` - VcsURL string `mapstructure:"vcs_url" json:"vcs_url,omitempty"` + + // VcsURL is the URL of the VCS repository for git/path dependencies (for packages fetched from version control systems like Git) + VcsURL string `mapstructure:"vcs_url" json:"vcs_url,omitempty"` } // DartPubspec is a struct that represents a package described in a pubspec.yaml file type DartPubspec struct { - Homepage string `mapstructure:"homepage" json:"homepage,omitempty"` - Repository string `mapstructure:"repository" json:"repository,omitempty"` - Documentation string `mapstructure:"documentation" json:"documentation,omitempty"` - PublishTo string `mapstructure:"publish_to" json:"publish_to,omitempty"` - Environment *DartPubspecEnvironment `mapstructure:"environment" json:"environment,omitempty"` - Platforms []string `mapstructure:"platforms" json:"platforms,omitempty"` - IgnoredAdvisories []string `mapstructure:"ignored_advisories" json:"ignored_advisories,omitempty"` + // Homepage is the package homepage URL + Homepage string `mapstructure:"homepage" json:"homepage,omitempty"` + + // Repository is the source code repository URL + Repository string `mapstructure:"repository" json:"repository,omitempty"` + + // Documentation is the documentation site URL + Documentation string `mapstructure:"documentation" json:"documentation,omitempty"` + + // PublishTo is the package repository to publish to, or "none" to prevent accidental publishing + PublishTo string `mapstructure:"publish_to" json:"publish_to,omitempty"` + + // Environment is SDK version constraints for Dart and Flutter + Environment *DartPubspecEnvironment `mapstructure:"environment" json:"environment,omitempty"` + + // Platforms are the supported platforms (Android, iOS, web, etc.) + Platforms []string `mapstructure:"platforms" json:"platforms,omitempty"` + + // IgnoredAdvisories are the security advisories to explicitly ignore for this package + IgnoredAdvisories []string `mapstructure:"ignored_advisories" json:"ignored_advisories,omitempty"` } +// DartPubspecEnvironment represents SDK version constraints from the environment section of pubspec.yaml. type DartPubspecEnvironment struct { - SDK string `mapstructure:"sdk" json:"sdk,omitempty"` + // SDK is the Dart SDK version constraint (e.g. ">=2.12.0 <3.0.0") + SDK string `mapstructure:"sdk" json:"sdk,omitempty"` + + // Flutter is the Flutter SDK version constraint if this is a Flutter package Flutter string `mapstructure:"flutter" json:"flutter,omitempty"` } diff --git a/syft/pkg/dotnet.go b/syft/pkg/dotnet.go index 47aca15d6a7..10e7851c894 100644 --- a/syft/pkg/dotnet.go +++ b/syft/pkg/dotnet.go @@ -2,30 +2,60 @@ package pkg // DotnetDepsEntry is a struct that represents a single entry found in the "libraries" section in a .NET [*.]deps.json file. type DotnetDepsEntry struct { - Name string `mapstructure:"name" json:"name"` - Version string `mapstructure:"version" json:"version"` - Path string `mapstructure:"path" json:"path"` - Sha512 string `mapstructure:"sha512" json:"sha512"` + // Name is the package name as found in the deps.json file + Name string `mapstructure:"name" json:"name"` + + // Version is the package version as found in the deps.json file + Version string `mapstructure:"version" json:"version"` + + // Path is the relative path to the package within the deps structure (e.g. "app.metrics/3.0.0") + Path string `mapstructure:"path" json:"path"` + + // Sha512 is the SHA-512 hash of the NuGet package content WITHOUT the signed content for verification (won't match hash from NuGet API or manual calculation of .nupkg file) + Sha512 string `mapstructure:"sha512" json:"sha512"` + + // HashPath is the relative path to the .nupkg.sha512 hash file (e.g. "app.metrics.3.0.0.nupkg.sha512") HashPath string `mapstructure:"hashPath" json:"hashPath"` + // Executables are the map of .NET Portable Executable files within this package with their version resources Executables map[string]DotnetPortableExecutableEntry `json:"executables,omitempty"` } // DotnetPackagesLockEntry is a struct that represents a single entry found in the "dependencies" section in a .NET packages.lock.json file. type DotnetPackagesLockEntry struct { - Name string `mapstructure:"name" json:"name"` - Version string `mapstructure:"version" json:"version"` + // Name is the package name as found in the packages.lock.json file + Name string `mapstructure:"name" json:"name"` + + // Version is the package version as found in the packages.lock.json file + Version string `mapstructure:"version" json:"version"` + + // ContentHash is the hash of the package content for verification ContentHash string `mapstructure:"contentHash" json:"contentHash"` - Type string `mapstructure:"type" json:"type"` + + // Type is the dependency type indicating how this dependency was added (Direct=explicit in project file, Transitive=pulled in by another package, Project=project reference) + Type string `mapstructure:"type" json:"type"` } // DotnetPortableExecutableEntry is a struct that represents a single entry found within "VersionResources" section of a .NET Portable Executable binary file. type DotnetPortableExecutableEntry struct { + // AssemblyVersion is the .NET assembly version number (strong-named version) AssemblyVersion string `json:"assemblyVersion"` - LegalCopyright string `json:"legalCopyright"` - Comments string `json:"comments,omitempty"` - InternalName string `json:"internalName,omitempty"` - CompanyName string `json:"companyName"` - ProductName string `json:"productName"` - ProductVersion string `json:"productVersion"` + + // LegalCopyright is the copyright notice string + LegalCopyright string `json:"legalCopyright"` + + // Comments are additional comments or description embedded in PE resources + Comments string `json:"comments,omitempty"` + + // InternalName is the internal name of the file + InternalName string `json:"internalName,omitempty"` + + // CompanyName is the company that produced the file + CompanyName string `json:"companyName"` + + // ProductName is the name of the product this file is part of + ProductName string `json:"productName"` + + // ProductVersion is the version of the product (may differ from AssemblyVersion) + ProductVersion string `json:"productVersion"` } diff --git a/syft/pkg/dpkg.go b/syft/pkg/dpkg.go index 7f6ef607636..818f8bccee4 100644 --- a/syft/pkg/dpkg.go +++ b/syft/pkg/dpkg.go @@ -12,6 +12,7 @@ const DpkgDBGlob = "**/var/lib/dpkg/{status,status.d/**}" var _ FileOwner = (*DpkgDBEntry)(nil) +// DpkgArchiveEntry represents package metadata extracted from a .deb archive file. type DpkgArchiveEntry DpkgDBEntry // DpkgDBEntry represents all captured data for a Debian package DB entry; available fields are described @@ -22,49 +23,53 @@ type DpkgArchiveEntry DpkgDBEntry // - https://www.debian.org/doc/debian-policy/ch-binary.html#s-virtual-pkg // - https://www.debian.org/doc/debian-policy/ch-relationships.html#s-virtual type DpkgDBEntry struct { - Package string `json:"package"` - Source string `json:"source" cyclonedx:"source"` - Version string `json:"version"` + // Package is the package name as found in the status file + Package string `json:"package"` + + // Source is the source package name this binary was built from (one source can produce multiple binary packages) + Source string `json:"source" cyclonedx:"source"` + + // Version is the binary package version as found in the status file + Version string `json:"version"` + + // SourceVersion is the source package version (may differ from binary version when binNMU rebuilds occur) SourceVersion string `json:"sourceVersion" cyclonedx:"sourceVersion"` - // Architecture can include the following sets of values depending on context and the control file used: - // - a unique single word identifying a Debian machine architecture as described in Architecture specification string (https://www.debian.org/doc/debian-policy/ch-customized-programs.html#s-arch-spec) . - // - an architecture wildcard identifying a set of Debian machine architectures, see Architecture wildcards (https://www.debian.org/doc/debian-policy/ch-customized-programs.html#s-arch-wildcard-spec). any matches all Debian machine architectures and is the most frequently used. - // - "all", which indicates an architecture-independent package. - // - "source", which indicates a source package. + // Architecture is the target architecture per Debian spec (specific arch like amd64/arm64, wildcard like any, architecture-independent "all", or "source" for source packages) Architecture string `json:"architecture"` - // Maintainer is the package maintainer’s name and email address. The name must come first, then the email - // address inside angle brackets <> (in RFC822 format). + // Maintainer is the package maintainer's name and email in RFC822 format (name must come first, then email in angle brackets) Maintainer string `json:"maintainer"` + // InstalledSize is the total size of installed files in kilobytes InstalledSize int `json:"installedSize" cyclonedx:"installedSize"` - // Description contains a description of the binary package, consisting of two parts, the synopsis or the short - // description, and the long description (in a multiline format). + // Description is a human-readable package description with synopsis (first line) and long description (multiline format) Description string `hash:"ignore" json:"-"` - // Provides is a virtual package that is provided by one or more packages. A virtual package is one which appears - // in the Provides control field of another package. The effect is as if the package(s) which provide a particular - // virtual package name had been listed by name everywhere the virtual package name appears. (See also Virtual packages) + // Provides are the virtual packages provided by this package (allows other packages to depend on capabilities. Can include versioned provides like "libdigest-md5-perl (= 2.55.01)") Provides []string `json:"provides,omitempty"` - // Depends This declares an absolute dependency. A package will not be configured unless all of the packages listed in - // its Depends field have been correctly configured (unless there is a circular dependency). + // Depends are the packages required for this package to function (will not be installed unless these requirements are met, creates strict ordering constraint) Depends []string `json:"depends,omitempty"` - // PreDepends is like Depends, except that it also forces dpkg to complete installation of the packages named - // before even starting the installation of the package which declares the pre-dependency. + // PreDepends are the packages that must be installed and configured BEFORE even starting installation of this package (stronger than Depends, discouraged unless absolutely necessary as it adds strict constraints for apt) PreDepends []string `json:"preDepends,omitempty"` + // Files are the files installed by this package Files []DpkgFileRecord `json:"files"` } // DpkgFileRecord represents a single file attributed to a debian package. type DpkgFileRecord struct { - Path string `json:"path"` - Digest *file.Digest `json:"digest,omitempty"` - IsConfigFile bool `json:"isConfigFile"` + // Path is the file path relative to the filesystem root + Path string `json:"path"` + + // Digest is the file content hash (typically MD5 for dpkg compatibility with legacy systems) + Digest *file.Digest `json:"digest,omitempty"` + + // IsConfigFile is whether this file is marked as a configuration file (dpkg will preserve user modifications during upgrades) + IsConfigFile bool `json:"isConfigFile"` } func (m DpkgDBEntry) OwnedFiles() (result []string) { diff --git a/syft/pkg/elixir.go b/syft/pkg/elixir.go index ac556cd87ff..b13d04d1fb5 100644 --- a/syft/pkg/elixir.go +++ b/syft/pkg/elixir.go @@ -2,8 +2,15 @@ package pkg // ElixirMixLockEntry is a struct that represents a single entry in a mix.lock file type ElixirMixLockEntry struct { - Name string `mapstructure:"name" json:"name"` - Version string `mapstructure:"version" json:"version"` - PkgHash string `mapstructure:"pkgHash" json:"pkgHash"` + // Name is the package name as found in the mix.lock file + Name string `mapstructure:"name" json:"name"` + + // Version is the package version as found in the mix.lock file + Version string `mapstructure:"version" json:"version"` + + // PkgHash is the outer checksum (SHA-256) of the entire Hex package tarball for integrity verification (preferred method, replaces deprecated inner checksum) + PkgHash string `mapstructure:"pkgHash" json:"pkgHash"` + + // PkgHashExt is the extended package hash format (inner checksum is deprecated - SHA-256 of concatenated file contents excluding CHECKSUM file, now replaced by outer checksum) PkgHashExt string `mapstructure:"pkgHashExt" json:"pkgHashExt"` } diff --git a/syft/pkg/erlang.go b/syft/pkg/erlang.go index d74ff680ec8..eb1987a9bd5 100644 --- a/syft/pkg/erlang.go +++ b/syft/pkg/erlang.go @@ -2,8 +2,15 @@ package pkg // ErlangRebarLockEntry represents a single package entry from the "deps" section within an Erlang rebar.lock file. type ErlangRebarLockEntry struct { - Name string `mapstructure:"name" json:"name"` - Version string `mapstructure:"version" json:"version"` - PkgHash string `mapstructure:"pkgHash" json:"pkgHash"` + // Name is the package name as found in the rebar.lock file + Name string `mapstructure:"name" json:"name"` + + // Version is the package version as found in the rebar.lock file + Version string `mapstructure:"version" json:"version"` + + // PkgHash is the outer checksum (SHA-256) of the entire Hex package tarball for integrity verification (preferred method over deprecated inner checksum) + PkgHash string `mapstructure:"pkgHash" json:"pkgHash"` + + // PkgHashExt is the extended package hash format (inner checksum deprecated - was SHA-256 of concatenated file contents) PkgHashExt string `mapstructure:"pkgHashExt" json:"pkgHashExt"` } diff --git a/syft/pkg/github.go b/syft/pkg/github.go index 8ffabea3bd8..1f5c9876b4e 100644 --- a/syft/pkg/github.go +++ b/syft/pkg/github.go @@ -1,6 +1,10 @@ package pkg +// GitHubActionsUseStatement represents a single 'uses' statement in a GitHub Actions workflow file referencing an action or reusable workflow. type GitHubActionsUseStatement struct { - Value string `json:"value"` + // Value is the action reference (e.g. "actions/checkout@v3") + Value string `json:"value"` + + // Comment is the inline comment associated with this uses statement Comment string `json:"comment,omitempty"` } diff --git a/syft/pkg/golang.go b/syft/pkg/golang.go index 4e0269c4491..9656f83b14c 100644 --- a/syft/pkg/golang.go +++ b/syft/pkg/golang.go @@ -2,16 +2,48 @@ package pkg // GolangBinaryBuildinfoEntry represents all captured data for a Golang binary type GolangBinaryBuildinfoEntry struct { - BuildSettings KeyValues `json:"goBuildSettings,omitempty" cyclonedx:"goBuildSettings"` - GoCompiledVersion string `json:"goCompiledVersion" cyclonedx:"goCompiledVersion"` - Architecture string `json:"architecture" cyclonedx:"architecture"` - H1Digest string `json:"h1Digest,omitempty" cyclonedx:"h1Digest"` - MainModule string `json:"mainModule,omitempty" cyclonedx:"mainModule"` - GoCryptoSettings []string `json:"goCryptoSettings,omitempty" cyclonedx:"goCryptoSettings"` - GoExperiments []string `json:"goExperiments,omitempty" cyclonedx:"goExperiments"` + // BuildSettings contains the Go build settings and flags used to compile the binary (e.g., GOARCH, GOOS, CGO_ENABLED). + BuildSettings KeyValues `json:"goBuildSettings,omitempty" cyclonedx:"goBuildSettings"` + + // GoCompiledVersion is the version of Go used to compile the binary. + GoCompiledVersion string `json:"goCompiledVersion" cyclonedx:"goCompiledVersion"` + + // Architecture is the target CPU architecture for the binary (extracted from GOARCH build setting). + Architecture string `json:"architecture" cyclonedx:"architecture"` + + // H1Digest is the Go module hash in h1: format for the main module from go.sum. + H1Digest string `json:"h1Digest,omitempty" cyclonedx:"h1Digest"` + + // MainModule is the main module path for the binary (e.g., "github.com/anchore/syft"). + MainModule string `json:"mainModule,omitempty" cyclonedx:"mainModule"` + + // GoCryptoSettings contains FIPS and cryptographic configuration settings if present. + GoCryptoSettings []string `json:"goCryptoSettings,omitempty" cyclonedx:"goCryptoSettings"` + + // GoExperiments lists experimental Go features enabled during compilation (e.g., "arenas", "cgocheck2"). + GoExperiments []string `json:"goExperiments,omitempty" cyclonedx:"goExperiments"` } // GolangModuleEntry represents all captured data for a Golang source scan with go.mod/go.sum type GolangModuleEntry struct { + // H1Digest is the Go module hash in h1: format from go.sum for verifying module contents. H1Digest string `json:"h1Digest,omitempty" cyclonedx:"h1Digest"` } + +// GolangSourceEntry represents all captured data for a Golang package found through source analysis +type GolangSourceEntry struct { + // H1Digest is the Go module hash in h1: format from go.sum for verifying module contents. + H1Digest string `json:"h1Digest,omitempty" cyclonedx:"h1Digest"` + + // OperatingSystem is the target OS for build constraints (e.g., "linux", "darwin", "windows"). + OperatingSystem string `json:"os,omitempty" cyclonedx:"os"` + + // Architecture is the target CPU architecture for build constraints (e.g., "amd64", "arm64"). + Architecture string `json:"architecture,omitempty" cyclonedx:"architecture"` + + // BuildTags are the build tags used to conditionally compile code (e.g., "integration,debug"). + BuildTags string `json:"buildTags,omitempty" cyclonedx:"buildTags"` + + // CgoEnabled indicates whether CGO was enabled for this package. + CgoEnabled bool `json:"cgoEnabled" cyclonedx:"cgoEnabled"` +} diff --git a/syft/pkg/hackage.go b/syft/pkg/hackage.go index 50e7d7eb6d2..3e1a2ed1bd6 100644 --- a/syft/pkg/hackage.go +++ b/syft/pkg/hackage.go @@ -2,11 +2,15 @@ package pkg // HackageStackYamlLockEntry represents a single entry from the "packages" section of a stack.yaml.lock file. type HackageStackYamlLockEntry struct { - PkgHash string `mapstructure:"pkgHash" json:"pkgHash,omitempty"` + // PkgHash is the package content hash for verification + PkgHash string `mapstructure:"pkgHash" json:"pkgHash,omitempty"` + + // SnapshotURL is the URL to the Stack snapshot this package came from SnapshotURL string `mapstructure:"snapshotURL" json:"snapshotURL,omitempty"` } // HackageStackYamlEntry represents a single entry from the "extra-deps" section of a stack.yaml file. type HackageStackYamlEntry struct { + // PkgHash is the package content hash for verification PkgHash string `mapstructure:"pkgHash" json:"pkgHash,omitempty"` } diff --git a/syft/pkg/homebrew.go b/syft/pkg/homebrew.go index 8abc567eefc..574e0d871a3 100644 --- a/syft/pkg/homebrew.go +++ b/syft/pkg/homebrew.go @@ -1,7 +1,13 @@ package pkg +// HomebrewFormula represents metadata about a Homebrew formula package extracted from formula JSON files. type HomebrewFormula struct { - Tap string `json:"tap,omitempty"` - Homepage string `json:"homepage,omitempty"` + // Tap is Homebrew tap this formula belongs to (e.g. "homebrew/core") + Tap string `json:"tap,omitempty"` + + // Homepage is the upstream project homepage URL + Homepage string `json:"homepage,omitempty"` + + // Description is a human-readable formula description Description string `json:"description,omitempty"` } diff --git a/syft/pkg/java.go b/syft/pkg/java.go index 3bba12d19bb..dc8bc06c107 100644 --- a/syft/pkg/java.go +++ b/syft/pkg/java.go @@ -18,15 +18,20 @@ var jenkinsPluginPomPropertiesGroupIDs = []string{ "com.cloudbees.jenkins.plugins", } +// JavaVMInstallation represents a Java Virtual Machine installation discovered on the system with its release information and file list. type JavaVMInstallation struct { + // Release is JVM release information and version details Release JavaVMRelease `json:"release"` - Files []string `json:"files"` + + // Files are the list of files that are part of this JVM installation + Files []string `json:"files"` } func (m JavaVMInstallation) OwnedFiles() []string { return m.Files } +// JavaVMRelease represents JVM version and build information extracted from the release file in a Java installation. type JavaVMRelease struct { // Implementor is extracted with the `java.vendor` JVM property Implementor string `mapstructure:"IMPLEMENTOR,omitempty" json:"implementor,omitempty"` @@ -94,42 +99,86 @@ type JavaVMRelease struct { // JavaArchive encapsulates all Java ecosystem metadata for a package as well as an (optional) parent relationship. type JavaArchive struct { - VirtualPath string `json:"virtualPath" cyclonedx:"virtualPath"` // we need to include the virtual path in cyclonedx documents to prevent deduplication of jars within jars - Manifest *JavaManifest `mapstructure:"Manifest" json:"manifest,omitempty"` - PomProperties *JavaPomProperties `mapstructure:"PomProperties" json:"pomProperties,omitempty" cyclonedx:"-"` - PomProject *JavaPomProject `mapstructure:"PomProject" json:"pomProject,omitempty"` - ArchiveDigests []file.Digest `hash:"ignore" json:"digest,omitempty"` - Parent *Package `hash:"ignore" json:"-"` // note: the parent cannot be included in the minimal definition of uniqueness since this field is not reproducible in an encode-decode cycle (is lossy). + // VirtualPath is path within the archive hierarchy, where nested entries are delimited with ':' (for nested JARs) + VirtualPath string `json:"virtualPath" cyclonedx:"virtualPath"` + + // Manifest is parsed META-INF/MANIFEST.MF contents + Manifest *JavaManifest `mapstructure:"Manifest" json:"manifest,omitempty"` + + // PomProperties is parsed pom.properties file contents + PomProperties *JavaPomProperties `mapstructure:"PomProperties" json:"pomProperties,omitempty" cyclonedx:"-"` + + // PomProject is parsed pom.xml file contents + PomProject *JavaPomProject `mapstructure:"PomProject" json:"pomProject,omitempty"` + + // ArchiveDigests is cryptographic hashes of the archive file + ArchiveDigests []file.Digest `hash:"ignore" json:"digest,omitempty"` + + // Parent is reference to parent package (for nested archives) + Parent *Package `hash:"ignore" json:"-"` } // JavaPomProperties represents the fields of interest extracted from a Java archive's pom.properties file. type JavaPomProperties struct { - Path string `mapstructure:"path" json:"path"` - Name string `mapstructure:"name" json:"name"` - GroupID string `mapstructure:"groupId" json:"groupId" cyclonedx:"groupID"` - ArtifactID string `mapstructure:"artifactId" json:"artifactId" cyclonedx:"artifactID"` - Version string `mapstructure:"version" json:"version"` - Scope string `mapstructure:"scope" json:"scope,omitempty"` - Extra map[string]string `mapstructure:",remain" json:"extraFields,omitempty"` + // Path is path to the pom.properties file within the archive + Path string `mapstructure:"path" json:"path"` + + // Name is the project name + Name string `mapstructure:"name" json:"name"` + + // GroupID is Maven group identifier uniquely identifying the project across all projects (follows reversed domain name convention like com.company.project) + GroupID string `mapstructure:"groupId" json:"groupId" cyclonedx:"groupID"` + + // ArtifactID is Maven artifact identifier, the name of the jar/artifact (unique within the groupId scope) + ArtifactID string `mapstructure:"artifactId" json:"artifactId" cyclonedx:"artifactID"` + + // Version is artifact version + Version string `mapstructure:"version" json:"version"` + + // Scope is dependency scope determining when dependency is available (compile=default all phases, test=test compilation/execution only, runtime=runtime and test not compile, provided=expected from JDK or container) + Scope string `mapstructure:"scope" json:"scope,omitempty"` + + // Extra is additional custom properties not in standard Maven coordinates + Extra map[string]string `mapstructure:",remain" json:"extraFields,omitempty"` } // JavaPomProject represents fields of interest extracted from a Java archive's pom.xml file. See https://maven.apache.org/ref/3.6.3/maven-model/maven.html for more details. type JavaPomProject struct { - Path string `json:"path"` - Parent *JavaPomParent `json:"parent,omitempty"` - GroupID string `json:"groupId"` - ArtifactID string `json:"artifactId"` - Version string `json:"version"` - Name string `json:"name"` - Description string `json:"description,omitempty"` - URL string `json:"url,omitempty"` + // Path is path to the pom.xml file within the archive + Path string `json:"path"` + + // Parent is the parent POM reference for inheritance (child POMs inherit configuration from parent) + Parent *JavaPomParent `json:"parent,omitempty"` + + // GroupID is Maven group identifier (reversed domain name like org.apache.maven) + GroupID string `json:"groupId"` + + // ArtifactID is Maven artifact identifier (project name) + ArtifactID string `json:"artifactId"` + + // Version is project version (together with groupId and artifactId forms Maven coordinates groupId:artifactId:version) + Version string `json:"version"` + + // Name is a human-readable project name (displayed in Maven-generated documentation) + Name string `json:"name"` + + // Description is detailed project description + Description string `json:"description,omitempty"` + + // URL is the project URL (typically project website or repository) + URL string `json:"url,omitempty"` } // JavaPomParent contains the fields within the tag in a pom.xml file type JavaPomParent struct { - GroupID string `json:"groupId"` + // GroupID is the parent Maven group identifier + GroupID string `json:"groupId"` + + // ArtifactID is the parent Maven artifact identifier ArtifactID string `json:"artifactId"` - Version string `json:"version"` + + // Version is the parent version (child inherits configuration from this specific version of parent POM) + Version string `json:"version"` } // PkgTypeIndicated returns the package Type indicated by the data contained in the JavaPomProperties. @@ -143,7 +192,10 @@ func (p JavaPomProperties) PkgTypeIndicated() Type { // JavaManifest represents the fields of interest extracted from a Java archive's META-INF/MANIFEST.MF file. type JavaManifest struct { - Main KeyValues `json:"main,omitempty"` + // Main is main manifest attributes as key-value pairs + Main KeyValues `json:"main,omitempty"` + + // Sections are the named sections from the manifest (e.g. per-entry attributes) Sections []KeyValues `json:"sections,omitempty"` } diff --git a/syft/pkg/key_value.go b/syft/pkg/key_value.go index 52337be75b9..dd6f6759cb4 100644 --- a/syft/pkg/key_value.go +++ b/syft/pkg/key_value.go @@ -6,11 +6,16 @@ import ( "sort" ) +// KeyValue represents a single key-value pair. type KeyValue struct { - Key string `json:"key"` + // Key is the key name + Key string `json:"key"` + + // Value is the value associated with the key Value string `json:"value"` } +// KeyValues represents an ordered collection of key-value pairs that preserves insertion order. type KeyValues []KeyValue func (k KeyValues) Get(key string) (string, bool) { diff --git a/syft/pkg/license.go b/syft/pkg/license.go index 24a2a687531..2f863dc4e80 100644 --- a/syft/pkg/license.go +++ b/syft/pkg/license.go @@ -14,6 +14,7 @@ import ( "github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/internal/log" + "github.com/anchore/syft/internal/spdxlicense" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/license" @@ -21,28 +22,38 @@ import ( var _ sort.Interface = (*Licenses)(nil) -// License represents an SPDX Expression or license value extracted from a package's metadata -// We want to ignore URLs and Location since we merge these fields across equal licenses. -// A License is a unique combination of value, expression and type, where -// its sources are always considered merged and additions to the evidence -// of where it was found and how it was sourced. -// This is different from how we treat a package since we consider package paths -// in order to distinguish if packages should be kept separate -// this is different for licenses since we're only looking for evidence -// of where a license was declared/concluded for a given package. -// If a license is given as it's full text in the metadata rather than it's value or SPDX expression. -// The Contents field is used to represent this data. -// A Concluded License type is the license the SBOM creator believes governs the package (human crafted or altered SBOM). -// The Declared License is what the authors of a project believe govern the package. This is the default type syft declares. +// License represents an SPDX Expression or license value extracted from a package's metadata. +// A License is a unique combination of value, expression and type, where its sources are always +// considered merged and additions to the evidence of where it was found and how it was sourced. +// This is different from how we treat a package since we consider package paths in order to +// distinguish if packages should be kept separate. This is different for licenses since we're +// only looking for evidence of where a license was declared/concluded for a given package. type License struct { + // SPDXExpression is parsed SPDX license expression (e.g. "MIT OR Apache-2.0") SPDXExpression string - Value string - Type license.Type - Contents string `hash:"ignore"` // we want to ignore the contents here so we can drop contents in the post-processing step - URLs []string `hash:"ignore"` // TODO: there is such thing as a url-only license, but we aren't hashing on this, which means overwriting could occur in the license set - Locations file.LocationSet `hash:"ignore"` + + // Value is original raw license string as found in metadata (e.g. "mit or apache-2") + Value string + + // Type is classification of how this license was discovered (declared, concluded, etc.). + // A Concluded License type is the license the SBOM creator believes governs the package (human crafted or altered SBOM). + // The Declared License is what the authors of a project believe govern the package (this is the default type syft uses). + Type license.Type + + // Contents is full license text if available. If a license is given as its full text in the + // metadata rather than its value or SPDX expression, this field is used to represent that data. + Contents string `hash:"ignore"` + + // URLs are the list of URLs where license information was found. These are ignored for uniqueness + // since we merge these fields across equal licenses. + URLs []string `hash:"ignore"` + + // Locations are the file locations where this license was discovered. These are ignored for uniqueness + // since we merge these fields across equal licenses. + Locations file.LocationSet `hash:"ignore"` } +// Licenses is a sortable collection of License objects implementing sort.Interface. type Licenses []License func (l Licenses) Len() int { @@ -132,6 +143,13 @@ func stripUnwantedCharacters(rawURL string) (string, error) { } func NewLicenseFromFieldsWithContext(ctx context.Context, value, url string, location *file.Location) License { + // If value is empty but URL is provided, try to enrich from SPDX database + if value == "" && url != "" { + if info, found := spdxlicense.LicenseByURL(url); found { + value = info.ID + } + } + lics := newLicenseBuilder().WithValues(value).WithURLs(url).WithOptionalLocation(location).Build(ctx).ToSlice() if len(lics) > 0 { return lics[0] @@ -182,12 +200,18 @@ func (s License) Merge(l License) (*License, error) { return &s, nil } +// licenseBuilder is an internal builder for constructing License objects with validation and normalization. type licenseBuilder struct { - values []string - contents []io.ReadCloser + // values are raw license strings or SPDX expressions to process. + values []string + // contents are readers for full license text content. + contents []io.ReadCloser + // locations are file locations where license information was discovered. locations []file.Location - urls []string - tp license.Type + // urls are web URLs where license information can be found. + urls []string + // tp is the license type classification (declared, concluded, etc.). + tp license.Type } func newLicenseBuilder() *licenseBuilder { @@ -294,11 +318,22 @@ func (b *licenseBuilder) Build(ctx context.Context) LicenseSet { if set.Empty() && len(b.urls) > 0 { // if we have no values or contents, but we do have URLs, let's make a license with the URLs - set.Add(License{ + // try to enrich the license by looking up the URL in the SPDX database + license := License{ Type: b.tp, URLs: b.urls, Locations: locations, - }) + } + + // attempt to fill in missing license information from the first URL + if len(b.urls) > 0 { + if info, found := spdxlicense.LicenseByURL(b.urls[0]); found { + license.Value = info.ID + license.SPDXExpression = info.ID + } + } + + set.Add(license) } return set diff --git a/syft/pkg/license_url_enrichment_test.go b/syft/pkg/license_url_enrichment_test.go new file mode 100644 index 00000000000..7837ad7b509 --- /dev/null +++ b/syft/pkg/license_url_enrichment_test.go @@ -0,0 +1,180 @@ +package pkg + +import ( + "context" + "testing" +) + +func TestNewLicenseFromFieldsWithContext_URLEnrichment(t *testing.T) { + tests := []struct { + name string + value string + url string + wantValue string + wantHasURL bool + }{ + { + name: "Empty value with MIT URL should enrich", + value: "", + url: "http://opensource.org/licenses/MIT", + wantValue: "MIT", + wantHasURL: true, + }, + { + name: "Empty value with Apache URL should enrich", + value: "", + url: "https://www.apache.org/licenses/LICENSE-2.0", + wantValue: "Apache-2.0", + wantHasURL: true, + }, + { + name: "Non-empty value should not be overridden", + value: "Custom-License", + url: "http://opensource.org/licenses/MIT", + wantValue: "Custom-License", + wantHasURL: true, + }, + { + name: "Unknown URL should not enrich", + value: "", + url: "https://example.com/unknown-license", + wantValue: "", + wantHasURL: true, + }, + { + name: "Empty value and empty URL", + value: "", + url: "", + wantValue: "", + wantHasURL: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + license := NewLicenseFromFieldsWithContext(ctx, tt.value, tt.url, nil) + + if license.Value != tt.wantValue { + t.Errorf("NewLicenseFromFieldsWithContext() Value = %v, want %v", license.Value, tt.wantValue) + } + + hasURL := len(license.URLs) > 0 + if hasURL != tt.wantHasURL { + t.Errorf("NewLicenseFromFieldsWithContext() has URL = %v, want %v", hasURL, tt.wantHasURL) + } + + if tt.wantHasURL && tt.url != "" && license.URLs[0] != tt.url { + t.Errorf("NewLicenseFromFieldsWithContext() URL = %v, want %v", license.URLs[0], tt.url) + } + }) + } +} + +func TestLicenseBuilder_URLOnlyEnrichment(t *testing.T) { + tests := []struct { + name string + urls []string + wantValue string + wantSPDX string + wantHasURL bool + }{ + { + name: "MIT URL only should enrich", + urls: []string{"http://opensource.org/licenses/MIT"}, + wantValue: "MIT", + wantSPDX: "MIT", + wantHasURL: true, + }, + { + name: "Apache URL only should enrich", + urls: []string{"https://www.apache.org/licenses/LICENSE-2.0"}, + wantValue: "Apache-2.0", + wantSPDX: "Apache-2.0", + wantHasURL: true, + }, + { + name: "Multiple URLs should use first", + urls: []string{"http://opensource.org/licenses/MIT", "https://example.com/other"}, + wantValue: "MIT", + wantSPDX: "MIT", + wantHasURL: true, + }, + { + name: "Unknown URL should not enrich", + urls: []string{"https://example.com/unknown-license"}, + wantValue: "", + wantSPDX: "", + wantHasURL: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + builder := newLicenseBuilder().WithURLs(tt.urls...) + licenses := builder.Build(ctx).ToSlice() + + if len(licenses) == 0 { + t.Fatal("Expected at least one license") + } + + license := licenses[0] + + if license.Value != tt.wantValue { + t.Errorf("License Value = %v, want %v", license.Value, tt.wantValue) + } + + if license.SPDXExpression != tt.wantSPDX { + t.Errorf("License SPDXExpression = %v, want %v", license.SPDXExpression, tt.wantSPDX) + } + + hasURL := len(license.URLs) > 0 + if hasURL != tt.wantHasURL { + t.Errorf("License has URL = %v, want %v", hasURL, tt.wantHasURL) + } + + if tt.wantHasURL && len(tt.urls) > 0 { + if len(license.URLs) != len(tt.urls) { + t.Errorf("License URL count = %v, want %v", len(license.URLs), len(tt.urls)) + } + if license.URLs[0] != tt.urls[0] { + t.Errorf("License first URL = %v, want %v", license.URLs[0], tt.urls[0]) + } + } + }) + } +} + +func TestNewLicenseFromURLsWithContext_URLEnrichment(t *testing.T) { + tests := []struct { + name string + value string + urls []string + wantValue string + }{ + { + name: "Empty value with MIT URL should enrich via builder", + value: "", + urls: []string{"http://opensource.org/licenses/MIT"}, + wantValue: "MIT", + }, + { + name: "Non-empty value should not be changed", + value: "Custom-License", + urls: []string{"http://opensource.org/licenses/MIT"}, + wantValue: "Custom-License", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + license := NewLicenseFromURLsWithContext(ctx, tt.value, tt.urls...) + + if license.Value != tt.wantValue { + t.Errorf("NewLicenseFromURLsWithContext() Value = %v, want %v", license.Value, tt.wantValue) + } + }) + } +} diff --git a/syft/pkg/linux_kernel.go b/syft/pkg/linux_kernel.go index e2aeb7cd038..15f30e1e2cc 100644 --- a/syft/pkg/linux_kernel.go +++ b/syft/pkg/linux_kernel.go @@ -2,33 +2,78 @@ package pkg // LinuxKernel represents all captured data for a Linux kernel type LinuxKernel struct { - Name string `mapstructure:"name" json:"name" cyclonedx:"name"` - Architecture string `mapstructure:"architecture" json:"architecture" cyclonedx:"architecture"` - Version string `mapstructure:"version" json:"version" cyclonedx:"version"` + // Name is kernel name (typically "Linux") + Name string `mapstructure:"name" json:"name" cyclonedx:"name"` + + // Architecture is the target CPU architecture + Architecture string `mapstructure:"architecture" json:"architecture" cyclonedx:"architecture"` + + // Version is kernel version string + Version string `mapstructure:"version" json:"version" cyclonedx:"version"` + + // ExtendedVersion is additional version information ExtendedVersion string `mapstructure:"extendedVersion" json:"extendedVersion,omitempty" cyclonedx:"extendedVersion"` - BuildTime string `mapstructure:"buildTime" json:"buildTime,omitempty" cyclonedx:"buildTime"` - Author string `mapstructure:"author" json:"author,omitempty" cyclonedx:"author"` - Format string `mapstructure:"format" json:"format,omitempty" cyclonedx:"format"` - RWRootFS bool `mapstructure:"rwRootFS" json:"rwRootFS,omitempty" cyclonedx:"rwRootFS"` - SwapDevice int `mapstructure:"swapDevice" json:"swapDevice,omitempty" cyclonedx:"swapDevice"` - RootDevice int `mapstructure:"rootDevice" json:"rootDevice,omitempty" cyclonedx:"rootDevice"` - VideoMode string `mapstructure:"videoMode" json:"videoMode,omitempty" cyclonedx:"videoMode"` + + // BuildTime is when the kernel was built + BuildTime string `mapstructure:"buildTime" json:"buildTime,omitempty" cyclonedx:"buildTime"` + + // Author is who built the kernel + Author string `mapstructure:"author" json:"author,omitempty" cyclonedx:"author"` + + // Format is kernel image format (e.g. bzImage, zImage) + Format string `mapstructure:"format" json:"format,omitempty" cyclonedx:"format"` + + // RWRootFS is whether root filesystem is mounted read-write + RWRootFS bool `mapstructure:"rwRootFS" json:"rwRootFS,omitempty" cyclonedx:"rwRootFS"` + + // SwapDevice is swap device number + SwapDevice int `mapstructure:"swapDevice" json:"swapDevice,omitempty" cyclonedx:"swapDevice"` + + // RootDevice is root device number + RootDevice int `mapstructure:"rootDevice" json:"rootDevice,omitempty" cyclonedx:"rootDevice"` + + // VideoMode is default video mode setting + VideoMode string `mapstructure:"videoMode" json:"videoMode,omitempty" cyclonedx:"videoMode"` } +// LinuxKernelModule represents a loadable kernel module (.ko file) with its metadata, parameters, and dependencies. type LinuxKernelModule struct { - Name string `mapstructure:"name" json:"name,omitempty" cyclonedx:"name"` - Version string `mapstructure:"version" json:"version,omitempty" cyclonedx:"version"` - SourceVersion string `mapstructure:"sourceVersion" json:"sourceVersion,omitempty" cyclonedx:"sourceVersion"` - Path string `mapstructure:"path" json:"path,omitempty" cyclonedx:"path"` - Description string `mapstructure:"description" json:"description,omitempty" cyclonedx:"description"` - Author string `mapstructure:"author" json:"author,omitempty" cyclonedx:"author"` - License string `mapstructure:"license" json:"license,omitempty" cyclonedx:"license"` - KernelVersion string `mapstructure:"kernelVersion" json:"kernelVersion,omitempty" cyclonedx:"kernelVersion"` - VersionMagic string `mapstructure:"versionMagic" json:"versionMagic,omitempty" cyclonedx:"versionMagic"` - Parameters map[string]LinuxKernelModuleParameter `mapstructure:"parameters" json:"parameters,omitempty" cyclonedx:"parameters"` + // Name is module name + Name string `mapstructure:"name" json:"name,omitempty" cyclonedx:"name"` + + // Version is module version string + Version string `mapstructure:"version" json:"version,omitempty" cyclonedx:"version"` + + // SourceVersion is the source code version identifier + SourceVersion string `mapstructure:"sourceVersion" json:"sourceVersion,omitempty" cyclonedx:"sourceVersion"` + + // Path is the filesystem path to the .ko kernel object file (absolute path) + Path string `mapstructure:"path" json:"path,omitempty" cyclonedx:"path"` + + // Description is a human-readable module description + Description string `mapstructure:"description" json:"description,omitempty" cyclonedx:"description"` + + // Author is module author name and email + Author string `mapstructure:"author" json:"author,omitempty" cyclonedx:"author"` + + // License is module license (e.g. GPL, BSD) which must be compatible with kernel + License string `mapstructure:"license" json:"license,omitempty" cyclonedx:"license"` + + // KernelVersion is kernel version this module was built for + KernelVersion string `mapstructure:"kernelVersion" json:"kernelVersion,omitempty" cyclonedx:"kernelVersion"` + + // VersionMagic is version magic string for compatibility checking (includes kernel version, SMP status, module loading capabilities like "3.17.4-302.fc21.x86_64 SMP mod_unload modversions"). Module will NOT load if vermagic doesn't match running kernel. + VersionMagic string `mapstructure:"versionMagic" json:"versionMagic,omitempty" cyclonedx:"versionMagic"` + + // Parameters are the module parameters that can be configured at load time (user-settable values like module options) + Parameters map[string]LinuxKernelModuleParameter `mapstructure:"parameters" json:"parameters,omitempty" cyclonedx:"parameters"` } +// LinuxKernelModuleParameter represents a configurable parameter for a kernel module with its type and description. type LinuxKernelModuleParameter struct { - Type string `mapstructure:"type" json:"type,omitempty" cyclonedx:"type"` + // Type is parameter data type (e.g. int, string, bool, array types) + Type string `mapstructure:"type" json:"type,omitempty" cyclonedx:"type"` + + // Description is a human-readable parameter description explaining what the parameter controls Description string `mapstructure:"description" json:"description,omitempty" cyclonedx:"description"` } diff --git a/syft/pkg/microsoft.go b/syft/pkg/microsoft.go index c80229f8cba..80c345c2891 100644 --- a/syft/pkg/microsoft.go +++ b/syft/pkg/microsoft.go @@ -6,6 +6,9 @@ package pkg // "Windows 10 Version 1703 for 32-bit Systems". // `Kb` is expected to be the actual KB number, for example "5001028" type MicrosoftKbPatch struct { + // ProductID is MSRC Product ID (e.g. "Windows 10 Version 1703 for 32-bit Systems") ProductID string `toml:"product_id" json:"product_id"` - Kb string `toml:"kb" json:"kb"` + + // Kb is Knowledge Base article number (e.g. "5001028") + Kb string `toml:"kb" json:"kb"` } diff --git a/syft/pkg/nix.go b/syft/pkg/nix.go index 61ee2717012..1160f9c13b2 100644 --- a/syft/pkg/nix.go +++ b/syft/pkg/nix.go @@ -6,43 +6,45 @@ import ( "github.com/scylladb/go-set/strset" ) +// NixStoreEntry represents a package in the Nix store (/nix/store) with its derivation information and metadata. type NixStoreEntry struct { - // Path is the store path for this output + // Path is full store path for this output (e.g. /nix/store/abc123...-package-1.0) Path string `mapstructure:"path" json:"path,omitempty"` - // Output allows for optionally specifying the specific nix package output this package represents (for packages that support multiple outputs). - // Note: the default output for a package is an empty string, so will not be present in the output. + // Output is the specific output name for multi-output packages (empty string for default "out" output, can be "bin", "dev", "doc", etc.) Output string `mapstructure:"output" json:"output,omitempty"` - // OutputHash is the prefix of the nix store basename path + // OutputHash is hash prefix of the store path basename (first part before the dash) OutputHash string `mapstructure:"outputHash" json:"outputHash"` - // Derivation is any information about the derivation file that was used to build this package + // Derivation is information about the .drv file that describes how this package was built Derivation NixDerivation `mapstructure:"derivation" json:"derivation,omitempty"` - // Files is a listing a files that are under the nix/store path for this package + // Files are the list of files under the nix/store path for this package Files []string `mapstructure:"files" json:"files,omitempty"` } +// NixDerivation represents a Nix .drv file that describes how to build a package including inputs, outputs, and build instructions. type NixDerivation struct { - // Path is the path to the derivation file + // Path is path to the .drv file in Nix store Path string `mapstructure:"path" json:"path,omitempty"` - // System is the nix system string that this derivation was built for + // System is target system string indicating where derivation can be built (e.g. "x86_64-linux", "aarch64-darwin"). Must match current system for local builds. System string `mapstructure:"system" json:"system,omitempty"` - // InputDerivations is a list of derivation paths that were used to build this package + // InputDerivations are the list of other derivations that were inputs to this build (dependencies) InputDerivations []NixDerivationReference `mapstructure:"inputDerivations" json:"inputDerivations,omitempty"` - // InputSources is a list of source paths that were used to build this package + // InputSources are the list of source file paths that were inputs to this build InputSources []string `mapstructure:"inputSources" json:"inputSources,omitempty"` } +// NixDerivationReference represents a reference to another derivation used as a build input or runtime dependency. type NixDerivationReference struct { - // Path is the path to the derivation file + // Path is path to the referenced .drv file Path string `mapstructure:"path" json:"path,omitempty"` - // Outputs is a list of output names that were used to build this package + // Outputs are which outputs of the referenced derivation were used (e.g. ["out"], ["bin", "dev"]) Outputs []string `mapstructure:"outputs" json:"outputs,omitempty"` } diff --git a/syft/pkg/npm.go b/syft/pkg/npm.go index c39539bd66b..a5068139c32 100644 --- a/syft/pkg/npm.go +++ b/syft/pkg/npm.go @@ -2,23 +2,42 @@ package pkg // NpmPackage represents the contents of a javascript package.json file. type NpmPackage struct { - Name string `mapstructure:"name" json:"name"` - Version string `mapstructure:"version" json:"version"` - Author string `mapstructure:"author" json:"author"` - Homepage string `mapstructure:"homepage" json:"homepage"` + // Name is the package name as found in package.json + Name string `mapstructure:"name" json:"name"` + + // Version is the package version as found in package.json + Version string `mapstructure:"version" json:"version"` + + // Author is package author name + Author string `mapstructure:"author" json:"author"` + + // Homepage is project homepage URL + Homepage string `mapstructure:"homepage" json:"homepage"` + + // Description is a human-readable package description Description string `mapstructure:"description" json:"description"` - URL string `mapstructure:"url" json:"url"` - Private bool `mapstructure:"private" json:"private"` + + // URL is repository or project URL + URL string `mapstructure:"url" json:"url"` + + // Private is whether this is a private package + Private bool `mapstructure:"private" json:"private"` } // NpmPackageLockEntry represents a single entry within the "packages" section of a package-lock.json file. type NpmPackageLockEntry struct { - Resolved string `mapstructure:"resolved" json:"resolved"` + // Resolved is URL where this package was downloaded from (registry source) + Resolved string `mapstructure:"resolved" json:"resolved"` + + // Integrity is Subresource Integrity hash for verification using standard SRI format (sha512-... or sha1-...). npm changed from SHA-1 to SHA-512 in newer versions. For registry sources this is the integrity from registry, for remote tarballs it's SHA-512 of the file. npm verifies tarball matches this hash before unpacking, throwing EINTEGRITY error if mismatch detected. Integrity string `mapstructure:"integrity" json:"integrity"` } // YarnLockEntry represents a single entry section of a yarn.lock file. type YarnLockEntry struct { - Resolved string `mapstructure:"resolved" json:"resolved"` + // Resolved is URL where this package was downloaded from + Resolved string `mapstructure:"resolved" json:"resolved"` + + // Integrity is Subresource Integrity hash for verification (SRI format) Integrity string `mapstructure:"integrity" json:"integrity"` } diff --git a/syft/pkg/ocaml.go b/syft/pkg/ocaml.go index 350d0433994..7003069a5a9 100644 --- a/syft/pkg/ocaml.go +++ b/syft/pkg/ocaml.go @@ -1,11 +1,25 @@ package pkg +// OpamPackage represents an OCaml package managed by the OPAM package manager with metadata from .opam files. type OpamPackage struct { - Name string `toml:"name" json:"name"` - Version string `toml:"version" json:"version"` - Licenses []string `mapstructure:"licenses" json:"licenses"` - URL string `mapstructure:"url" json:"url"` - Checksums []string `mapstructure:"checksums" json:"checksum"` - Homepage string `json:"homepage"` + // Name is the package name as found in the .opam file + Name string `toml:"name" json:"name"` + + // Version is the package version as found in the .opam file + Version string `toml:"version" json:"version"` + + // Licenses are the list of applicable licenses + Licenses []string `mapstructure:"licenses" json:"licenses"` + + // URL is download URL for the package source + URL string `mapstructure:"url" json:"url"` + + // Checksums are the list of checksums for verification + Checksums []string `mapstructure:"checksums" json:"checksum"` + + // Homepage is project homepage URL + Homepage string `json:"homepage"` + + // Dependencies are the list of required dependencies Dependencies []string `toml:"dependencies" json:"dependencies"` } diff --git a/syft/pkg/package.go b/syft/pkg/package.go index a9fc65317b3..546c91f5c9e 100644 --- a/syft/pkg/package.go +++ b/syft/pkg/package.go @@ -17,17 +17,38 @@ import ( // Package represents an application or library that has been bundled into a distributable format. // TODO: if we ignore FoundBy for ID generation should we merge the field to show it was found in two places? type Package struct { - id artifact.ID `hash:"ignore"` - Name string // the package name - Version string // the version of the package - FoundBy string `hash:"ignore" cyclonedx:"foundBy"` // the specific cataloger that discovered this package - Locations file.LocationSet // the locations that lead to the discovery of this package (note: this is not necessarily the locations that make up this package) - Licenses LicenseSet // licenses discovered with the package metadata - Language Language `hash:"ignore" cyclonedx:"language"` // the language ecosystem this package belongs to (e.g. JavaScript, Python, etc) - Type Type `cyclonedx:"type"` // the package type (e.g. Npm, Yarn, Python, Rpm, Deb, etc) - CPEs []cpe.CPE `hash:"ignore"` // all possible Common Platform Enumerators (note: this is NOT included in the definition of the ID since all fields on a CPE are derived from other fields) - PURL string `hash:"ignore"` // the Package URL (see https://github.com/package-url/purl-spec) - Metadata any // additional data found while parsing the package source + // id is a content-addressable identifier for this package, computed from most attribute values (applied recursively) + id artifact.ID `hash:"ignore"` + + // Name is the package name + Name string + + // Version is the package version + Version string + + // FoundBy is the specific cataloger that discovered this package + FoundBy string `hash:"ignore" cyclonedx:"foundBy"` + + // Locations are the locations that lead to the discovery of this package (note: not necessarily the locations that make up the package) + Locations file.LocationSet + + // Licenses are the licenses discovered from the package metadata + Licenses LicenseSet + + // Language is the language this package was written in (e.g. JavaScript, Python, etc) + Language Language `hash:"ignore" cyclonedx:"language"` + + // Type is the ecosystem the package belongs to (e.g. Npm, Yarn, Python, Rpm, Deb, etc) + Type Type `cyclonedx:"type"` + + // CPEs are all possible Common Platform Enumerators (note: NOT included in ID since derived from other fields) + CPEs []cpe.CPE `hash:"ignore"` + + // PURL is the Package URL (see https://github.com/package-url/purl-spec) + PURL string `hash:"ignore"` + + // Metadata is additional data found while parsing the package source + Metadata any } func (p *Package) OverrideID(id artifact.ID) { diff --git a/syft/pkg/php.go b/syft/pkg/php.go index 2759a229c95..1864ed9efa0 100644 --- a/syft/pkg/php.go +++ b/syft/pkg/php.go @@ -5,35 +5,82 @@ type PhpComposerInstalledEntry PhpComposerLockEntry // PhpComposerLockEntry represents a single package entry found from a composer.lock file. type PhpComposerLockEntry struct { - Name string `json:"name"` - Version string `json:"version"` - Source PhpComposerExternalReference `json:"source"` - Dist PhpComposerExternalReference `json:"dist"` - Require map[string]string `json:"require,omitempty"` - Provide map[string]string `json:"provide,omitempty"` - RequireDev map[string]string `json:"require-dev,omitempty"` - Suggest map[string]string `json:"suggest,omitempty"` - License []string `json:"license,omitempty"` - Type string `json:"type,omitempty"` - NotificationURL string `json:"notification-url,omitempty"` - Bin []string `json:"bin,omitempty"` - Authors []PhpComposerAuthors `json:"authors,omitempty"` - Description string `json:"description,omitempty"` - Homepage string `json:"homepage,omitempty"` - Keywords []string `json:"keywords,omitempty"` - Time string `json:"time,omitempty"` + // Name is package name in vendor/package format (e.g. symfony/console) + Name string `json:"name"` + + // Version is the package version + Version string `json:"version"` + + // Source is the source repository information for development (typically git repo, used when passing --prefer-source). Originates from source code repository. + Source PhpComposerExternalReference `json:"source"` + + // Dist is distribution archive information for production (typically zip/tar, default install method). Packaged version of released code. + Dist PhpComposerExternalReference `json:"dist"` + + // Require is runtime dependencies with version constraints (package will not install unless these requirements can be met) + Require map[string]string `json:"require,omitempty"` + + // Provide is virtual packages/functionality provided by this package (allows other packages to depend on capabilities) + Provide map[string]string `json:"provide,omitempty"` + + // RequireDev is development-only dependencies (not installed in production, only when developing this package or running tests) + RequireDev map[string]string `json:"require-dev,omitempty"` + + // Suggest is optional but recommended dependencies (suggestions for packages that would extend functionality) + Suggest map[string]string `json:"suggest,omitempty"` + + // License is the list of license identifiers (SPDX format) + License []string `json:"license,omitempty"` + + // Type is package type indicating purpose (library=reusable code, project=application, metapackage=aggregates dependencies, etc.) + Type string `json:"type,omitempty"` + + // NotificationURL is the URL to notify when package is installed (for tracking/statistics) + NotificationURL string `json:"notification-url,omitempty"` + + // Bin is the list of binary/executable files that should be added to PATH + Bin []string `json:"bin,omitempty"` + + // Authors are the list of package authors with name/email/homepage + Authors []PhpComposerAuthors `json:"authors,omitempty"` + + // Description is a human-readable package description + Description string `json:"description,omitempty"` + + // Homepage is project homepage URL + Homepage string `json:"homepage,omitempty"` + + // Keywords are the list of keywords for package discovery/search + Keywords []string `json:"keywords,omitempty"` + + // Time is timestamp when this package version was released + Time string `json:"time,omitempty"` } +// PhpComposerExternalReference represents source or distribution information for a PHP package, indicating where the package code is retrieved from. type PhpComposerExternalReference struct { - Type string `json:"type"` - URL string `json:"url"` + // Type is reference type (git for source VCS, zip/tar for dist archives) + Type string `json:"type"` + + // URL is the URL to the resource (git repository URL or archive download URL) + URL string `json:"url"` + + // Reference is git commit hash or version tag for source, or archive version for dist Reference string `json:"reference"` - Shasum string `json:"shasum,omitempty"` + + // Shasum is SHA hash of the archive file for integrity verification (dist only) + Shasum string `json:"shasum,omitempty"` } +// PhpComposerAuthors represents author information for a PHP Composer package from the authors field in composer.json. type PhpComposerAuthors struct { - Name string `json:"name"` - Email string `json:"email,omitempty"` + // Name is author's full name + Name string `json:"name"` + + // Email is author's email address + Email string `json:"email,omitempty"` + + // Homepage is author's personal or company website Homepage string `json:"homepage,omitempty"` } @@ -43,8 +90,15 @@ type PhpPeclEntry PhpPearEntry // PhpPearEntry represents a single package entry found within php pear metadata files. type PhpPearEntry struct { - Name string `json:"name"` - Channel string `json:"channel,omitempty"` - Version string `json:"version"` + // Name is the package name + Name string `json:"name"` + + // Channel is PEAR channel this package is from + Channel string `json:"channel,omitempty"` + + // Version is the package version + Version string `json:"version"` + + // License is the list of applicable licenses License []string `json:"license,omitempty"` } diff --git a/syft/pkg/portage.go b/syft/pkg/portage.go index 35a556a702a..eaf6c05e82e 100644 --- a/syft/pkg/portage.go +++ b/syft/pkg/portage.go @@ -12,14 +12,22 @@ var _ FileOwner = (*PortageEntry)(nil) // PortageEntry represents a single package entry in the portage DB flat-file store. type PortageEntry struct { - InstalledSize int `json:"installedSize" cyclonedx:"installedSize"` - Licenses string `json:"licenses,omitempty"` - Files []PortageFileRecord `json:"files"` + // InstalledSize is total size of installed files in bytes + InstalledSize int `json:"installedSize" cyclonedx:"installedSize"` + + // Licenses is license string which may be an expression (e.g. "GPL-2 OR Apache-2.0") + Licenses string `json:"licenses,omitempty"` + + // Files are the files installed by this package (tracked in CONTENTS file) + Files []PortageFileRecord `json:"files"` } // PortageFileRecord represents a single file attributed to a portage package. type PortageFileRecord struct { - Path string `json:"path"` + // Path is the file path relative to the filesystem root + Path string `json:"path"` + + // Digest is file content hash (MD5 for regular files in CONTENTS format: "obj filename md5hash mtime") Digest *file.Digest `json:"digest,omitempty"` } diff --git a/syft/pkg/python.go b/syft/pkg/python.go index 65787358671..8b1fdbd6add 100644 --- a/syft/pkg/python.go +++ b/syft/pkg/python.go @@ -13,37 +13,58 @@ var _ FileOwner = (*PythonPackage)(nil) // Historically these were defined in PEPs 345, 314, and 241, but have been superseded by PEP 566. This means that this // struct can (partially) express at least versions 1.0, 1.1, 1.2, 2.1, 2.2, and 2.3 of the metadata format. type PythonPackage struct { - Name string `json:"name" mapstructure:"Name"` - Version string `json:"version" mapstructure:"Version"` - Author string `json:"author" mapstructure:"Author"` - AuthorEmail string `json:"authorEmail" mapstructure:"AuthorEmail"` - Platform string `json:"platform" mapstructure:"Platform"` - Files []PythonFileRecord `json:"files,omitempty"` - SitePackagesRootPath string `json:"sitePackagesRootPath"` - TopLevelPackages []string `json:"topLevelPackages,omitempty"` - DirectURLOrigin *PythonDirectURLOriginInfo `json:"directUrlOrigin,omitempty"` - RequiresPython string `json:"requiresPython,omitempty" mapstructure:"RequiresPython"` - RequiresDist []string `json:"requiresDist,omitempty" mapstructure:"RequiresDist"` - ProvidesExtra []string `json:"providesExtra,omitempty" mapstructure:"ProvidesExtra"` + // Name is the package name from the Name field in PKG-INFO or METADATA. + Name string `json:"name" mapstructure:"Name"` + // Version is the package version from the Version field in PKG-INFO or METADATA. + Version string `json:"version" mapstructure:"Version"` + // Author is the package author name from the Author field. + Author string `json:"author" mapstructure:"Author"` + // AuthorEmail is the package author's email address from the Author-Email field. + AuthorEmail string `json:"authorEmail" mapstructure:"AuthorEmail"` + // Platform indicates the target platform for the package (e.g., "any", "linux", "win32"). + Platform string `json:"platform" mapstructure:"Platform"` + // Files are the installed files listed in the RECORD file for wheels or installed-files.txt for eggs. + Files []PythonFileRecord `json:"files,omitempty"` + // SitePackagesRootPath is the root directory path containing the package (e.g., "/usr/lib/python3.9/site-packages"). + SitePackagesRootPath string `json:"sitePackagesRootPath"` + // TopLevelPackages are the top-level Python module names from top_level.txt file. + TopLevelPackages []string `json:"topLevelPackages,omitempty"` + // DirectURLOrigin contains VCS or direct URL installation information from direct_url.json. + DirectURLOrigin *PythonDirectURLOriginInfo `json:"directUrlOrigin,omitempty"` + // RequiresPython specifies the Python version requirement (e.g., ">=3.6"). + RequiresPython string `json:"requiresPython,omitempty" mapstructure:"RequiresPython"` + // RequiresDist lists the package dependencies with version specifiers from Requires-Dist fields. + RequiresDist []string `json:"requiresDist,omitempty" mapstructure:"RequiresDist"` + // ProvidesExtra lists optional feature names that can be installed via extras (e.g., "dev", "test"). + ProvidesExtra []string `json:"providesExtra,omitempty" mapstructure:"ProvidesExtra"` } // PythonFileDigest represents the file metadata for a single file attributed to a python package. type PythonFileDigest struct { + // Algorithm is the hash algorithm used (e.g., "sha256"). Algorithm string `json:"algorithm"` - Value string `json:"value"` + // Value is the hex-encoded hash digest value. + Value string `json:"value"` } // PythonFileRecord represents a single entry within a RECORD file for a python wheel or egg package type PythonFileRecord struct { - Path string `json:"path"` + // Path is the installed file path from the RECORD file. + Path string `json:"path"` + // Digest contains the hash algorithm and value for file integrity verification. Digest *PythonFileDigest `json:"digest,omitempty"` - Size string `json:"size,omitempty"` + // Size is the file size in bytes as a string. + Size string `json:"size,omitempty"` } +// PythonDirectURLOriginInfo represents installation source metadata from direct_url.json for packages installed from VCS or direct URLs. type PythonDirectURLOriginInfo struct { - URL string `json:"url"` + // URL is the source URL from which the package was installed. + URL string `json:"url"` + // CommitID is the VCS commit hash if installed from version control. CommitID string `json:"commitId,omitempty"` - VCS string `json:"vcs,omitempty"` + // VCS is the version control system type (e.g., "git", "hg"). + VCS string `json:"vcs,omitempty"` } func (m PythonPackage) OwnedFiles() (result []string) { @@ -60,35 +81,84 @@ func (m PythonPackage) OwnedFiles() (result []string) { // PythonPipfileLockEntry represents a single package entry within a Pipfile.lock file. type PythonPipfileLockEntry struct { + // Hashes are the package file hash values in the format "algorithm:digest" for integrity verification. Hashes []string `mapstructure:"hashes" json:"hashes"` - Index string `mapstructure:"index" json:"index"` + // Index is the PyPI index name where the package should be fetched from. + Index string `mapstructure:"index" json:"index"` } // PythonPoetryLockEntry represents a single package entry within a Pipfile.lock file. type PythonPoetryLockEntry struct { - Index string `mapstructure:"index" json:"index"` + // Index is the package repository name where the package should be fetched from. + Index string `mapstructure:"index" json:"index"` + // Dependencies are the package's runtime dependencies with version constraints. Dependencies []PythonPoetryLockDependencyEntry `json:"dependencies"` - Extras []PythonPoetryLockExtraEntry `json:"extras,omitempty"` + // Extras are optional feature groups that include additional dependencies. + Extras []PythonPoetryLockExtraEntry `json:"extras,omitempty"` } +// PythonPoetryLockDependencyEntry represents a single dependency entry within a Poetry lock file. type PythonPoetryLockDependencyEntry struct { - Name string `json:"name"` - Version string `json:"version"` - Optional bool `json:"optional"` - Markers string `json:"markers,omitempty"` - Extras []string `json:"extras,omitempty"` + // Name is the dependency package name. + Name string `json:"name"` + // Version is the locked version or version constraint for the dependency. + Version string `json:"version"` + // Optional indicates whether this dependency is optional (only needed for certain extras). + Optional bool `json:"optional"` + // Markers are environment marker expressions that conditionally enable the dependency (e.g., "python_version >= '3.8'"). + Markers string `json:"markers,omitempty"` + // Extras are the optional feature names from the dependency that should be installed. + Extras []string `json:"extras,omitempty"` } +// PythonPoetryLockExtraEntry represents an optional feature group in a Poetry lock file. type PythonPoetryLockExtraEntry struct { - Name string `json:"name"` + // Name is the optional feature name (e.g., "dev", "test"). + Name string `json:"name"` + // Dependencies are the package names required when this extra is installed. Dependencies []string `json:"dependencies"` } // PythonRequirementsEntry represents a single entry within a [*-]requirements.txt file. type PythonRequirementsEntry struct { - Name string `json:"name" mapstructure:"Name"` - Extras []string `json:"extras,omitempty" mapstructure:"Extras"` - VersionConstraint string `json:"versionConstraint" mapstructure:"VersionConstraint"` - URL string `json:"url,omitempty" mapstructure:"URL"` - Markers string `json:"markers,omitempty" mapstructure:"Markers"` + // Name is the package name from the requirements file. + Name string `json:"name" mapstructure:"Name"` + // Extras are the optional features to install from the package (e.g., package[dev,test]). + Extras []string `json:"extras,omitempty" mapstructure:"Extras"` + // VersionConstraint specifies version requirements (e.g., ">=1.0,<2.0"). + VersionConstraint string `json:"versionConstraint" mapstructure:"VersionConstraint"` + // URL is the direct download URL or VCS URL if specified instead of a PyPI package. + URL string `json:"url,omitempty" mapstructure:"URL"` + // Markers are environment marker expressions for conditional installation (e.g., "python_version >= '3.8'"). + Markers string `json:"markers,omitempty" mapstructure:"Markers"` +} + +// PythonUvLockDependencyEntry represents a single dependency entry within a uv lock file. +type PythonUvLockDependencyEntry struct { + // Name is the dependency package name. + Name string `json:"name"` + // Optional indicates whether this dependency is optional (only needed for certain extras). + Optional bool `json:"optional"` + // Markers are environment marker expressions that conditionally enable the dependency (e.g., "python_version >= '3.8'"). + Markers string `json:"markers,omitempty"` + // Extras are the optional feature names from the dependency that should be installed. + Extras []string `json:"extras,omitempty"` +} + +// PythonUvLockExtraEntry represents an optional feature group in a uv lock file. +type PythonUvLockExtraEntry struct { + // Name is the optional feature name (e.g., "dev", "test"). + Name string `json:"name"` + // Dependencies are the package names required when this extra is installed. + Dependencies []string `json:"dependencies"` +} + +// PythonUvLockEntry represents a single package entry within a uv.lock file. +type PythonUvLockEntry struct { + // Index is the package repository name where the package should be fetched from. + Index string `mapstructure:"index" json:"index"` + // Dependencies are the package's runtime dependencies with version constraints. + Dependencies []PythonUvLockDependencyEntry `json:"dependencies"` + // Extras are optional feature groups that include additional dependencies. + Extras []PythonUvLockExtraEntry `json:"extras,omitempty"` } diff --git a/syft/pkg/r.go b/syft/pkg/r.go index c10c11d0e16..04563406ee6 100644 --- a/syft/pkg/r.go +++ b/syft/pkg/r.go @@ -1,23 +1,44 @@ package pkg +// Fields chosen by: +// docker run --rm -it rocker/r-ver bash +// $ install2.r ggplot2 # has a lot of dependencies +// $ find /usr/local/lib/R -name DESCRIPTION | xargs cat | grep -v '^\s' | cut -d ':' -f 1 | sort | uniq -c | sort -nr +// +// For more information on the DESCRIPTION file see https://r-pkgs.org/description.html + +// RDescription represents metadata from an R package DESCRIPTION file containing package information, dependencies, and author details. type RDescription struct { - /* - Fields chosen by: - docker run --rm -it rocker/r-ver bash - $ install2.r ggplot2 # has a lot of dependencies - $ find /usr/local/lib/R -name DESCRIPTION | xargs cat | grep -v '^\s' | cut -d ':' -f 1 | sort | uniq -c | sort -nr - - For more information on the DESCRIPTION file see https://r-pkgs.org/description.html - */ - Title string `json:"title,omitempty"` - Description string `json:"description,omitempty"` - Author string `json:"author,omitempty"` - Maintainer string `json:"maintainer,omitempty"` - URL []string `json:"url,omitempty"` - Repository string `json:"repository,omitempty"` - Built string `json:"built,omitempty"` - NeedsCompilation bool `json:"needsCompilation,omitempty"` - Imports []string `json:"imports,omitempty"` - Depends []string `json:"depends,omitempty"` - Suggests []string `json:"suggests,omitempty"` + // Title is short one-line package title + Title string `json:"title,omitempty"` + + // Description is detailed package description + Description string `json:"description,omitempty"` + + // Author is package author(s) + Author string `json:"author,omitempty"` + + // Maintainer is current package maintainer + Maintainer string `json:"maintainer,omitempty"` + + // URL is the list of related URLs + URL []string `json:"url,omitempty"` + + // Repository is CRAN or other repository name + Repository string `json:"repository,omitempty"` + + // Built is R version and platform this was built with + Built string `json:"built,omitempty"` + + // NeedsCompilation is whether this package requires compilation + NeedsCompilation bool `json:"needsCompilation,omitempty"` + + // Imports are the packages imported in the NAMESPACE + Imports []string `json:"imports,omitempty"` + + // Depends are the packages this package depends on + Depends []string `json:"depends,omitempty"` + + // Suggests are the optional packages that extend functionality + Suggests []string `json:"suggests,omitempty"` } diff --git a/syft/pkg/rockspec.go b/syft/pkg/rockspec.go index 05ca74f7ca8..05ae5d2ed9c 100644 --- a/syft/pkg/rockspec.go +++ b/syft/pkg/rockspec.go @@ -1,11 +1,25 @@ package pkg +// LuaRocksPackage represents a Lua package managed by the LuaRocks package manager with metadata from .rockspec files. type LuaRocksPackage struct { - Name string `json:"name"` - Version string `json:"version"` - License string `json:"license"` - Homepage string `json:"homepage"` - Description string `json:"description"` - URL string `json:"url"` + // Name is the package name as found in the .rockspec file + Name string `json:"name"` + + // Version is the package version as found in the .rockspec file + Version string `json:"version"` + + // License is license identifier + License string `json:"license"` + + // Homepage is project homepage URL + Homepage string `json:"homepage"` + + // Description is a human-readable package description + Description string `json:"description"` + + // URL is the source download URL + URL string `json:"url"` + + // Dependencies are the map of dependency names to version constraints Dependencies map[string]string `json:"dependencies"` } diff --git a/syft/pkg/rpm.go b/syft/pkg/rpm.go index b11205c1b3b..3e8b67ba1c7 100644 --- a/syft/pkg/rpm.go +++ b/syft/pkg/rpm.go @@ -22,31 +22,64 @@ const RpmManifestGlob = "**/var/lib/rpmmanifest/container-manifest-2" var _ FileOwner = (*RpmDBEntry)(nil) -// RpmArchive represents all captured data from a RPM package archive. +// RpmArchive represents package metadata extracted directly from a .rpm archive file, containing the same information as an RPM database entry. type RpmArchive RpmDBEntry // RpmDBEntry represents all captured data from a RPM DB package entry. type RpmDBEntry struct { - Name string `json:"name"` - Version string `json:"version"` - Epoch *int `json:"epoch" cyclonedx:"epoch" jsonschema:"nullable"` - Arch string `json:"architecture"` - Release string `json:"release" cyclonedx:"release"` - SourceRpm string `json:"sourceRpm" cyclonedx:"sourceRpm"` - Signatures []RpmSignature `json:"signatures,omitempty" cyclonedx:"signatures"` - Size int `json:"size" cyclonedx:"size"` - Vendor string `json:"vendor"` - ModularityLabel *string `json:"modularityLabel,omitempty"` - Provides []string `json:"provides,omitempty"` - Requires []string `json:"requires,omitempty"` - Files []RpmFileRecord `json:"files"` + // Name is the RPM package name as found in the RPM database. + Name string `json:"name"` + + // Version is the upstream version of the package. + Version string `json:"version"` + + // Epoch is the version epoch used to force upgrade ordering (null if not set). + Epoch *int `json:"epoch" cyclonedx:"epoch" jsonschema:"nullable"` + + // Arch is the target CPU architecture (e.g., "x86_64", "aarch64", "noarch"). + Arch string `json:"architecture"` + + // Release is the package release number or distribution-specific version suffix. + Release string `json:"release" cyclonedx:"release"` + + // SourceRpm is the source RPM filename that was used to build this package. + SourceRpm string `json:"sourceRpm" cyclonedx:"sourceRpm"` + + // Signatures contains GPG signature metadata for package verification. + Signatures []RpmSignature `json:"signatures,omitempty" cyclonedx:"signatures"` + + // Size is the total installed size of the package in bytes. + Size int `json:"size" cyclonedx:"size"` + + // Vendor is the organization that packaged the software. + Vendor string `json:"vendor"` + + // ModularityLabel identifies the module stream for modular RPM packages (e.g., "nodejs:12:20200101"). + ModularityLabel *string `json:"modularityLabel,omitempty" cyclonedx:"modularityLabel"` + + // Provides lists the virtual packages and capabilities this package provides. + Provides []string `json:"provides,omitempty"` + + // Requires lists the dependencies required by this package. + Requires []string `json:"requires,omitempty"` + + // Files are the file records for all files owned by this package. + Files []RpmFileRecord `json:"files"` } +// RpmSignature represents a GPG signature for an RPM package used for authenticity verification. type RpmSignature struct { + // PublicKeyAlgorithm is the public key algorithm used for signing (e.g., "RSA"). PublicKeyAlgorithm string `json:"algo"` - HashAlgorithm string `json:"hash"` - Created string `json:"created"` - IssuerKeyID string `json:"issuer"` + + // HashAlgorithm is the hash algorithm used for the signature (e.g., "SHA256"). + HashAlgorithm string `json:"hash"` + + // Created is the timestamp when the signature was created. + Created string `json:"created"` + + // IssuerKeyID is the GPG key ID that created the signature. + IssuerKeyID string `json:"issuer"` } func (s RpmSignature) String() string { @@ -60,13 +93,26 @@ func (s RpmSignature) String() string { // RpmFileRecord represents the file metadata for a single file attributed to a RPM package. type RpmFileRecord struct { - Path string `json:"path"` - Mode RpmFileMode `json:"mode"` - Size int `json:"size"` - Digest file.Digest `json:"digest"` - UserName string `json:"userName"` - GroupName string `json:"groupName"` - Flags string `json:"flags"` + // Path is the absolute file path where the file is installed. + Path string `json:"path"` + + // Mode is the file permission mode bits following Unix stat.h conventions. + Mode RpmFileMode `json:"mode"` + + // Size is the file size in bytes. + Size int `json:"size"` + + // Digest contains the hash algorithm and value for file integrity verification. + Digest file.Digest `json:"digest"` + + // UserName is the owner username for the file. + UserName string `json:"userName"` + + // GroupName is the group name for the file. + GroupName string `json:"groupName"` + + // Flags indicates the file type (e.g., "%config", "%doc", "%ghost"). + Flags string `json:"flags"` } // RpmFileMode is the raw file mode for a single file. This can be interpreted as the linux stat.h mode (see https://pubs.opengroup.org/onlinepubs/007908799/xsh/sysstat.h.html) diff --git a/syft/pkg/ruby.go b/syft/pkg/ruby.go index 81280c54084..a4d8db6617d 100644 --- a/syft/pkg/ruby.go +++ b/syft/pkg/ruby.go @@ -2,24 +2,18 @@ package pkg // RubyGemspec represents all metadata parsed from the *.gemspec file type RubyGemspec struct { - Name string `mapstructure:"name" json:"name"` + // Name is gem name as specified in the gemspec + Name string `mapstructure:"name" json:"name"` + + // Version is gem version as specified in the gemspec Version string `mapstructure:"version" json:"version"` - // note regarding if Files can contribute to GemMetadata being able to implement FileOwner: this list is a - // "logical" list of files, not a list of paths that can be used to find the files without additional processing. - // - // For example: The "bundler" gem has a file entry of: - // "lib/bundler/vendor/uri/lib/uri/ldap.rb" - // but the actual file is located at: - // "/usr/local/lib/ruby/3.2.0/bundler/vendor/uri/lib/uri/ldap.rb" - // which do not match (the "lib" prefix is missing even for relative processing). - // - // without additional information about: - // - the gem installation path - // - the ruby installation path - // - the ruby version - // - environment variables (e.g. GEM_HOME) that may affect the gem installation path - // ... we can't reliably determine the full path to the file on disk, thus cannot implement FileOwner (...yet...). - Files []string `mapstructure:"files" json:"files,omitempty"` - Authors []string `mapstructure:"authors" json:"authors,omitempty"` - Homepage string `mapstructure:"homepage" json:"homepage,omitempty"` + + // Files is logical list of files in the gem (NOT directly usable as filesystem paths. Example: bundler gem lists "lib/bundler/vendor/uri/lib/uri/ldap.rb" but actual path is "/usr/local/lib/ruby/3.2.0/bundler/vendor/uri/lib/uri/ldap.rb". Would need gem installation path, ruby version, and env vars like GEM_HOME to resolve actual paths.) + Files []string `mapstructure:"files" json:"files,omitempty"` + + // Authors are the list of gem authors (stored as array regardless of using `author` or `authors` method in gemspec) + Authors []string `mapstructure:"authors" json:"authors,omitempty"` + + // Homepage is project homepage URL + Homepage string `mapstructure:"homepage" json:"homepage,omitempty"` } diff --git a/syft/pkg/rust.go b/syft/pkg/rust.go index c06c65fe7bd..b37e7d848e7 100644 --- a/syft/pkg/rust.go +++ b/syft/pkg/rust.go @@ -1,15 +1,31 @@ package pkg +// RustCargoLockEntry represents a locked dependency from a Cargo.lock file with precise version and checksum information. type RustCargoLockEntry struct { - Name string `toml:"name" json:"name"` - Version string `toml:"version" json:"version"` - Source string `toml:"source" json:"source"` - Checksum string `toml:"checksum" json:"checksum"` + // Name is crate name as specified in Cargo.toml + Name string `toml:"name" json:"name"` + + // Version is crate version as specified in Cargo.toml + Version string `toml:"version" json:"version"` + + // Source is the source registry or repository URL in format "registry+https://github.com/rust-lang/crates.io-index" for registry packages + Source string `toml:"source" json:"source"` + + // Checksum is content checksum for registry packages only (hexadecimal string). Cargo doesn't require or include checksums for git dependencies. Used to detect MITM attacks by verifying downloaded crate matches lockfile checksum. + Checksum string `toml:"checksum" json:"checksum"` + + // Dependencies are the list of dependencies with version constraints Dependencies []string `toml:"dependencies" json:"dependencies"` } +// RustBinaryAuditEntry represents Rust crate metadata extracted from a compiled binary using cargo-auditable format. type RustBinaryAuditEntry struct { - Name string `toml:"name" json:"name"` + // Name is crate name as specified in audit section of the build binary + Name string `toml:"name" json:"name"` + + // Version is crate version as specified in audit section of the build binary Version string `toml:"version" json:"version"` - Source string `toml:"source" json:"source"` + + // Source is the source registry or repository where this crate came from + Source string `toml:"source" json:"source"` } diff --git a/syft/pkg/snap.go b/syft/pkg/snap.go new file mode 100644 index 00000000000..b9b421c2eef --- /dev/null +++ b/syft/pkg/snap.go @@ -0,0 +1,28 @@ +package pkg + +const ( + SnapTypeBase = "base" + SnapTypeKernel = "kernel" + SnapTypeApp = "app" + SnapTypeGadget = "gadget" + SnapTypeSnapd = "snapd" +) + +// SnapEntry represents metadata for a Snap package extracted from snap.yaml or snapcraft.yaml files. +type SnapEntry struct { + // SnapType indicates the snap type (base, kernel, app, gadget, or snapd). + SnapType string `json:"snapType" yaml:"snapType"` // base, kernel, system, gadget, snapd + + // Base is the base snap name that this snap depends on (e.g., "core20", "core22"). + Base string `json:"base" yaml:"base"` // base snap name (e.g., core20, core22) + + // SnapName is the snap package name. + SnapName string `json:"snapName" yaml:"snapName"` // name of the snap + + // SnapVersion is the snap package version. + SnapVersion string `json:"snapVersion" yaml:"snapVersion"` // version of the snap + + // Architecture is the target CPU architecture (e.g., "amd64", "arm64"). + Architecture string `json:"architecture" yaml:"architecture"` // architecture (amd64, arm64, etc.) + +} diff --git a/syft/pkg/swift.go b/syft/pkg/swift.go index 3df696c1cf8..7dcf0137a1d 100644 --- a/syft/pkg/swift.go +++ b/syft/pkg/swift.go @@ -1,5 +1,7 @@ package pkg +// SwiftPackageManagerResolvedEntry represents a resolved dependency from a Package.resolved file with its locked version and source location. type SwiftPackageManagerResolvedEntry struct { + // Revision is git commit hash of the resolved package Revision string `mapstructure:"revision" json:"revision"` } diff --git a/syft/pkg/swipl.go b/syft/pkg/swipl.go index c4e1c4a86ac..80a646d3997 100644 --- a/syft/pkg/swipl.go +++ b/syft/pkg/swipl.go @@ -1,12 +1,28 @@ package pkg +// SwiplPackEntry represents a SWI-Prolog package from the pack system with metadata about the package and its dependencies. type SwiplPackEntry struct { - Name string `toml:"name" json:"name"` - Version string `toml:"version" json:"version"` - Author string `json:"author" mapstructure:"Author"` - AuthorEmail string `json:"authorEmail" mapstructure:"AuthorEmail"` - Packager string `json:"packager" mapstructure:"Packager"` - PackagerEmail string `json:"packagerEmail" mapstructure:"PackagerEmail"` - Homepage string `json:"homepage"` - Dependencies []string `toml:"dependencies" json:"dependencies"` + // Name is the package name as found in the .toml file + Name string `toml:"name" json:"name"` + + // Version is the package version as found in the .toml file + Version string `toml:"version" json:"version"` + + // Author is author name + Author string `json:"author" mapstructure:"Author"` + + // AuthorEmail is author email address + AuthorEmail string `json:"authorEmail" mapstructure:"AuthorEmail"` + + // Packager is packager name (if different from author) + Packager string `json:"packager" mapstructure:"Packager"` + + // PackagerEmail is packager email address + PackagerEmail string `json:"packagerEmail" mapstructure:"PackagerEmail"` + + // Homepage is project homepage URL + Homepage string `json:"homepage"` + + // Dependencies are the list of required dependencies + Dependencies []string `toml:"dependencies" json:"dependencies"` } diff --git a/syft/pkg/terraform.go b/syft/pkg/terraform.go index 30b191838cb..1e66f34021d 100644 --- a/syft/pkg/terraform.go +++ b/syft/pkg/terraform.go @@ -2,8 +2,12 @@ package pkg // TerraformLockProviderEntry represents a single provider entry in a Terraform dependency lock file (.terraform.lock.hcl). type TerraformLockProviderEntry struct { - URL string `hcl:",label" json:"url"` - Constraints string `hcl:"constraints,optional" json:"constraints"` - Version string `hcl:"version" json:"version"` - Hashes []string `hcl:"hashes" json:"hashes"` + // URL is the provider source address (e.g., "registry.terraform.io/hashicorp/aws"). + URL string `hcl:",label" json:"url"` + // Constraints specifies the version constraints for the provider (e.g., "~> 4.0"). + Constraints string `hcl:"constraints,optional" json:"constraints"` + // Version is the locked provider version selected during terraform init. + Version string `hcl:"version" json:"version"` + // Hashes are cryptographic checksums for the provider plugin archives across different platforms. + Hashes []string `hcl:"hashes" json:"hashes"` } diff --git a/syft/pkg/type.go b/syft/pkg/type.go index 04c08cd406e..7dea22586e0 100644 --- a/syft/pkg/type.go +++ b/syft/pkg/type.go @@ -16,6 +16,7 @@ const ( BitnamiPkg Type = "bitnami" CocoapodsPkg Type = "pod" ConanPkg Type = "conan" + CondaPkg Type = "conda" DartPubPkg Type = "dart-pub" DebPkg Type = "deb" DotnetPkg Type = "dotnet" @@ -59,6 +60,7 @@ var AllPkgs = []Type{ BitnamiPkg, CocoapodsPkg, ConanPkg, + CondaPkg, DartPubPkg, DebPkg, DotnetPkg, @@ -109,6 +111,8 @@ func (t Type) PackageURLType() string { return packageurl.TypeCocoapods case ConanPkg: return packageurl.TypeConan + case CondaPkg: + return packageurl.TypeGeneric case DartPubPkg: return packageurl.TypePub case DebPkg: @@ -206,6 +210,8 @@ func TypeByName(name string) Type { return GemPkg case "cargo", "crate": return RustPkg + case "conda": + return CondaPkg case packageurl.TypePub: return DartPubPkg case "dotnet": // here to support legacy use cases diff --git a/syft/pkg/type_test.go b/syft/pkg/type_test.go index abb1ba569e8..a0695b5bf04 100644 --- a/syft/pkg/type_test.go +++ b/syft/pkg/type_test.go @@ -130,6 +130,11 @@ func TestTypeFromPURL(t *testing.T) { purl: "pkg:opam/ocaml-base-compiler@5.2.0", expected: OpamPkg, }, + { + name: "conda", + purl: "pkg:generic/conda@1.2.3", + expected: CondaPkg, + }, } var pkgTypes = strset.New() diff --git a/syft/pkg/wordpress.go b/syft/pkg/wordpress.go index deeb6188353..fb219bd23a1 100644 --- a/syft/pkg/wordpress.go +++ b/syft/pkg/wordpress.go @@ -2,7 +2,12 @@ package pkg // WordpressPluginEntry represents all metadata parsed from the wordpress plugin file type WordpressPluginEntry struct { + // PluginInstallDirectory is directory name where the plugin is installed PluginInstallDirectory string `mapstructure:"pluginInstallDirectory" json:"pluginInstallDirectory"` - Author string `mapstructure:"author" json:"author,omitempty"` - AuthorURI string `mapstructure:"authorUri" json:"authorUri,omitempty"` + + // Author is plugin author name + Author string `mapstructure:"author" json:"author,omitempty"` + + // AuthorURI is author's website URL + AuthorURI string `mapstructure:"authorUri" json:"authorUri,omitempty"` } diff --git a/syft/source/alias.go b/syft/source/alias.go index e1c5c670173..e389a8afa79 100644 --- a/syft/source/alias.go +++ b/syft/source/alias.go @@ -1,8 +1,9 @@ package source type Alias struct { - Name string `json:"name" yaml:"name" mapstructure:"name"` - Version string `json:"version" yaml:"version" mapstructure:"version"` + Name string `json:"name" yaml:"name" mapstructure:"name"` + Version string `json:"version" yaml:"version" mapstructure:"version"` + Supplier string `json:"supplier" yaml:"supplier" mapstructure:"supplier"` } func (a *Alias) IsEmpty() bool { diff --git a/syft/source/description.go b/syft/source/description.go index 0aae582573f..04bb983fc45 100644 --- a/syft/source/description.go +++ b/syft/source/description.go @@ -5,5 +5,6 @@ type Description struct { ID string `hash:"ignore"` // the id generated from the parent source struct Name string `hash:"ignore"` Version string `hash:"ignore"` + Supplier string `hash:"ignore"` Metadata interface{} } diff --git a/syft/source/directorysource/directory_source.go b/syft/source/directorysource/directory_source.go index 0ab06980fe5..d45084a4ed5 100644 --- a/syft/source/directorysource/directory_source.go +++ b/syft/source/directorysource/directory_source.go @@ -112,6 +112,7 @@ func (s directorySource) ID() artifact.ID { func (s directorySource) Describe() source.Description { name := cleanDirPath(s.config.Path, s.config.Base) version := "" + supplier := "" if !s.config.Alias.IsEmpty() { a := s.config.Alias if a.Name != "" { @@ -120,11 +121,15 @@ func (s directorySource) Describe() source.Description { if a.Version != "" { version = a.Version } + if a.Supplier != "" { + supplier = a.Supplier + } } return source.Description{ - ID: string(s.id), - Name: name, - Version: version, + ID: string(s.id), + Name: name, + Version: version, + Supplier: supplier, Metadata: source.DirectoryMetadata{ Path: s.config.Path, Base: s.config.Base, diff --git a/syft/source/directorysource/directory_source_test.go b/syft/source/directorysource/directory_source_test.go index 751d4766289..fcadfbf864d 100644 --- a/syft/source/directorysource/directory_source_test.go +++ b/syft/source/directorysource/directory_source_test.go @@ -475,12 +475,13 @@ func Test_DirectorySource_ID(t *testing.T) { wantErr: require.Error, }, { - name: "to dir with name and version", + name: "to dir with name and version and supplier", cfg: Config{ Path: "./test-fixtures", Alias: source.Alias{ - Name: "name-me-that!", - Version: "version-me-this!", + Name: "name-me-that!", + Version: "version-me-this!", + Supplier: "some-supplier", }, }, want: artifact.ID("51a5f2a1536cf4b5220d4247814b07eec5862ab0547050f90e9ae216548ded7e"), @@ -490,8 +491,9 @@ func Test_DirectorySource_ID(t *testing.T) { cfg: Config{ Path: "./test-fixtures/image-simple", Alias: source.Alias{ - Name: "name-me-that!", - Version: "version-me-this!", + Name: "name-me-that!", + Version: "version-me-this!", + Supplier: "some-supplier", }, }, // note: this must match the previous value because the alias should trump the path info diff --git a/syft/source/filesource/file_source.go b/syft/source/filesource/file_source.go index 09a4422ced5..aa4b4df4bba 100644 --- a/syft/source/filesource/file_source.go +++ b/syft/source/filesource/file_source.go @@ -123,6 +123,7 @@ func (s fileSource) ID() artifact.ID { func (s fileSource) Describe() source.Description { name := path.Base(s.config.Path) version := s.digestForVersion + supplier := "" if !s.config.Alias.IsEmpty() { a := s.config.Alias if a.Name != "" { @@ -132,11 +133,16 @@ func (s fileSource) Describe() source.Description { if a.Version != "" { version = a.Version } + + if a.Supplier != "" { + supplier = a.Supplier + } } return source.Description{ - ID: string(s.id), - Name: name, - Version: version, + ID: string(s.id), + Name: name, + Version: version, + Supplier: supplier, Metadata: source.FileMetadata{ Path: s.config.Path, Digests: s.digests, diff --git a/syft/source/stereoscopesource/image_source.go b/syft/source/stereoscopesource/image_source.go index 3b23027dcbd..f14e311eda9 100644 --- a/syft/source/stereoscopesource/image_source.go +++ b/syft/source/stereoscopesource/image_source.go @@ -51,6 +51,7 @@ func (s stereoscopeImageSource) Describe() source.Description { a := s.config.Alias name := a.Name + supplier := a.Supplier nameIfUnset := func(n string) { if name != "" { return @@ -90,6 +91,7 @@ func (s stereoscopeImageSource) Describe() source.Description { ID: string(s.id), Name: name, Version: version, + Supplier: supplier, Metadata: s.metadata, } } diff --git a/syft/testutil/completion_testing.go b/syft/testutil/completion_testing.go new file mode 100644 index 00000000000..94ab7501276 --- /dev/null +++ b/syft/testutil/completion_testing.go @@ -0,0 +1,30 @@ +package testutil + +import ( + "testing" + + "github.com/anchore/syft/internal/packagemetadata" + "github.com/anchore/syft/internal/sourcemetadata" +) + +type PackageMetadataCompletionTester struct { + *packagemetadata.CompletionTester +} + +type SourceMetadataCompletionTester struct { + *sourcemetadata.CompletionTester +} + +func NewPackageMetadataCompletionTester(t testing.TB, ignore ...any) *PackageMetadataCompletionTester { + t.Helper() + return &PackageMetadataCompletionTester{ + CompletionTester: packagemetadata.NewCompletionTester(t, ignore...), + } +} + +func NewSourceMetadataCompletionTester(t testing.TB, ignore ...any) *SourceMetadataCompletionTester { + t.Helper() + return &SourceMetadataCompletionTester{ + CompletionTester: sourcemetadata.NewCompletionTester(t, ignore...), + } +} diff --git a/syft/testutil/package_metadata.go b/syft/testutil/package_metadata.go deleted file mode 100644 index ae49ba7983d..00000000000 --- a/syft/testutil/package_metadata.go +++ /dev/null @@ -1,17 +0,0 @@ -package testutil - -import ( - "testing" - - "github.com/anchore/syft/syft/internal/packagemetadata" -) - -type PackageMetadataCompletionTester struct { - *packagemetadata.CompletionTester -} - -func NewPackageMetadataCompletionTester(t testing.TB, ignore ...any) *PackageMetadataCompletionTester { - return &PackageMetadataCompletionTester{ - CompletionTester: packagemetadata.NewCompletionTester(t, ignore...), - } -} diff --git a/test/cli/config_test.go b/test/cli/config_test.go index 0a37169afee..3fd8287a201 100644 --- a/test/cli/config_test.go +++ b/test/cli/config_test.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/stretchr/testify/require" - "gopkg.in/yaml.v3" + "go.yaml.in/yaml/v3" ) func Test_configLoading(t *testing.T) { diff --git a/test/cli/scan_cmd_test.go b/test/cli/scan_cmd_test.go index 42aad73dba4..133b1d171ba 100644 --- a/test/cli/scan_cmd_test.go +++ b/test/cli/scan_cmd_test.go @@ -71,6 +71,21 @@ func TestPackagesCmdFlags(t *testing.T) { assertSuccessfulReturnCode, }, }, + { + name: "source flags override bom metadata", + args: []string{ + "scan", + "--source-name", "custom-name", + "--source-version", "custom-version", + "--source-supplier", "custom-supplier", + "-o", "json", coverageImage}, + assertions: []traitAssertion{ + assertInOutput("custom-name"), + assertInOutput("custom-version"), + assertInOutput("custom-supplier"), + assertSuccessfulReturnCode, + }, + }, // I haven't been able to reproduce locally yet, but in CI this has proven to be unstable: // For the same commit: // pass: https://github.com/anchore/syft/runs/4611344142?check_suite_focus=true diff --git a/test/install/1_download_snapshot_asset_test.sh b/test/install/1_download_snapshot_asset_test.sh index 8a8439817bf..0590f1ce620 100755 --- a/test/install/1_download_snapshot_asset_test.sh +++ b/test/install/1_download_snapshot_asset_test.sh @@ -104,6 +104,8 @@ run_test_case test_positive_snapshot_download_asset "darwin" "arm64" "tar.gz" run_test_case test_positive_snapshot_download_asset "windows" "amd64" "sbom" run_test_case test_positive_snapshot_download_asset "windows" "amd64" "zip" +run_test_case test_positive_snapshot_download_asset "windows" "arm64" "sbom" +run_test_case test_positive_snapshot_download_asset "windows" "arm64" "zip" # note: the mac signing process produces a dmg which is not part of the snapshot process (thus is not exercised here) # let's make certain we covered all assets that were expected diff --git a/test/install/3_install_asset_test.sh b/test/install/3_install_asset_test.sh index 02fa7630036..225d5370bf2 100755 --- a/test/install/3_install_asset_test.sh +++ b/test/install/3_install_asset_test.sh @@ -99,6 +99,7 @@ run_test_case test_positive_snapshot_install_asset "linux" "s390x" "tar.gz" run_test_case test_positive_snapshot_install_asset "darwin" "amd64" "tar.gz" run_test_case test_positive_snapshot_install_asset "darwin" "arm64" "tar.gz" run_test_case test_positive_snapshot_install_asset "windows" "amd64" "zip" +run_test_case test_positive_snapshot_install_asset "windows" "arm64" "zip" # let's make certain we covered all assets that were expected run_test_case test_install_asset_exercised_all_archive_assets