mirror of
https://github.com/anchore/syft.git
synced 2026-10-25 03:22:22 +01:00
Compare commits
+3
-3
@@ -90,7 +90,7 @@ tools:
|
||||
# used for running all local and CI tasks
|
||||
- name: task
|
||||
version:
|
||||
want: v3.46.4
|
||||
want: v3.48.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: go-task/task
|
||||
@@ -98,7 +98,7 @@ tools:
|
||||
# used for triggering a release
|
||||
- name: gh
|
||||
version:
|
||||
want: v2.85.0
|
||||
want: v2.86.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: cli/cli
|
||||
@@ -114,7 +114,7 @@ tools:
|
||||
# used to upload test fixture cache
|
||||
- name: yq
|
||||
version:
|
||||
want: v4.50.1
|
||||
want: v4.52.2
|
||||
method: github-release
|
||||
with:
|
||||
repo: mikefarah/yq
|
||||
|
||||
@@ -29,7 +29,7 @@ runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
# note: go mod and build is automatically cached on default with v4+
|
||||
- uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
|
||||
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||
if: inputs.go-version != ''
|
||||
with:
|
||||
go-version: ${{ inputs.go-version }}
|
||||
|
||||
@@ -15,6 +15,8 @@ updates:
|
||||
|
||||
- package-ecosystem: gomod
|
||||
directory: "/"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "friday"
|
||||
@@ -34,6 +36,8 @@ updates:
|
||||
directories:
|
||||
- "/"
|
||||
- "/.github/actions/bootstrap"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "friday"
|
||||
|
||||
@@ -36,18 +36,18 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c #v6.1.0
|
||||
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 #v6.2.0
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 #v3.29.5
|
||||
uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -58,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@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 #v3.29.5
|
||||
uses: github/codeql-action/autobuild@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -72,4 +72,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 #v3.29.5
|
||||
uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
issues: write
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
if: ${{ github.event.inputs.phase == 'all' }}
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -141,7 +141,7 @@ jobs:
|
||||
# required for goreleaser signs section with cosign
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: true
|
||||
@@ -192,14 +192,24 @@ jobs:
|
||||
file: go.mod
|
||||
artifact-name: sbom.spdx.json
|
||||
|
||||
- uses: 8398a7/action-slack@77eaa4f1c608a7d68b38af4e3f739dcd8cba273e #v3.19.0
|
||||
- name: Notify Slack of new release
|
||||
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a #v2.1.1
|
||||
continue-on-error: true
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
fields: repo,workflow,action,eventName
|
||||
text: "A new Syft release has been published: https://github.com/anchore/syft/releases/tag/${{ github.event.inputs.version }}"
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
|
||||
webhook: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
|
||||
webhook-type: incoming-webhook
|
||||
payload: |
|
||||
text: "A new Syft release has been published: https://github.com/anchore/syft/releases/tag/${{ github.event.inputs.version }}"
|
||||
blocks:
|
||||
- type: section
|
||||
text:
|
||||
type: mrkdwn
|
||||
text: |
|
||||
*A new Syft release has been published* :rocket:
|
||||
• Release: <https://github.com/anchore/syft/releases/tag/${{ github.event.inputs.version }}|${{ github.event.inputs.version }}>
|
||||
• Repo: `${{ github.repository }}`
|
||||
• Workflow: `${{ github.workflow }}`
|
||||
• Event: `${{ github.event_name }}`
|
||||
if: ${{ success() }}
|
||||
|
||||
release-install-script:
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
permissions:
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'anchore' # only run for main repo (not forks)
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
app-id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private-key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 #v8.0.0
|
||||
- uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 #v8.1.0
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
app-id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private-key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 #v8.0.0
|
||||
- uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 #v8.1.0
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
packages: write
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
app-id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private-key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 #v8.0.0
|
||||
- uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 #v8.1.0
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
@@ -64,11 +64,21 @@ jobs:
|
||||
Update CPE dictionary index based on the latest available CPE dictionary
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
- uses: 8398a7/action-slack@77eaa4f1c608a7d68b38af4e3f739dcd8cba273e #v3.19.0
|
||||
- name: Notify Slack on failure
|
||||
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a #v2.1.1
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
fields: workflow,eventName,job
|
||||
text: Syft CPE dictionary index update failed
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
|
||||
webhook: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
|
||||
webhook-type: incoming-webhook
|
||||
payload: |
|
||||
text: "Syft CPE dictionary index update failed"
|
||||
blocks:
|
||||
- type: section
|
||||
text:
|
||||
type: mrkdwn
|
||||
text: |
|
||||
*Syft CPE dictionary index update failed*
|
||||
• Workflow: `${{ github.workflow }}`
|
||||
• Event: `${{ github.event_name }}`
|
||||
• Job Status: `${{ job.status }}`
|
||||
• <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>
|
||||
if: ${{ failure() && env.SLACK_NOTIFICATIONS == 'true' }}
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 #v8.0.0
|
||||
- uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 #v8.1.0
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
@@ -44,11 +44,21 @@ jobs:
|
||||
Update SPDX license list based on the latest available list from spdx.org
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
- uses: 8398a7/action-slack@77eaa4f1c608a7d68b38af4e3f739dcd8cba273e #v3.19.0
|
||||
- name: Notify Slack on failure
|
||||
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a #v2.1.1
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
fields: workflow,eventName,job
|
||||
text: Syft SPDX license list update failed
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
|
||||
webhook: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
|
||||
webhook-type: incoming-webhook
|
||||
payload: |
|
||||
text: "Syft SPDX license list update failed"
|
||||
blocks:
|
||||
- type: section
|
||||
text:
|
||||
type: mrkdwn
|
||||
text: |
|
||||
*Syft SPDX license list update failed*
|
||||
• Workflow: `${{ github.workflow }}`
|
||||
• Event: `${{ github.event_name }}`
|
||||
• Job Status: `${{ job.status }}`
|
||||
• <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>
|
||||
if: ${{ failure() && env.SLACK_NOTIFICATIONS == 'true' }}
|
||||
|
||||
@@ -23,13 +23,14 @@ jobs:
|
||||
contents: read
|
||||
security-events: write # for uploading SARIF results
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run zizmor"
|
||||
uses: zizmorcore/zizmor-action@e639db99335bc9038abc0e066dfcd72e23d26fb4 # v0.3.0
|
||||
uses: zizmorcore/zizmor-action@135698455da5c3b3e55f73f4419e481ab68cdd95 # v0.4.1
|
||||
with:
|
||||
config-file: .github/zizmor.yml
|
||||
sarif-upload: true
|
||||
config: .github/zizmor.yml
|
||||
# Disable SARIF upload so the step is a simple pass/fail gate
|
||||
advanced-security: false
|
||||
inputs: .github
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
# tmpfs: faster io-intensive workflows
|
||||
runs-on: &test-runner "runs-on=${{ github.run_id }}/cpu=4+8/ram=32+128/family=r5+r6+r7+r8+m4+m5+m6+m7+m8/spot=price-capacity-optimized/extras=s3-cache+tmpfs"
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -46,7 +46,7 @@ jobs:
|
||||
name: "Unit tests"
|
||||
runs-on: *test-runner
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
name: "Integration tests"
|
||||
runs-on: *test-runner
|
||||
steps:
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
# required for magic-cache from runs-on to function with artifact upload/download (see https://runs-on.com/caching/magic-cache/#actionsupload-artifact-compatibility)
|
||||
- uses: runs-on/action@cd2b598b0515d39d78c38a02d529db87d2196d1e # v2.0.3
|
||||
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -121,7 +121,7 @@ jobs:
|
||||
# required for magic-cache from runs-on to function with artifact upload/download (see https://runs-on.com/caching/magic-cache/#actionsupload-artifact-compatibility)
|
||||
- uses: runs-on/action@cd2b598b0515d39d78c38a02d529db87d2196d1e # v2.0.3
|
||||
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -163,7 +163,7 @@ jobs:
|
||||
- name: Install Cosign
|
||||
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
|
||||
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@@ -198,7 +198,7 @@ jobs:
|
||||
# required for magic-cache from runs-on to function with artifact upload/download (see https://runs-on.com/caching/magic-cache/#actionsupload-artifact-compatibility)
|
||||
- uses: runs-on/action@cd2b598b0515d39d78c38a02d529db87d2196d1e # v2.0.3
|
||||
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
rules:
|
||||
unpinned-uses:
|
||||
ignore:
|
||||
# Allow unpinned uses of trusted internal anchore/workflows actions
|
||||
- update-anchore-dependencies.yml
|
||||
|
||||
config:
|
||||
policies:
|
||||
# anchore/workflows is an internal repository; using @main is acceptable
|
||||
anchore/*: any
|
||||
dangerous-triggers:
|
||||
ignore:
|
||||
# Safe use of pull_request_target - only runs trusted scripts from base repo,
|
||||
|
||||
@@ -23,7 +23,7 @@ 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.18
|
||||
github.com/anchore/stereoscope v0.1.19
|
||||
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
|
||||
@@ -39,12 +39,12 @@ require (
|
||||
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.5
|
||||
github.com/github/go-spdx/v2 v2.3.6
|
||||
github.com/gkampitakis/go-snaps v0.5.19
|
||||
github.com/go-git/go-billy/v5 v5.7.0
|
||||
github.com/go-git/go-git/v5 v5.16.4
|
||||
github.com/go-test/deep v1.1.1
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0
|
||||
github.com/gohugoio/hashstructure v0.6.0
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/google/go-containerregistry v0.20.7
|
||||
@@ -64,7 +64,7 @@ require (
|
||||
github.com/mholt/archives v0.1.5
|
||||
github.com/moby/sys/mountinfo v0.7.2
|
||||
github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1
|
||||
github.com/olekukonko/tablewriter v1.1.2
|
||||
github.com/olekukonko/tablewriter v1.1.3
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.23
|
||||
@@ -76,7 +76,7 @@ require (
|
||||
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e
|
||||
github.com/sergi/go-diff v1.4.0
|
||||
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb
|
||||
github.com/spdx/tools-golang v0.5.6
|
||||
github.com/spdx/tools-golang v0.5.7
|
||||
github.com/spf13/afero v1.15.0
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/stretchr/testify v1.11.1
|
||||
@@ -88,10 +88,10 @@ require (
|
||||
github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1
|
||||
go.uber.org/goleak v1.3.0
|
||||
go.yaml.in/yaml/v3 v3.0.4
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b
|
||||
golang.org/x/mod v0.31.0
|
||||
golang.org/x/net v0.48.0
|
||||
modernc.org/sqlite v1.43.0
|
||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546
|
||||
golang.org/x/mod v0.32.0
|
||||
golang.org/x/net v0.49.0
|
||||
modernc.org/sqlite v1.44.3
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -139,7 +139,7 @@ require (
|
||||
github.com/containerd/typeurl/v2 v2.2.3 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.6.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/docker/cli v29.1.4+incompatible // indirect
|
||||
github.com/docker/cli v29.1.5+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker v28.5.2+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.9.4 // indirect
|
||||
@@ -199,7 +199,7 @@ require (
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/termenv v0.16.0 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.3.0 // indirect
|
||||
github.com/opencontainers/selinux v1.13.1 // indirect
|
||||
@@ -258,7 +258,7 @@ require (
|
||||
golang.org/x/term v0.39.0 // indirect
|
||||
golang.org/x/text v0.33.0 // indirect
|
||||
golang.org/x/time v0.14.0
|
||||
golang.org/x/tools v0.40.0
|
||||
golang.org/x/tools v0.41.0
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||
google.golang.org/api v0.256.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20250922171735-9219d122eba9 // indirect
|
||||
@@ -268,7 +268,7 @@ require (
|
||||
google.golang.org/protobuf v1.36.10 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
modernc.org/libc v1.66.10 // indirect
|
||||
modernc.org/libc v1.67.6 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.11.0 // indirect
|
||||
)
|
||||
@@ -307,7 +307,7 @@ require (
|
||||
github.com/aws/smithy-go v1.24.0 // indirect
|
||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/clipperhouse/displaywidth v0.6.0 // indirect
|
||||
github.com/clipperhouse/displaywidth v0.6.2 // indirect
|
||||
github.com/clipperhouse/stringish v0.1.1 // indirect
|
||||
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect
|
||||
@@ -326,7 +326,7 @@ require (
|
||||
github.com/nwaples/rardecode/v2 v2.2.0 // indirect
|
||||
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect
|
||||
github.com/olekukonko/errors v1.1.0 // indirect
|
||||
github.com/olekukonko/ll v0.1.3 // indirect
|
||||
github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0 // indirect
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d // indirect
|
||||
github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect
|
||||
|
||||
@@ -152,8 +152,8 @@ 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.18 h1:Mj34pRtxwfdFJkYKtKjiO9Xn7qs0RTCi59ofRYTSCEU=
|
||||
github.com/anchore/stereoscope v0.1.18/go.mod h1:y8P4BURfBj0DVRly9cPHsSuZdI/AsZs3ee/x/HusEe4=
|
||||
github.com/anchore/stereoscope v0.1.19 h1:1G5LVmRN1Sz6qNezpVAEeN7QfWwCE9zw9TJK1ZGnkvw=
|
||||
github.com/anchore/stereoscope v0.1.19/go.mod h1:+laNHlk05xA2YqgEzq8mxkFzclL3NRdeNIsiQQVeZZ4=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
|
||||
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
|
||||
@@ -282,8 +282,8 @@ github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38
|
||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/clipperhouse/displaywidth v0.6.0 h1:k32vueaksef9WIKCNcoqRNyKbyvkvkysNYnAWz2fN4s=
|
||||
github.com/clipperhouse/displaywidth v0.6.0/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o=
|
||||
github.com/clipperhouse/displaywidth v0.6.2 h1:ZDpTkFfpHOKte4RG5O/BOyf3ysnvFswpyYrV7z2uAKo=
|
||||
github.com/clipperhouse/displaywidth v0.6.2/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o=
|
||||
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
|
||||
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
|
||||
github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
|
||||
@@ -351,8 +351,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr
|
||||
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 v29.1.4+incompatible h1:AI8fwZhqsAsrqZnVv9h6lbexeW/LzNTasf6A4vcNN8M=
|
||||
github.com/docker/cli v29.1.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v29.1.5+incompatible h1:GckbANUt3j+lsnQ6eCcQd70mNSOismSHWt8vk2AX8ao=
|
||||
github.com/docker/cli v29.1.5+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.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=
|
||||
@@ -420,8 +420,8 @@ github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/github/go-spdx/v2 v2.3.5 h1:rtRQmzDSq2sU/F2oTIvNQQ+6oInq7yxex5npgY//bJQ=
|
||||
github.com/github/go-spdx/v2 v2.3.5/go.mod h1:VziiWwQ/hoGS++2ifYyr/za0Ng9rlgMS+c4U7zckrDs=
|
||||
github.com/github/go-spdx/v2 v2.3.6 h1:9flm625VmmTlWXi0YH5W9V8FdMfulvxalHdYnUfoqxc=
|
||||
github.com/github/go-spdx/v2 v2.3.6/go.mod h1:/5rwgS0txhGtRdUZwc02bTglzg6HK3FfuEbECKlK2Sg=
|
||||
github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs=
|
||||
github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo=
|
||||
github.com/gkampitakis/go-snaps v0.5.19 h1:hUJlCQOpTt1M+kSisMwioDWZDWpDtdAvUhvWCx1YGW0=
|
||||
@@ -458,8 +458,8 @@ github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
|
||||
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.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.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=
|
||||
@@ -772,8 +772,8 @@ github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIf
|
||||
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
|
||||
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
|
||||
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||
github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 h1:kpt9ZfKcm+EDG4s40hMwE//d5SBgDjUOrITReV2u4aA=
|
||||
github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1/go.mod h1:qgCw4bBKZX8qMgGeEZzGFVT3notl42dBjNqO2jut0M0=
|
||||
github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE=
|
||||
@@ -784,10 +784,10 @@ github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj
|
||||
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0=
|
||||
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.1.3 h1:sV2jrhQGq5B3W0nENUISCR6azIPf7UBUpVq0x/y70Fg=
|
||||
github.com/olekukonko/ll v0.1.3/go.mod h1:b52bVQRRPObe+yyBl0TxNfhesL0nedD4Cht0/zx55Ew=
|
||||
github.com/olekukonko/tablewriter v1.1.2 h1:L2kI1Y5tZBct/O/TyZK1zIE9GlBj/TVs+AY5tZDCDSc=
|
||||
github.com/olekukonko/tablewriter v1.1.2/go.mod h1:z7SYPugVqGVavWoA2sGsFIoOVNmEHxUAAMrhXONtfkg=
|
||||
github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0 h1:jrYnow5+hy3WRDCBypUFvVKNSPPCdqgSXIE9eJDD8LM=
|
||||
github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0/go.mod h1:b52bVQRRPObe+yyBl0TxNfhesL0nedD4Cht0/zx55Ew=
|
||||
github.com/olekukonko/tablewriter v1.1.3 h1:VSHhghXxrP0JHl+0NnKid7WoEmd9/urKRJLysb70nnA=
|
||||
github.com/olekukonko/tablewriter v1.1.3/go.mod h1:9VU0knjhmMkXjnMKrZ3+L2JhhtsQ/L38BbL3CRNE8tM=
|
||||
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=
|
||||
@@ -898,8 +898,8 @@ github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIK
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb h1:bLo8hvc8XFm9J47r690TUKBzcjSWdJDxmjXJZ+/f92U=
|
||||
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM=
|
||||
github.com/spdx/tools-golang v0.5.6 h1:HUwSJWxyAR7vBstEeZ1+guD6Jcl4TVsKyTBUwT0RjTQ=
|
||||
github.com/spdx/tools-golang v0.5.6/go.mod h1:jg7w0LOpoNAw6OxKEzCoqPC2GCTj45LyTlVmXubDsYw=
|
||||
github.com/spdx/tools-golang v0.5.7 h1:+sWcKGnhwp3vLdMqPcLdA6QK679vd86cK9hQWH3AwCg=
|
||||
github.com/spdx/tools-golang v0.5.7/go.mod h1:jg7w0LOpoNAw6OxKEzCoqPC2GCTj45LyTlVmXubDsYw=
|
||||
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
|
||||
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||
@@ -1079,8 +1079,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
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-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/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
|
||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
||||
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/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -1108,8 +1108,8 @@ 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
|
||||
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
|
||||
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
||||
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
||||
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=
|
||||
@@ -1154,8 +1154,8 @@ golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
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=
|
||||
@@ -1342,8 +1342,8 @@ 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.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
|
||||
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
|
||||
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=
|
||||
@@ -1537,18 +1537,20 @@ 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=
|
||||
modernc.org/cc/v4 v4.26.5 h1:xM3bX7Mve6G8K8b+T11ReenJOT+BmVqQj0FY5T4+5Y4=
|
||||
modernc.org/cc/v4 v4.26.5/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.28.1 h1:wPKYn5EC/mYTqBO373jKjvX2n+3+aK7+sICCv4Fjy1A=
|
||||
modernc.org/ccgo/v4 v4.28.1/go.mod h1:uD+4RnfrVgE6ec9NGguUNdhqzNIeeomeXf6CL0GTE5Q=
|
||||
modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=
|
||||
modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.30.1 h1:4r4U1J6Fhj98NKfSjnPUN7Ze2c6MnAdL0hWw6+LrJpc=
|
||||
modernc.org/ccgo/v4 v4.30.1/go.mod h1:bIOeI1JL54Utlxn+LwrFyjCx2n2RDiYEaJVSrgdrRfM=
|
||||
modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA=
|
||||
modernc.org/fileutil v1.3.40/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/gc/v3 v3.1.1 h1:k8T3gkXWY9sEiytKhcgyiZ2L0DTyCQ/nvX+LoCljoRE=
|
||||
modernc.org/gc/v3 v3.1.1/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
|
||||
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.10 h1:yZkb3YeLx4oynyR+iUsXsybsX4Ubx7MQlSYEw4yj59A=
|
||||
modernc.org/libc v1.66.10/go.mod h1:8vGSEwvoUoltr4dlywvHqjtAqHBaw0j1jI7iFBTAr2I=
|
||||
modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI=
|
||||
modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE=
|
||||
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.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
|
||||
@@ -1557,8 +1559,8 @@ 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.43.0 h1:8YqiFx3G1VhHTXO2Q00bl1Wz9KhS9Q5okwfp9Y97VnA=
|
||||
modernc.org/sqlite v1.43.0/go.mod h1:+VkC6v3pLOAE0A0uVucQEcbVW0I5nHCeDaBf+DpsQT8=
|
||||
modernc.org/sqlite v1.44.3 h1:+39JvV/HWMcYslAwRxHb8067w+2zowvFOUrOWIy9PjY=
|
||||
modernc.org/sqlite v1.44.3/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA=
|
||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
|
||||
@@ -163,7 +163,8 @@ func cleanLicenseID(id string) string {
|
||||
return strings.ReplaceAll(cleanID, "-", "")
|
||||
}
|
||||
|
||||
// buildURLToLicenseMap creates a mapping from license URLs (from seeAlso fields) to license IDs
|
||||
// buildURLToLicenseMap creates a mapping from license URLs (from seeAlso fields) to license IDs.
|
||||
// URLs are stored without scheme (http:// or https://) so that a single lookup covers both.
|
||||
func buildURLToLicenseMap(result LicenseList) map[string]string {
|
||||
urlMap := make(map[string]string)
|
||||
|
||||
@@ -175,7 +176,7 @@ func buildURLToLicenseMap(result LicenseList) map[string]string {
|
||||
if replacement != nil {
|
||||
// Map deprecated license URLs to the replacement license
|
||||
for _, url := range l.SeeAlso {
|
||||
urlMap[url] = replacement.ID
|
||||
urlMap[stripScheme(url)] = replacement.ID
|
||||
}
|
||||
}
|
||||
continue
|
||||
@@ -183,9 +184,17 @@ func buildURLToLicenseMap(result LicenseList) map[string]string {
|
||||
|
||||
// Add URLs from non-deprecated licenses
|
||||
for _, url := range l.SeeAlso {
|
||||
urlMap[url] = l.ID
|
||||
urlMap[stripScheme(url)] = l.ID
|
||||
}
|
||||
}
|
||||
|
||||
return urlMap
|
||||
}
|
||||
|
||||
// stripScheme removes http:// or https:// prefix from a URL.
|
||||
// This allows a single map entry to match both schemes.
|
||||
func stripScheme(url string) string {
|
||||
url = strings.TrimPrefix(url, "https://")
|
||||
url = strings.TrimPrefix(url, "http://")
|
||||
return url
|
||||
}
|
||||
|
||||
@@ -41,10 +41,12 @@ 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
|
||||
// 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.
|
||||
// The scheme (http:// or https://) is stripped before lookup, so both schemes match.
|
||||
func LicenseByURL(url string) (LicenseInfo, bool) {
|
||||
url = strings.TrimSpace(url)
|
||||
url = stripScheme(url)
|
||||
if id, exists := urlToLicense[url]; exists {
|
||||
return LicenseInfo{
|
||||
ID: id,
|
||||
@@ -52,3 +54,11 @@ func LicenseByURL(url string) (LicenseInfo, bool) {
|
||||
}
|
||||
return LicenseInfo{}, false
|
||||
}
|
||||
|
||||
// stripScheme removes http:// or https:// prefix from a URL.
|
||||
// This allows a single map entry to match both schemes.
|
||||
func stripScheme(url string) string {
|
||||
url = strings.TrimPrefix(url, "https://")
|
||||
url = strings.TrimPrefix(url, "http://")
|
||||
return url
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -76,6 +76,96 @@ func TestLicenseByURL(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLicenseByURL_AlternateScheme(t *testing.T) {
|
||||
// Test that URLs work with alternate schemes (http ↔ https) even if only one is in the SPDX list
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
wantID string
|
||||
wantFound bool
|
||||
}{
|
||||
{
|
||||
name: "Apache URL with http when https is in list",
|
||||
url: "http://www.apache.org/licenses/LICENSE-2.0",
|
||||
wantID: "Apache-2.0",
|
||||
wantFound: true,
|
||||
},
|
||||
{
|
||||
name: "BSD-3-Clause with http when https is in list",
|
||||
url: "http://opensource.org/licenses/BSD-3-Clause",
|
||||
wantID: "BSD-3-Clause",
|
||||
wantFound: true,
|
||||
},
|
||||
{
|
||||
name: "Unknown URL with http still not found",
|
||||
url: "http://example.com/not-a-real-license",
|
||||
wantID: "",
|
||||
wantFound: false,
|
||||
},
|
||||
{
|
||||
name: "Unknown URL with https still not found",
|
||||
url: "https://example.com/not-a-real-license",
|
||||
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 && info.ID != tt.wantID {
|
||||
t.Errorf("LicenseByURL() ID = %v, want %v", info.ID, tt.wantID)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStripScheme(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "https scheme stripped",
|
||||
url: "https://example.com/license",
|
||||
want: "example.com/license",
|
||||
},
|
||||
{
|
||||
name: "http scheme stripped",
|
||||
url: "http://example.com/license",
|
||||
want: "example.com/license",
|
||||
},
|
||||
{
|
||||
name: "ftp scheme not stripped",
|
||||
url: "ftp://example.com/license",
|
||||
want: "ftp://example.com/license",
|
||||
},
|
||||
{
|
||||
name: "no scheme unchanged",
|
||||
url: "example.com/license",
|
||||
want: "example.com/license",
|
||||
},
|
||||
{
|
||||
name: "empty string unchanged",
|
||||
url: "",
|
||||
want: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := stripScheme(tt.url)
|
||||
if got != tt.want {
|
||||
t.Errorf("stripScheme() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -8,4 +8,4 @@ validate-schema:
|
||||
xmllint --noout --schema ./cyclonedx.xsd bom.xml
|
||||
|
||||
@echo "\nValidating CycloneDX JSON..."
|
||||
../../.tool/yajsv -s cyclonedx.json bom.json
|
||||
../../.tool/yajsv -s cyclonedx.json -r spdx.schema.json bom.json
|
||||
|
||||
@@ -5670,4 +5670,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,786 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "http://cyclonedx.org/schema/spdx.schema.json",
|
||||
"$comment": "v1.0-3.27.0",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"0BSD",
|
||||
"3D-Slicer-1.0",
|
||||
"AAL",
|
||||
"Abstyles",
|
||||
"AdaCore-doc",
|
||||
"Adobe-2006",
|
||||
"Adobe-Display-PostScript",
|
||||
"Adobe-Glyph",
|
||||
"Adobe-Utopia",
|
||||
"ADSL",
|
||||
"AFL-1.1",
|
||||
"AFL-1.2",
|
||||
"AFL-2.0",
|
||||
"AFL-2.1",
|
||||
"AFL-3.0",
|
||||
"Afmparse",
|
||||
"AGPL-1.0",
|
||||
"AGPL-1.0-only",
|
||||
"AGPL-1.0-or-later",
|
||||
"AGPL-3.0",
|
||||
"AGPL-3.0-only",
|
||||
"AGPL-3.0-or-later",
|
||||
"Aladdin",
|
||||
"AMD-newlib",
|
||||
"AMDPLPA",
|
||||
"AML",
|
||||
"AML-glslang",
|
||||
"AMPAS",
|
||||
"ANTLR-PD",
|
||||
"ANTLR-PD-fallback",
|
||||
"any-OSI",
|
||||
"any-OSI-perl-modules",
|
||||
"Apache-1.0",
|
||||
"Apache-1.1",
|
||||
"Apache-2.0",
|
||||
"APAFML",
|
||||
"APL-1.0",
|
||||
"App-s2p",
|
||||
"APSL-1.0",
|
||||
"APSL-1.1",
|
||||
"APSL-1.2",
|
||||
"APSL-2.0",
|
||||
"Arphic-1999",
|
||||
"Artistic-1.0",
|
||||
"Artistic-1.0-cl8",
|
||||
"Artistic-1.0-Perl",
|
||||
"Artistic-2.0",
|
||||
"Artistic-dist",
|
||||
"Aspell-RU",
|
||||
"ASWF-Digital-Assets-1.0",
|
||||
"ASWF-Digital-Assets-1.1",
|
||||
"Baekmuk",
|
||||
"Bahyph",
|
||||
"Barr",
|
||||
"bcrypt-Solar-Designer",
|
||||
"Beerware",
|
||||
"Bitstream-Charter",
|
||||
"Bitstream-Vera",
|
||||
"BitTorrent-1.0",
|
||||
"BitTorrent-1.1",
|
||||
"blessing",
|
||||
"BlueOak-1.0.0",
|
||||
"Boehm-GC",
|
||||
"Boehm-GC-without-fee",
|
||||
"Borceux",
|
||||
"Brian-Gladman-2-Clause",
|
||||
"Brian-Gladman-3-Clause",
|
||||
"BSD-1-Clause",
|
||||
"BSD-2-Clause",
|
||||
"BSD-2-Clause-Darwin",
|
||||
"BSD-2-Clause-first-lines",
|
||||
"BSD-2-Clause-FreeBSD",
|
||||
"BSD-2-Clause-NetBSD",
|
||||
"BSD-2-Clause-Patent",
|
||||
"BSD-2-Clause-pkgconf-disclaimer",
|
||||
"BSD-2-Clause-Views",
|
||||
"BSD-3-Clause",
|
||||
"BSD-3-Clause-acpica",
|
||||
"BSD-3-Clause-Attribution",
|
||||
"BSD-3-Clause-Clear",
|
||||
"BSD-3-Clause-flex",
|
||||
"BSD-3-Clause-HP",
|
||||
"BSD-3-Clause-LBNL",
|
||||
"BSD-3-Clause-Modification",
|
||||
"BSD-3-Clause-No-Military-License",
|
||||
"BSD-3-Clause-No-Nuclear-License",
|
||||
"BSD-3-Clause-No-Nuclear-License-2014",
|
||||
"BSD-3-Clause-No-Nuclear-Warranty",
|
||||
"BSD-3-Clause-Open-MPI",
|
||||
"BSD-3-Clause-Sun",
|
||||
"BSD-4-Clause",
|
||||
"BSD-4-Clause-Shortened",
|
||||
"BSD-4-Clause-UC",
|
||||
"BSD-4.3RENO",
|
||||
"BSD-4.3TAHOE",
|
||||
"BSD-Advertising-Acknowledgement",
|
||||
"BSD-Attribution-HPND-disclaimer",
|
||||
"BSD-Inferno-Nettverk",
|
||||
"BSD-Protection",
|
||||
"BSD-Source-beginning-file",
|
||||
"BSD-Source-Code",
|
||||
"BSD-Systemics",
|
||||
"BSD-Systemics-W3Works",
|
||||
"BSL-1.0",
|
||||
"BUSL-1.1",
|
||||
"bzip2-1.0.5",
|
||||
"bzip2-1.0.6",
|
||||
"C-UDA-1.0",
|
||||
"CAL-1.0",
|
||||
"CAL-1.0-Combined-Work-Exception",
|
||||
"Caldera",
|
||||
"Caldera-no-preamble",
|
||||
"Catharon",
|
||||
"CATOSL-1.1",
|
||||
"CC-BY-1.0",
|
||||
"CC-BY-2.0",
|
||||
"CC-BY-2.5",
|
||||
"CC-BY-2.5-AU",
|
||||
"CC-BY-3.0",
|
||||
"CC-BY-3.0-AT",
|
||||
"CC-BY-3.0-AU",
|
||||
"CC-BY-3.0-DE",
|
||||
"CC-BY-3.0-IGO",
|
||||
"CC-BY-3.0-NL",
|
||||
"CC-BY-3.0-US",
|
||||
"CC-BY-4.0",
|
||||
"CC-BY-NC-1.0",
|
||||
"CC-BY-NC-2.0",
|
||||
"CC-BY-NC-2.5",
|
||||
"CC-BY-NC-3.0",
|
||||
"CC-BY-NC-3.0-DE",
|
||||
"CC-BY-NC-4.0",
|
||||
"CC-BY-NC-ND-1.0",
|
||||
"CC-BY-NC-ND-2.0",
|
||||
"CC-BY-NC-ND-2.5",
|
||||
"CC-BY-NC-ND-3.0",
|
||||
"CC-BY-NC-ND-3.0-DE",
|
||||
"CC-BY-NC-ND-3.0-IGO",
|
||||
"CC-BY-NC-ND-4.0",
|
||||
"CC-BY-NC-SA-1.0",
|
||||
"CC-BY-NC-SA-2.0",
|
||||
"CC-BY-NC-SA-2.0-DE",
|
||||
"CC-BY-NC-SA-2.0-FR",
|
||||
"CC-BY-NC-SA-2.0-UK",
|
||||
"CC-BY-NC-SA-2.5",
|
||||
"CC-BY-NC-SA-3.0",
|
||||
"CC-BY-NC-SA-3.0-DE",
|
||||
"CC-BY-NC-SA-3.0-IGO",
|
||||
"CC-BY-NC-SA-4.0",
|
||||
"CC-BY-ND-1.0",
|
||||
"CC-BY-ND-2.0",
|
||||
"CC-BY-ND-2.5",
|
||||
"CC-BY-ND-3.0",
|
||||
"CC-BY-ND-3.0-DE",
|
||||
"CC-BY-ND-4.0",
|
||||
"CC-BY-SA-1.0",
|
||||
"CC-BY-SA-2.0",
|
||||
"CC-BY-SA-2.0-UK",
|
||||
"CC-BY-SA-2.1-JP",
|
||||
"CC-BY-SA-2.5",
|
||||
"CC-BY-SA-3.0",
|
||||
"CC-BY-SA-3.0-AT",
|
||||
"CC-BY-SA-3.0-DE",
|
||||
"CC-BY-SA-3.0-IGO",
|
||||
"CC-BY-SA-4.0",
|
||||
"CC-PDDC",
|
||||
"CC-PDM-1.0",
|
||||
"CC-SA-1.0",
|
||||
"CC0-1.0",
|
||||
"CDDL-1.0",
|
||||
"CDDL-1.1",
|
||||
"CDL-1.0",
|
||||
"CDLA-Permissive-1.0",
|
||||
"CDLA-Permissive-2.0",
|
||||
"CDLA-Sharing-1.0",
|
||||
"CECILL-1.0",
|
||||
"CECILL-1.1",
|
||||
"CECILL-2.0",
|
||||
"CECILL-2.1",
|
||||
"CECILL-B",
|
||||
"CECILL-C",
|
||||
"CERN-OHL-1.1",
|
||||
"CERN-OHL-1.2",
|
||||
"CERN-OHL-P-2.0",
|
||||
"CERN-OHL-S-2.0",
|
||||
"CERN-OHL-W-2.0",
|
||||
"CFITSIO",
|
||||
"check-cvs",
|
||||
"checkmk",
|
||||
"ClArtistic",
|
||||
"Clips",
|
||||
"CMU-Mach",
|
||||
"CMU-Mach-nodoc",
|
||||
"CNRI-Jython",
|
||||
"CNRI-Python",
|
||||
"CNRI-Python-GPL-Compatible",
|
||||
"COIL-1.0",
|
||||
"Community-Spec-1.0",
|
||||
"Condor-1.1",
|
||||
"copyleft-next-0.3.0",
|
||||
"copyleft-next-0.3.1",
|
||||
"Cornell-Lossless-JPEG",
|
||||
"CPAL-1.0",
|
||||
"CPL-1.0",
|
||||
"CPOL-1.02",
|
||||
"Cronyx",
|
||||
"Crossword",
|
||||
"CryptoSwift",
|
||||
"CrystalStacker",
|
||||
"CUA-OPL-1.0",
|
||||
"Cube",
|
||||
"curl",
|
||||
"cve-tou",
|
||||
"D-FSL-1.0",
|
||||
"DEC-3-Clause",
|
||||
"diffmark",
|
||||
"DL-DE-BY-2.0",
|
||||
"DL-DE-ZERO-2.0",
|
||||
"DOC",
|
||||
"DocBook-DTD",
|
||||
"DocBook-Schema",
|
||||
"DocBook-Stylesheet",
|
||||
"DocBook-XML",
|
||||
"Dotseqn",
|
||||
"DRL-1.0",
|
||||
"DRL-1.1",
|
||||
"DSDP",
|
||||
"dtoa",
|
||||
"dvipdfm",
|
||||
"ECL-1.0",
|
||||
"ECL-2.0",
|
||||
"eCos-2.0",
|
||||
"EFL-1.0",
|
||||
"EFL-2.0",
|
||||
"eGenix",
|
||||
"Elastic-2.0",
|
||||
"Entessa",
|
||||
"EPICS",
|
||||
"EPL-1.0",
|
||||
"EPL-2.0",
|
||||
"ErlPL-1.1",
|
||||
"etalab-2.0",
|
||||
"EUDatagrid",
|
||||
"EUPL-1.0",
|
||||
"EUPL-1.1",
|
||||
"EUPL-1.2",
|
||||
"Eurosym",
|
||||
"Fair",
|
||||
"FBM",
|
||||
"FDK-AAC",
|
||||
"Ferguson-Twofish",
|
||||
"Frameworx-1.0",
|
||||
"FreeBSD-DOC",
|
||||
"FreeImage",
|
||||
"FSFAP",
|
||||
"FSFAP-no-warranty-disclaimer",
|
||||
"FSFUL",
|
||||
"FSFULLR",
|
||||
"FSFULLRSD",
|
||||
"FSFULLRWD",
|
||||
"FSL-1.1-ALv2",
|
||||
"FSL-1.1-MIT",
|
||||
"FTL",
|
||||
"Furuseth",
|
||||
"fwlw",
|
||||
"Game-Programming-Gems",
|
||||
"GCR-docs",
|
||||
"GD",
|
||||
"generic-xts",
|
||||
"GFDL-1.1",
|
||||
"GFDL-1.1-invariants-only",
|
||||
"GFDL-1.1-invariants-or-later",
|
||||
"GFDL-1.1-no-invariants-only",
|
||||
"GFDL-1.1-no-invariants-or-later",
|
||||
"GFDL-1.1-only",
|
||||
"GFDL-1.1-or-later",
|
||||
"GFDL-1.2",
|
||||
"GFDL-1.2-invariants-only",
|
||||
"GFDL-1.2-invariants-or-later",
|
||||
"GFDL-1.2-no-invariants-only",
|
||||
"GFDL-1.2-no-invariants-or-later",
|
||||
"GFDL-1.2-only",
|
||||
"GFDL-1.2-or-later",
|
||||
"GFDL-1.3",
|
||||
"GFDL-1.3-invariants-only",
|
||||
"GFDL-1.3-invariants-or-later",
|
||||
"GFDL-1.3-no-invariants-only",
|
||||
"GFDL-1.3-no-invariants-or-later",
|
||||
"GFDL-1.3-only",
|
||||
"GFDL-1.3-or-later",
|
||||
"Giftware",
|
||||
"GL2PS",
|
||||
"Glide",
|
||||
"Glulxe",
|
||||
"GLWTPL",
|
||||
"gnuplot",
|
||||
"GPL-1.0",
|
||||
"GPL-1.0+",
|
||||
"GPL-1.0-only",
|
||||
"GPL-1.0-or-later",
|
||||
"GPL-2.0",
|
||||
"GPL-2.0+",
|
||||
"GPL-2.0-only",
|
||||
"GPL-2.0-or-later",
|
||||
"GPL-2.0-with-autoconf-exception",
|
||||
"GPL-2.0-with-bison-exception",
|
||||
"GPL-2.0-with-classpath-exception",
|
||||
"GPL-2.0-with-font-exception",
|
||||
"GPL-2.0-with-GCC-exception",
|
||||
"GPL-3.0",
|
||||
"GPL-3.0+",
|
||||
"GPL-3.0-only",
|
||||
"GPL-3.0-or-later",
|
||||
"GPL-3.0-with-autoconf-exception",
|
||||
"GPL-3.0-with-GCC-exception",
|
||||
"Graphics-Gems",
|
||||
"gSOAP-1.3b",
|
||||
"gtkbook",
|
||||
"Gutmann",
|
||||
"HaskellReport",
|
||||
"HDF5",
|
||||
"hdparm",
|
||||
"HIDAPI",
|
||||
"Hippocratic-2.1",
|
||||
"HP-1986",
|
||||
"HP-1989",
|
||||
"HPND",
|
||||
"HPND-DEC",
|
||||
"HPND-doc",
|
||||
"HPND-doc-sell",
|
||||
"HPND-export-US",
|
||||
"HPND-export-US-acknowledgement",
|
||||
"HPND-export-US-modify",
|
||||
"HPND-export2-US",
|
||||
"HPND-Fenneberg-Livingston",
|
||||
"HPND-INRIA-IMAG",
|
||||
"HPND-Intel",
|
||||
"HPND-Kevlin-Henney",
|
||||
"HPND-Markus-Kuhn",
|
||||
"HPND-merchantability-variant",
|
||||
"HPND-MIT-disclaimer",
|
||||
"HPND-Netrek",
|
||||
"HPND-Pbmplus",
|
||||
"HPND-sell-MIT-disclaimer-xserver",
|
||||
"HPND-sell-regexpr",
|
||||
"HPND-sell-variant",
|
||||
"HPND-sell-variant-MIT-disclaimer",
|
||||
"HPND-sell-variant-MIT-disclaimer-rev",
|
||||
"HPND-UC",
|
||||
"HPND-UC-export-US",
|
||||
"HTMLTIDY",
|
||||
"IBM-pibs",
|
||||
"ICU",
|
||||
"IEC-Code-Components-EULA",
|
||||
"IJG",
|
||||
"IJG-short",
|
||||
"ImageMagick",
|
||||
"iMatix",
|
||||
"Imlib2",
|
||||
"Info-ZIP",
|
||||
"Inner-Net-2.0",
|
||||
"InnoSetup",
|
||||
"Intel",
|
||||
"Intel-ACPI",
|
||||
"Interbase-1.0",
|
||||
"IPA",
|
||||
"IPL-1.0",
|
||||
"ISC",
|
||||
"ISC-Veillard",
|
||||
"Jam",
|
||||
"JasPer-2.0",
|
||||
"jove",
|
||||
"JPL-image",
|
||||
"JPNIC",
|
||||
"JSON",
|
||||
"Kastrup",
|
||||
"Kazlib",
|
||||
"Knuth-CTAN",
|
||||
"LAL-1.2",
|
||||
"LAL-1.3",
|
||||
"Latex2e",
|
||||
"Latex2e-translated-notice",
|
||||
"Leptonica",
|
||||
"LGPL-2.0",
|
||||
"LGPL-2.0+",
|
||||
"LGPL-2.0-only",
|
||||
"LGPL-2.0-or-later",
|
||||
"LGPL-2.1",
|
||||
"LGPL-2.1+",
|
||||
"LGPL-2.1-only",
|
||||
"LGPL-2.1-or-later",
|
||||
"LGPL-3.0",
|
||||
"LGPL-3.0+",
|
||||
"LGPL-3.0-only",
|
||||
"LGPL-3.0-or-later",
|
||||
"LGPLLR",
|
||||
"Libpng",
|
||||
"libpng-1.6.35",
|
||||
"libpng-2.0",
|
||||
"libselinux-1.0",
|
||||
"libtiff",
|
||||
"libutil-David-Nugent",
|
||||
"LiLiQ-P-1.1",
|
||||
"LiLiQ-R-1.1",
|
||||
"LiLiQ-Rplus-1.1",
|
||||
"Linux-man-pages-1-para",
|
||||
"Linux-man-pages-copyleft",
|
||||
"Linux-man-pages-copyleft-2-para",
|
||||
"Linux-man-pages-copyleft-var",
|
||||
"Linux-OpenIB",
|
||||
"LOOP",
|
||||
"LPD-document",
|
||||
"LPL-1.0",
|
||||
"LPL-1.02",
|
||||
"LPPL-1.0",
|
||||
"LPPL-1.1",
|
||||
"LPPL-1.2",
|
||||
"LPPL-1.3a",
|
||||
"LPPL-1.3c",
|
||||
"lsof",
|
||||
"Lucida-Bitmap-Fonts",
|
||||
"LZMA-SDK-9.11-to-9.20",
|
||||
"LZMA-SDK-9.22",
|
||||
"Mackerras-3-Clause",
|
||||
"Mackerras-3-Clause-acknowledgment",
|
||||
"magaz",
|
||||
"mailprio",
|
||||
"MakeIndex",
|
||||
"man2html",
|
||||
"Martin-Birgmeier",
|
||||
"McPhee-slideshow",
|
||||
"metamail",
|
||||
"Minpack",
|
||||
"MIPS",
|
||||
"MirOS",
|
||||
"MIT",
|
||||
"MIT-0",
|
||||
"MIT-advertising",
|
||||
"MIT-Click",
|
||||
"MIT-CMU",
|
||||
"MIT-enna",
|
||||
"MIT-feh",
|
||||
"MIT-Festival",
|
||||
"MIT-Khronos-old",
|
||||
"MIT-Modern-Variant",
|
||||
"MIT-open-group",
|
||||
"MIT-testregex",
|
||||
"MIT-Wu",
|
||||
"MITNFA",
|
||||
"MMIXware",
|
||||
"Motosoto",
|
||||
"MPEG-SSG",
|
||||
"mpi-permissive",
|
||||
"mpich2",
|
||||
"MPL-1.0",
|
||||
"MPL-1.1",
|
||||
"MPL-2.0",
|
||||
"MPL-2.0-no-copyleft-exception",
|
||||
"mplus",
|
||||
"MS-LPL",
|
||||
"MS-PL",
|
||||
"MS-RL",
|
||||
"MTLL",
|
||||
"MulanPSL-1.0",
|
||||
"MulanPSL-2.0",
|
||||
"Multics",
|
||||
"Mup",
|
||||
"NAIST-2003",
|
||||
"NASA-1.3",
|
||||
"Naumen",
|
||||
"NBPL-1.0",
|
||||
"NCBI-PD",
|
||||
"NCGL-UK-2.0",
|
||||
"NCL",
|
||||
"NCSA",
|
||||
"Net-SNMP",
|
||||
"NetCDF",
|
||||
"Newsletr",
|
||||
"NGPL",
|
||||
"ngrep",
|
||||
"NICTA-1.0",
|
||||
"NIST-PD",
|
||||
"NIST-PD-fallback",
|
||||
"NIST-Software",
|
||||
"NLOD-1.0",
|
||||
"NLOD-2.0",
|
||||
"NLPL",
|
||||
"Nokia",
|
||||
"NOSL",
|
||||
"Noweb",
|
||||
"NPL-1.0",
|
||||
"NPL-1.1",
|
||||
"NPOSL-3.0",
|
||||
"NRL",
|
||||
"NTIA-PD",
|
||||
"NTP",
|
||||
"NTP-0",
|
||||
"Nunit",
|
||||
"O-UDA-1.0",
|
||||
"OAR",
|
||||
"OCCT-PL",
|
||||
"OCLC-2.0",
|
||||
"ODbL-1.0",
|
||||
"ODC-By-1.0",
|
||||
"OFFIS",
|
||||
"OFL-1.0",
|
||||
"OFL-1.0-no-RFN",
|
||||
"OFL-1.0-RFN",
|
||||
"OFL-1.1",
|
||||
"OFL-1.1-no-RFN",
|
||||
"OFL-1.1-RFN",
|
||||
"OGC-1.0",
|
||||
"OGDL-Taiwan-1.0",
|
||||
"OGL-Canada-2.0",
|
||||
"OGL-UK-1.0",
|
||||
"OGL-UK-2.0",
|
||||
"OGL-UK-3.0",
|
||||
"OGTSL",
|
||||
"OLDAP-1.1",
|
||||
"OLDAP-1.2",
|
||||
"OLDAP-1.3",
|
||||
"OLDAP-1.4",
|
||||
"OLDAP-2.0",
|
||||
"OLDAP-2.0.1",
|
||||
"OLDAP-2.1",
|
||||
"OLDAP-2.2",
|
||||
"OLDAP-2.2.1",
|
||||
"OLDAP-2.2.2",
|
||||
"OLDAP-2.3",
|
||||
"OLDAP-2.4",
|
||||
"OLDAP-2.5",
|
||||
"OLDAP-2.6",
|
||||
"OLDAP-2.7",
|
||||
"OLDAP-2.8",
|
||||
"OLFL-1.3",
|
||||
"OML",
|
||||
"OpenPBS-2.3",
|
||||
"OpenSSL",
|
||||
"OpenSSL-standalone",
|
||||
"OpenVision",
|
||||
"OPL-1.0",
|
||||
"OPL-UK-3.0",
|
||||
"OPUBL-1.0",
|
||||
"OSET-PL-2.1",
|
||||
"OSL-1.0",
|
||||
"OSL-1.1",
|
||||
"OSL-2.0",
|
||||
"OSL-2.1",
|
||||
"OSL-3.0",
|
||||
"PADL",
|
||||
"Parity-6.0.0",
|
||||
"Parity-7.0.0",
|
||||
"PDDL-1.0",
|
||||
"PHP-3.0",
|
||||
"PHP-3.01",
|
||||
"Pixar",
|
||||
"pkgconf",
|
||||
"Plexus",
|
||||
"pnmstitch",
|
||||
"PolyForm-Noncommercial-1.0.0",
|
||||
"PolyForm-Small-Business-1.0.0",
|
||||
"PostgreSQL",
|
||||
"PPL",
|
||||
"PSF-2.0",
|
||||
"psfrag",
|
||||
"psutils",
|
||||
"Python-2.0",
|
||||
"Python-2.0.1",
|
||||
"python-ldap",
|
||||
"Qhull",
|
||||
"QPL-1.0",
|
||||
"QPL-1.0-INRIA-2004",
|
||||
"radvd",
|
||||
"Rdisc",
|
||||
"RHeCos-1.1",
|
||||
"RPL-1.1",
|
||||
"RPL-1.5",
|
||||
"RPSL-1.0",
|
||||
"RSA-MD",
|
||||
"RSCPL",
|
||||
"Ruby",
|
||||
"Ruby-pty",
|
||||
"SAX-PD",
|
||||
"SAX-PD-2.0",
|
||||
"Saxpath",
|
||||
"SCEA",
|
||||
"SchemeReport",
|
||||
"Sendmail",
|
||||
"Sendmail-8.23",
|
||||
"Sendmail-Open-Source-1.1",
|
||||
"SGI-B-1.0",
|
||||
"SGI-B-1.1",
|
||||
"SGI-B-2.0",
|
||||
"SGI-OpenGL",
|
||||
"SGP4",
|
||||
"SHL-0.5",
|
||||
"SHL-0.51",
|
||||
"SimPL-2.0",
|
||||
"SISSL",
|
||||
"SISSL-1.2",
|
||||
"SL",
|
||||
"Sleepycat",
|
||||
"SMAIL-GPL",
|
||||
"SMLNJ",
|
||||
"SMPPL",
|
||||
"SNIA",
|
||||
"snprintf",
|
||||
"SOFA",
|
||||
"softSurfer",
|
||||
"Soundex",
|
||||
"Spencer-86",
|
||||
"Spencer-94",
|
||||
"Spencer-99",
|
||||
"SPL-1.0",
|
||||
"ssh-keyscan",
|
||||
"SSH-OpenSSH",
|
||||
"SSH-short",
|
||||
"SSLeay-standalone",
|
||||
"SSPL-1.0",
|
||||
"StandardML-NJ",
|
||||
"SugarCRM-1.1.3",
|
||||
"SUL-1.0",
|
||||
"Sun-PPP",
|
||||
"Sun-PPP-2000",
|
||||
"SunPro",
|
||||
"SWL",
|
||||
"swrule",
|
||||
"Symlinks",
|
||||
"TAPR-OHL-1.0",
|
||||
"TCL",
|
||||
"TCP-wrappers",
|
||||
"TermReadKey",
|
||||
"TGPPL-1.0",
|
||||
"ThirdEye",
|
||||
"threeparttable",
|
||||
"TMate",
|
||||
"TORQUE-1.1",
|
||||
"TOSL",
|
||||
"TPDL",
|
||||
"TPL-1.0",
|
||||
"TrustedQSL",
|
||||
"TTWL",
|
||||
"TTYP0",
|
||||
"TU-Berlin-1.0",
|
||||
"TU-Berlin-2.0",
|
||||
"Ubuntu-font-1.0",
|
||||
"UCAR",
|
||||
"UCL-1.0",
|
||||
"ulem",
|
||||
"UMich-Merit",
|
||||
"Unicode-3.0",
|
||||
"Unicode-DFS-2015",
|
||||
"Unicode-DFS-2016",
|
||||
"Unicode-TOU",
|
||||
"UnixCrypt",
|
||||
"Unlicense",
|
||||
"Unlicense-libtelnet",
|
||||
"Unlicense-libwhirlpool",
|
||||
"UPL-1.0",
|
||||
"URT-RLE",
|
||||
"Vim",
|
||||
"VOSTROM",
|
||||
"VSL-1.0",
|
||||
"W3C",
|
||||
"W3C-19980720",
|
||||
"W3C-20150513",
|
||||
"w3m",
|
||||
"Watcom-1.0",
|
||||
"Widget-Workshop",
|
||||
"Wsuipa",
|
||||
"WTFPL",
|
||||
"wwl",
|
||||
"wxWindows",
|
||||
"X11",
|
||||
"X11-distribute-modifications-variant",
|
||||
"X11-swapped",
|
||||
"Xdebug-1.03",
|
||||
"Xerox",
|
||||
"Xfig",
|
||||
"XFree86-1.1",
|
||||
"xinetd",
|
||||
"xkeyboard-config-Zinoviev",
|
||||
"xlock",
|
||||
"Xnet",
|
||||
"xpp",
|
||||
"XSkat",
|
||||
"xzoom",
|
||||
"YPL-1.0",
|
||||
"YPL-1.1",
|
||||
"Zed",
|
||||
"Zeeff",
|
||||
"Zend-2.0",
|
||||
"Zimbra-1.3",
|
||||
"Zimbra-1.4",
|
||||
"Zlib",
|
||||
"zlib-acknowledgement",
|
||||
"ZPL-1.1",
|
||||
"ZPL-2.0",
|
||||
"ZPL-2.1",
|
||||
"389-exception",
|
||||
"Asterisk-exception",
|
||||
"Asterisk-linking-protocols-exception",
|
||||
"Autoconf-exception-2.0",
|
||||
"Autoconf-exception-3.0",
|
||||
"Autoconf-exception-generic",
|
||||
"Autoconf-exception-generic-3.0",
|
||||
"Autoconf-exception-macro",
|
||||
"Bison-exception-1.24",
|
||||
"Bison-exception-2.2",
|
||||
"Bootloader-exception",
|
||||
"CGAL-linking-exception",
|
||||
"Classpath-exception-2.0",
|
||||
"CLISP-exception-2.0",
|
||||
"cryptsetup-OpenSSL-exception",
|
||||
"Digia-Qt-LGPL-exception-1.1",
|
||||
"DigiRule-FOSS-exception",
|
||||
"eCos-exception-2.0",
|
||||
"erlang-otp-linking-exception",
|
||||
"Fawkes-Runtime-exception",
|
||||
"FLTK-exception",
|
||||
"fmt-exception",
|
||||
"Font-exception-2.0",
|
||||
"freertos-exception-2.0",
|
||||
"GCC-exception-2.0",
|
||||
"GCC-exception-2.0-note",
|
||||
"GCC-exception-3.1",
|
||||
"Gmsh-exception",
|
||||
"GNAT-exception",
|
||||
"GNOME-examples-exception",
|
||||
"GNU-compiler-exception",
|
||||
"gnu-javamail-exception",
|
||||
"GPL-3.0-389-ds-base-exception",
|
||||
"GPL-3.0-interface-exception",
|
||||
"GPL-3.0-linking-exception",
|
||||
"GPL-3.0-linking-source-exception",
|
||||
"GPL-CC-1.0",
|
||||
"GStreamer-exception-2005",
|
||||
"GStreamer-exception-2008",
|
||||
"harbour-exception",
|
||||
"i2p-gpl-java-exception",
|
||||
"Independent-modules-exception",
|
||||
"KiCad-libraries-exception",
|
||||
"LGPL-3.0-linking-exception",
|
||||
"libpri-OpenH323-exception",
|
||||
"Libtool-exception",
|
||||
"Linux-syscall-note",
|
||||
"LLGPL",
|
||||
"LLVM-exception",
|
||||
"LZMA-exception",
|
||||
"mif-exception",
|
||||
"mxml-exception",
|
||||
"Nokia-Qt-exception-1.1",
|
||||
"OCaml-LGPL-linking-exception",
|
||||
"OCCT-exception-1.0",
|
||||
"OpenJDK-assembly-exception-1.0",
|
||||
"openvpn-openssl-exception",
|
||||
"PCRE2-exception",
|
||||
"polyparse-exception",
|
||||
"PS-or-PDF-font-exception-20170817",
|
||||
"QPL-1.0-INRIA-2004-exception",
|
||||
"Qt-GPL-exception-1.0",
|
||||
"Qt-LGPL-exception-1.1",
|
||||
"Qwt-exception-1.0",
|
||||
"romic-exception",
|
||||
"RRDtool-FLOSS-exception-2.0",
|
||||
"SANE-exception",
|
||||
"SHL-2.0",
|
||||
"SHL-2.1",
|
||||
"stunnel-exception",
|
||||
"SWI-exception",
|
||||
"Swift-exception",
|
||||
"Texinfo-exception",
|
||||
"u-boot-exception-2.0",
|
||||
"UBDL-exception",
|
||||
"Universal-FOSS-exception-1.0",
|
||||
"vsftpd-openssl-exception",
|
||||
"WxWindows-exception-3.1",
|
||||
"x11vnc-openssl-exception"
|
||||
]
|
||||
}
|
||||
+106
-1
@@ -2,7 +2,7 @@
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
elementFormDefault="qualified"
|
||||
targetNamespace="http://cyclonedx.org/schema/spdx"
|
||||
version="1.0-3.26.0">
|
||||
version="1.0-3.27.0">
|
||||
|
||||
<xs:simpleType name="licenseId">
|
||||
<xs:restriction base="xs:string">
|
||||
@@ -242,6 +242,16 @@
|
||||
<xs:documentation>Artistic License 2.0</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="Artistic-dist">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Artistic License 1.0 (dist)</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="Aspell-RU">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Aspell Russian License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="ASWF-Digital-Assets-1.0">
|
||||
<xs:annotation>
|
||||
<xs:documentation>ASWF Digital Assets License version 1.0</xs:documentation>
|
||||
@@ -367,6 +377,11 @@
|
||||
<xs:documentation>BSD-2-Clause Plus Patent License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="BSD-2-Clause-pkgconf-disclaimer">
|
||||
<xs:annotation>
|
||||
<xs:documentation>BSD 2-Clause pkgconf disclaimer variant</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="BSD-2-Clause-Views">
|
||||
<xs:annotation>
|
||||
<xs:documentation>BSD 2-Clause with views sentence</xs:documentation>
|
||||
@@ -1027,6 +1042,11 @@
|
||||
<xs:documentation>Crossword License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="CryptoSwift">
|
||||
<xs:annotation>
|
||||
<xs:documentation>CryptoSwift License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="CrystalStacker">
|
||||
<xs:annotation>
|
||||
<xs:documentation>CrystalStacker License</xs:documentation>
|
||||
@@ -1082,6 +1102,11 @@
|
||||
<xs:documentation>DOC License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="DocBook-DTD">
|
||||
<xs:annotation>
|
||||
<xs:documentation>DocBook DTD License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="DocBook-Schema">
|
||||
<xs:annotation>
|
||||
<xs:documentation>DocBook Schema License</xs:documentation>
|
||||
@@ -1272,11 +1297,26 @@
|
||||
<xs:documentation>FSF Unlimited License (with License Retention)</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="FSFULLRSD">
|
||||
<xs:annotation>
|
||||
<xs:documentation>FSF Unlimited License (with License Retention and Short Disclaimer)</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="FSFULLRWD">
|
||||
<xs:annotation>
|
||||
<xs:documentation>FSF Unlimited License (With License Retention and Warranty Disclaimer)</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="FSL-1.1-ALv2">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Functional Source License, Version 1.1, ALv2 Future License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="FSL-1.1-MIT">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Functional Source License, Version 1.1, MIT Future License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="FTL">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Freetype Project License</xs:documentation>
|
||||
@@ -1292,6 +1332,11 @@
|
||||
<xs:documentation>fwlw License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="Game-Programming-Gems">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Game Programming Gems License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="GCR-docs">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Gnome GCR Documentation License</xs:documentation>
|
||||
@@ -1562,6 +1607,11 @@
|
||||
<xs:documentation>Haskell Language Report License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="HDF5">
|
||||
<xs:annotation>
|
||||
<xs:documentation>HDF5 License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="hdparm">
|
||||
<xs:annotation>
|
||||
<xs:documentation>hdparm License</xs:documentation>
|
||||
@@ -1812,6 +1862,11 @@
|
||||
<xs:documentation>JasPer License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="jove">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Jove License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="JPL-image">
|
||||
<xs:annotation>
|
||||
<xs:documentation>JPL Image Use Policy</xs:documentation>
|
||||
@@ -1937,6 +1992,11 @@
|
||||
<xs:documentation>libpng License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="libpng-1.6.35">
|
||||
<xs:annotation>
|
||||
<xs:documentation>PNG Reference Library License v1 (for libpng 0.5 through 1.6.35)</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="libpng-2.0">
|
||||
<xs:annotation>
|
||||
<xs:documentation>PNG Reference Library version 2</xs:documentation>
|
||||
@@ -2087,6 +2147,11 @@
|
||||
<xs:documentation>MakeIndex License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="man2html">
|
||||
<xs:annotation>
|
||||
<xs:documentation>man2html License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="Martin-Birgmeier">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Martin Birgmeier License</xs:documentation>
|
||||
@@ -2337,6 +2402,11 @@
|
||||
<xs:documentation>Nethack General Public License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="ngrep">
|
||||
<xs:annotation>
|
||||
<xs:documentation>ngrep License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="NICTA-1.0">
|
||||
<xs:annotation>
|
||||
<xs:documentation>NICTA Public Software License, Version 1.0</xs:documentation>
|
||||
@@ -2407,6 +2477,11 @@
|
||||
<xs:documentation>NRL License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="NTIA-PD">
|
||||
<xs:annotation>
|
||||
<xs:documentation>NTIA Public Domain Notice</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="NTP">
|
||||
<xs:annotation>
|
||||
<xs:documentation>NTP License</xs:documentation>
|
||||
@@ -2967,6 +3042,11 @@
|
||||
<xs:documentation>snprintf License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="SOFA">
|
||||
<xs:annotation>
|
||||
<xs:documentation>SOFA Software License</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="softSurfer">
|
||||
<xs:annotation>
|
||||
<xs:documentation>softSurfer License</xs:documentation>
|
||||
@@ -3032,6 +3112,11 @@
|
||||
<xs:documentation>SugarCRM Public License v1.1.3</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="SUL-1.0">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Sustainable Use License v1.0</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="Sun-PPP">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Sun PPP License</xs:documentation>
|
||||
@@ -3202,6 +3287,16 @@
|
||||
<xs:documentation>The Unlicense</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="Unlicense-libtelnet">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Unlicense - libtelnet variant</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="Unlicense-libwhirlpool">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Unlicense - libwhirlpool variant</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="UPL-1.0">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Universal Permissive License v1.0</xs:documentation>
|
||||
@@ -3483,6 +3578,11 @@
|
||||
<xs:documentation>cryptsetup OpenSSL exception</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="Digia-Qt-LGPL-exception-1.1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Digia Qt LGPL Exception version 1.1</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="DigiRule-FOSS-exception">
|
||||
<xs:annotation>
|
||||
<xs:documentation>DigiRule FOSS License Exception</xs:documentation>
|
||||
@@ -3693,6 +3793,11 @@
|
||||
<xs:documentation>PCRE2 exception</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="polyparse-exception">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Polyparse Exception</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="PS-or-PDF-font-exception-20170817">
|
||||
<xs:annotation>
|
||||
<xs:documentation>PS/PDF font exception (2017-08-17)</xs:documentation>
|
||||
|
||||
@@ -54,6 +54,12 @@ var identityFiles = []parseEntry{
|
||||
// /////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
// after a parser function returns a Release, it may have incomplete information; supplementers can be used to
|
||||
// fill in missing details based on other files present in the filesystem
|
||||
var supplementers = []func(file.Resolver, *Release){
|
||||
supplementDebianVersion,
|
||||
}
|
||||
|
||||
// IdentifyRelease parses distro-specific files to discover and raise linux distribution release details.
|
||||
func IdentifyRelease(resolver file.Resolver) *Release {
|
||||
logger := log.Nested("operation", "identify-release")
|
||||
@@ -67,6 +73,9 @@ func IdentifyRelease(resolver file.Resolver) *Release {
|
||||
for _, location := range locations {
|
||||
release := tryParseReleaseInfo(resolver, location, logger, entry)
|
||||
if release != nil {
|
||||
for _, supplementer := range supplementers {
|
||||
supplementer(resolver, release)
|
||||
}
|
||||
return release
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ func TestIdentifyRelease(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
fixture: "test-fixtures/os/debian",
|
||||
fixture: "test-fixtures/os/debian/from-os-release",
|
||||
release: &Release{
|
||||
PrettyName: "Debian GNU/Linux 8 (jessie)",
|
||||
Name: "Debian GNU/Linux",
|
||||
@@ -87,6 +87,20 @@ func TestIdentifyRelease(t *testing.T) {
|
||||
BugReportURL: "https://bugs.debian.org/",
|
||||
},
|
||||
},
|
||||
{
|
||||
fixture: "test-fixtures/os/debian/from-debian_version",
|
||||
release: &Release{
|
||||
PrettyName: "Distroless",
|
||||
Name: "Debian GNU/Linux",
|
||||
ID: "debian",
|
||||
IDLike: nil,
|
||||
Version: "10.8",
|
||||
VersionID: "10.8",
|
||||
HomeURL: "https://github.com/GoogleContainerTools/distroless",
|
||||
SupportURL: "https://github.com/GoogleContainerTools/distroless/blob/master/README.md",
|
||||
BugReportURL: "https://github.com/GoogleContainerTools/distroless/issues/new",
|
||||
},
|
||||
},
|
||||
{
|
||||
fixture: "test-fixtures/os/fedora",
|
||||
release: &Release{
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package linux
|
||||
|
||||
import (
|
||||
"io"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
)
|
||||
|
||||
func supplementDebianVersion(resolver file.Resolver, release *Release) {
|
||||
// we're only looking for version information for debian when none is present in /etc/os-release
|
||||
if release.Version != "" || release.VersionID != "" || !strings.EqualFold(release.ID, "debian") {
|
||||
return
|
||||
}
|
||||
// if we have a debian release with no version, look for a debian_version
|
||||
locations, err := resolver.FilesByGlob("/etc/debian_version")
|
||||
if err != nil {
|
||||
log.Debugf("error reading /etc/debian_version: %v", err)
|
||||
return
|
||||
}
|
||||
for _, location := range locations {
|
||||
version := readDebianVersionFile(resolver, location)
|
||||
if version != "" {
|
||||
release.Version = version
|
||||
release.VersionID = version
|
||||
return // keep the first result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func readDebianVersionFile(resolver file.Resolver, location file.Location) string {
|
||||
rdr, err := resolver.FileContentsByLocation(location)
|
||||
if err != nil {
|
||||
log.Debugf("error getting contents for %s: %v", location.RealPath, err)
|
||||
return ""
|
||||
}
|
||||
defer internal.CloseAndLogError(rdr, location.RealPath)
|
||||
contents, err := io.ReadAll(rdr)
|
||||
if err != nil {
|
||||
log.Debugf("error reading %s: %v", location.RealPath, err)
|
||||
return ""
|
||||
}
|
||||
version := strings.TrimSpace(string(contents))
|
||||
if regexp.MustCompile(`^\d+(?:\.\d+)?$`).MatchString(version) {
|
||||
return version
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
10.8
|
||||
@@ -0,0 +1,6 @@
|
||||
PRETTY_NAME="Distroless"
|
||||
NAME="Debian GNU/Linux"
|
||||
ID="debian"
|
||||
HOME_URL="https://github.com/GoogleContainerTools/distroless"
|
||||
SUPPORT_URL="https://github.com/GoogleContainerTools/distroless/blob/master/README.md"
|
||||
BUG_REPORT_URL="https://github.com/GoogleContainerTools/distroless/issues/new"
|
||||
@@ -48,7 +48,7 @@ catalogers:
|
||||
type: BinaryPkg
|
||||
- method: glob
|
||||
criteria:
|
||||
- '**/go'
|
||||
- '**/{go,go.exe}'
|
||||
packages:
|
||||
- class: go-binary
|
||||
name: go
|
||||
@@ -109,16 +109,6 @@ catalogers:
|
||||
cpes:
|
||||
- cpe:2.3:a:nodejs:node.js:*:*:*:*:*:*:*:*
|
||||
type: BinaryPkg
|
||||
- method: glob
|
||||
criteria:
|
||||
- '**/VERSION*'
|
||||
packages:
|
||||
- class: go-binary-hint
|
||||
name: go
|
||||
purl: pkg:generic/go
|
||||
cpes:
|
||||
- cpe:2.3:a:golang:go:*:*:*:*:*:*:*:*
|
||||
type: BinaryPkg
|
||||
- method: glob
|
||||
criteria:
|
||||
- '**/busybox'
|
||||
@@ -433,6 +423,17 @@ catalogers:
|
||||
cpes:
|
||||
- cpe:2.3:a:openssl:openssl:*:*:*:*:*:*:*:*
|
||||
type: BinaryPkg
|
||||
- method: glob
|
||||
criteria:
|
||||
- '**/libQt*Core.so*'
|
||||
packages:
|
||||
- class: qt-qtbase-lib
|
||||
name: qtbase
|
||||
purl: pkg:generic/qtbase
|
||||
cpes:
|
||||
- cpe:2.3:a:qt:qt:*:*:*:*:*:*:*:*
|
||||
- cpe:2.3:a:qt:qtbase:*:*:*:*:*:*:*:*
|
||||
type: BinaryPkg
|
||||
- method: glob
|
||||
criteria:
|
||||
- '**/gcc'
|
||||
|
||||
@@ -64,6 +64,10 @@ func (c cataloger) Catalog(_ context.Context, resolver file.Resolver) ([]pkg.Pac
|
||||
var relationships []artifact.Relationship
|
||||
var errs error
|
||||
|
||||
// we do not run these classifiers in parallel currently because: when determining primary vs. supporting evidence,
|
||||
// we take preference to the classifier that was defined first, if we modify this to run in parallel,
|
||||
// we need to retain this behavior by giving precedence to the classifier defined first in the c.classifiers list;
|
||||
// if this is ever made parallel, we will need to account for this to have deterministic behavior
|
||||
for _, cls := range c.classifiers {
|
||||
log.WithFields("classifier", cls.Class).Trace("cataloging binaries")
|
||||
newPkgs, err := catalog(resolver, cls)
|
||||
@@ -101,8 +105,26 @@ 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()...)
|
||||
addedEvidence := false
|
||||
// when merging locations together, we need to maintain primary vs. supporting evidence -
|
||||
// if we are merging two packages together that have overlapping evidence, e.g. libpython
|
||||
// which are found by 2 different classifiers, we want to deduplicate evidence for the same
|
||||
// locations when merging so libpython is not considered primary evidence. This allows cases
|
||||
// where we find python binary with version info coming from libpython to deduplicate the libpython
|
||||
// entries, but also surface results for libpython separately as primary evidence when there is
|
||||
// no python binary referencing it
|
||||
for _, location := range extra.Locations.ToSlice() {
|
||||
// if we already have the same location, don't include duplicates
|
||||
if target.Locations.Contains(location) {
|
||||
continue
|
||||
}
|
||||
addedEvidence = true
|
||||
target.Locations.Add(location)
|
||||
}
|
||||
// only include the additional metadata if we added evidence, as it was likely duplicated e.g. libpython
|
||||
if !addedEvidence {
|
||||
return
|
||||
}
|
||||
// update the metadata to indicate which classifiers were used
|
||||
meta, _ := target.Metadata.(pkg.BinarySignature)
|
||||
if m, ok := extra.Metadata.(pkg.BinarySignature); ok {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -547,6 +548,7 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
// no python binary, but we find libpython, which is surfaced as primary evidence
|
||||
logicalFixture: "python-shared-lib/3.7.4/linux-amd64",
|
||||
expected: pkg.Package{
|
||||
Name: "python",
|
||||
@@ -556,7 +558,6 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
|
||||
Metadata: metadata("python-binary-lib"),
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
// note: dynamic (non-snippet) test case
|
||||
logicalFixture: "python-slim-shared-libs/3.11/linux-amd64",
|
||||
@@ -569,7 +570,6 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
|
||||
Matches: []pkg.ClassifierMatch{
|
||||
match("python-binary", "python3.11"),
|
||||
match("python-binary", "libpython3.11.so.1.0"),
|
||||
match("python-binary-lib", "libpython3.11.so.1.0"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -586,7 +586,6 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
|
||||
Matches: []pkg.ClassifierMatch{
|
||||
match("python-binary", "python3.9"),
|
||||
match("python-binary", "libpython3.9.so.1.0"),
|
||||
match("python-binary-lib", "libpython3.9.so.1.0"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -618,7 +617,6 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
|
||||
Matches: []pkg.ClassifierMatch{
|
||||
match("python-binary", "python3.4"),
|
||||
match("python-binary", "libpython3.4m.so.1.0"),
|
||||
match("python-binary-lib", "libpython3.4m.so.1.0"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -734,8 +732,28 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
|
||||
Name: "go",
|
||||
Version: "1.15",
|
||||
PURL: "pkg:generic/go@1.15",
|
||||
Locations: locations("VERSION"),
|
||||
Metadata: metadata("go-binary-hint"),
|
||||
Locations: locations("bin/go", "VERSION"),
|
||||
Metadata: metadata("go-binary"),
|
||||
},
|
||||
},
|
||||
{
|
||||
logicalFixture: "go-version-hint/1.15w/any",
|
||||
expected: pkg.Package{
|
||||
Name: "go",
|
||||
Version: "1.15",
|
||||
PURL: "pkg:generic/go@1.15",
|
||||
Locations: locations("bin/go.exe", "VERSION"),
|
||||
Metadata: metadata("go-binary"),
|
||||
},
|
||||
},
|
||||
{
|
||||
logicalFixture: "go-version-hint/1.21/any",
|
||||
expected: pkg.Package{
|
||||
Name: "go",
|
||||
Version: "1.21",
|
||||
PURL: "pkg:generic/go@1.21",
|
||||
Locations: locations("go", "VERSION"),
|
||||
Metadata: metadata("go-binary"),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -745,8 +763,18 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
|
||||
Name: "go",
|
||||
Version: "1.25-d524e1e",
|
||||
PURL: "pkg:generic/go@1.25-d524e1e",
|
||||
Locations: locations("VERSION.cache"),
|
||||
Metadata: metadata("go-binary-hint"),
|
||||
Locations: locations("bin/go", "VERSION.cache"),
|
||||
Metadata: metadata("go-binary"),
|
||||
},
|
||||
},
|
||||
{
|
||||
logicalFixture: "go-version-hint/1.25w/any",
|
||||
expected: pkg.Package{
|
||||
Name: "go",
|
||||
Version: "1.25-d524e1e",
|
||||
PURL: "pkg:generic/go@1.25-d524e1e",
|
||||
Locations: locations("go.exe", "VERSION"),
|
||||
Metadata: metadata("go-binary"),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -1271,6 +1299,39 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
|
||||
Metadata: metadata("openssl-binary"),
|
||||
},
|
||||
},
|
||||
{
|
||||
logicalFixture: "qt/4.8.6/linux-amd64",
|
||||
expected: pkg.Package{
|
||||
Name: "qtbase",
|
||||
Version: "4.8.6",
|
||||
Type: "binary",
|
||||
PURL: "pkg:generic/qtbase@4.8.6",
|
||||
Locations: locations("libQtCore.so.4.8.6"),
|
||||
Metadata: metadata("qt-qtbase-lib"),
|
||||
},
|
||||
},
|
||||
{
|
||||
logicalFixture: "qt/5.15.2/linux-amd64",
|
||||
expected: pkg.Package{
|
||||
Name: "qtbase",
|
||||
Version: "5.15.2",
|
||||
Type: "binary",
|
||||
PURL: "pkg:generic/qtbase@5.15.2",
|
||||
Locations: locations("libQt5Core.so.5.15.2"),
|
||||
Metadata: metadata("qt-qtbase-lib"),
|
||||
},
|
||||
},
|
||||
{
|
||||
logicalFixture: "qt/6.5.0/linux-amd64",
|
||||
expected: pkg.Package{
|
||||
Name: "qtbase",
|
||||
Version: "6.5.0",
|
||||
Type: "binary",
|
||||
PURL: "pkg:generic/qtbase@6.5.0",
|
||||
Locations: locations("libQt6Core.so.6.5.0"),
|
||||
Metadata: metadata("qt-qtbase-lib"),
|
||||
},
|
||||
},
|
||||
{
|
||||
logicalFixture: "gcc/12.3.0/linux-amd64",
|
||||
expected: pkg.Package{
|
||||
@@ -1823,17 +1884,6 @@ func Test_Cataloger_DefaultClassifiers_PositiveCases_Image(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, p := range packages {
|
||||
expectedLocations := test.expected.Locations.ToSlice()
|
||||
gotLocations := p.Locations.ToSlice()
|
||||
require.Len(t, gotLocations, len(expectedLocations))
|
||||
|
||||
for i, expectedLocation := range expectedLocations {
|
||||
gotLocation := gotLocations[i]
|
||||
if expectedLocation.RealPath != gotLocation.RealPath {
|
||||
t.Fatalf("locations do not match; expected: %v got: %v", expectedLocations, gotLocations)
|
||||
}
|
||||
}
|
||||
|
||||
assertPackagesAreEqual(t, test.expected, p)
|
||||
}
|
||||
})
|
||||
@@ -2023,12 +2073,13 @@ func assertPackagesAreEqual(t *testing.T, expected pkg.Package, p pkg.Package) {
|
||||
gotLocations := p.Locations.ToSlice()
|
||||
|
||||
if len(expectedLocations) != len(gotLocations) {
|
||||
failMessages = append(failMessages, "locations are not equal length")
|
||||
failMessages = append(failMessages, fmt.Sprintf("locations are not equal: %v != %v", expectedLocations, gotLocations))
|
||||
} else {
|
||||
for i, expectedLocation := range expectedLocations {
|
||||
gotLocation := gotLocations[i]
|
||||
if expectedLocation.RealPath != gotLocation.RealPath {
|
||||
failMessages = append(failMessages, fmt.Sprintf("locations do not match; expected: %v got: %v", expectedLocation.RealPath, gotLocation.RealPath))
|
||||
for _, expectedLocation := range expectedLocations {
|
||||
if !slices.ContainsFunc(gotLocations, func(gotLocation file.Location) bool {
|
||||
return gotLocation.RealPath == expectedLocation.RealPath
|
||||
}) {
|
||||
failMessages = append(failMessages, fmt.Sprintf("location not found; expected: %v in set: %v", expectedLocation.RealPath, gotLocations))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,9 +70,17 @@ func DefaultClassifiers() []binutils.Classifier {
|
||||
},
|
||||
{
|
||||
Class: "go-binary",
|
||||
FileGlob: "**/go",
|
||||
EvidenceMatcher: m.FileContentsVersionMatcher(
|
||||
`(?m)go(?P<version>[0-9]+\.[0-9]+(\.[0-9]+|beta[0-9]+|alpha[0-9]+|rc[0-9]+)?)\x00`),
|
||||
FileGlob: "**/{go,go.exe}",
|
||||
EvidenceMatcher: binutils.MatchAny(
|
||||
m.FileContentsVersionMatcher(
|
||||
`(?m)go(?P<version>[0-9]+\.[0-9]+(\.[0-9]+|beta[0-9]+|alpha[0-9]+|rc[0-9]+)?)\x00`),
|
||||
binutils.SupportingEvidenceMatcher("VERSION*",
|
||||
m.FileContentsVersionMatcher(
|
||||
`(?m)go(?P<version>[0-9]+\.[0-9]+(\.[0-9]+|beta[0-9]+|alpha[0-9]+|rc[0-9]+|-[_0-9a-z]+)?)\s`)),
|
||||
binutils.SupportingEvidenceMatcher("../VERSION*",
|
||||
m.FileContentsVersionMatcher(
|
||||
`(?m)go(?P<version>[0-9]+\.[0-9]+(\.[0-9]+|beta[0-9]+|alpha[0-9]+|rc[0-9]+|-[_0-9a-z]+)?)\s`)),
|
||||
),
|
||||
Package: "go",
|
||||
PURL: mustPURL("pkg:generic/go@version"),
|
||||
CPEs: singleCPE("cpe:2.3:a:golang:go:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
|
||||
@@ -142,15 +150,6 @@ func DefaultClassifiers() []binutils.Classifier {
|
||||
PURL: mustPURL("pkg:generic/node@version"),
|
||||
CPEs: singleCPE("cpe:2.3:a:nodejs:node.js:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
|
||||
},
|
||||
{
|
||||
Class: "go-binary-hint",
|
||||
FileGlob: "**/VERSION*",
|
||||
EvidenceMatcher: m.FileContentsVersionMatcher(
|
||||
`(?m)go(?P<version>[0-9]+\.[0-9]+(\.[0-9]+|beta[0-9]+|alpha[0-9]+|rc[0-9]+)?(-[0-9a-f]{7})?)`),
|
||||
Package: "go",
|
||||
PURL: mustPURL("pkg:generic/go@version"),
|
||||
CPEs: singleCPE("cpe:2.3:a:golang:go:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
|
||||
},
|
||||
{
|
||||
Class: "busybox-binary",
|
||||
FileGlob: "**/busybox",
|
||||
@@ -513,6 +512,22 @@ func DefaultClassifiers() []binutils.Classifier {
|
||||
PURL: mustPURL("pkg:generic/openssl@version"),
|
||||
CPEs: singleCPE("cpe:2.3:a:openssl:openssl:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
|
||||
},
|
||||
{
|
||||
Class: "qt-qtbase-lib",
|
||||
FileGlob: "**/libQt*Core.so*",
|
||||
EvidenceMatcher: binutils.MatchAny(
|
||||
// Qt 5.x and Qt 6.x pattern [NUL][NUL]Qt 6.5.0 (x86_64-little_endian-...
|
||||
m.FileContentsVersionMatcher(`\x00\x00Qt (?P<version>[0-9]+\.[0-9]+\.[0-9]+) \(`),
|
||||
// Qt 4.x pattern QtCore lib ver 4.8.7
|
||||
m.FileContentsVersionMatcher(`QtCore library version (?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
|
||||
),
|
||||
Package: "qtbase",
|
||||
PURL: mustPURL("pkg:generic/qtbase@version"),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:qt:qt:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
|
||||
cpe.Must("cpe:2.3:a:qt:qtbase:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
|
||||
},
|
||||
},
|
||||
{
|
||||
Class: "gcc-binary",
|
||||
FileGlob: "**/gcc",
|
||||
|
||||
@@ -41,4 +41,4 @@ clean-fingerprint: ## clean up all legacy fingerprint files
|
||||
help:
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "$(BOLD)$(CYAN)%-25s$(RESET)%s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: default list download download-all clean clean-fingerprint add-snippet fingerprint
|
||||
.PHONY: default list download download-all clean clean-fingerprint add-snippet fingerprint
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
go1.15-beta2
|
||||
go1.15 Fri 2003
|
||||
+1
@@ -0,0 +1 @@
|
||||
no version in this binary
|
||||
+1
@@ -0,0 +1 @@
|
||||
go1.15 Fri 2003
|
||||
+1
@@ -0,0 +1 @@
|
||||
no version in this binary
|
||||
+1
@@ -0,0 +1 @@
|
||||
go1.21 Fri 2003
|
||||
+1
@@ -0,0 +1 @@
|
||||
no version in this binary
|
||||
+1
@@ -0,0 +1 @@
|
||||
no version in this binary
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
devel go1.25-d524e1e Sun Feb 16 07:23:13 2025 -0800
|
||||
3devel go1.25-d524e1e Sun Feb 16 07:23:13 2025 -0800
|
||||
+1
@@ -0,0 +1 @@
|
||||
no version in this binary
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -11,7 +11,7 @@ from-images:
|
||||
|
||||
- name: busybox
|
||||
version: 1.36.1
|
||||
images:
|
||||
images:
|
||||
- ref: busybox:1.36.1@sha256:058f0df5310fbbbfea7e81a3a3e2b4bf3452438ec841138d170e170adbbd27a4
|
||||
platform: linux/amd64
|
||||
paths:
|
||||
@@ -1020,6 +1020,29 @@ from-images:
|
||||
paths:
|
||||
- /usr/share/grafana/bin/grafana-server
|
||||
|
||||
- name: qt
|
||||
version: 6.5.0
|
||||
images:
|
||||
- ref: stateoftheartio/qt6:6.5-gcc-aqt@sha256:c0dfd1cd174d855f0157ce0455270b2ee49f5eea4c7a40ffe0e848d41ae4d074
|
||||
platform: linux/amd64
|
||||
paths:
|
||||
- /opt/Qt/6.5.0/gcc_64/lib/libQt6Core.so.6.5.0
|
||||
|
||||
- name: qt
|
||||
version: 5.15.2
|
||||
images:
|
||||
- ref: rabits/qt:5.15-desktop@sha256:8dd10b4fcdece7e329dd2b9db52dafcd6590940954bc36d5018567e850d9599c
|
||||
platform: linux/amd64
|
||||
paths:
|
||||
- /opt/Qt/5.15.2/gcc_64/lib/libQt5Core.so.5.15.2
|
||||
|
||||
- name: qt
|
||||
version: 4.8.6
|
||||
images:
|
||||
- ref: uvatbc/qt:qt4@sha256:9d6f18e000df14077f4c96e487fc84e02f1cef19c27f2a8f66f161b8a1ef6b06
|
||||
platform: linux/amd64
|
||||
paths:
|
||||
- /usr/lib/x86_64-linux-gnu/libQtCore.so.4.8.6
|
||||
- version: 1.36.4
|
||||
images:
|
||||
- ref: envoyproxy/envoy:v1.36.4@sha256:ae31562b8cede20913a2d3d6a4f44c8479a50551e033cb8ef7bb8e38cec4b573
|
||||
@@ -1081,4 +1104,4 @@ from-images:
|
||||
- ref: envoyproxy/envoy:v1.6.0@sha256:6d02409028d76b69bc348650e080e68fd81b863e68aa16e96c95d74ab0f16f24
|
||||
platform: linux/amd64
|
||||
paths:
|
||||
- /usr/local/bin/envoy
|
||||
- /usr/local/bin/envoy
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func Test_BranchingMatcher(t *testing.T) {
|
||||
matchingTest := FileContentsVersionMatcher("", `my-verison:(?<version>\d+\.\d+)`)
|
||||
matchingTest := FileContentsVersionMatcher("", `my-version:(?<version>\d+\.\d+)`)
|
||||
notMatchingTest := MatchPath("**/not-version*")
|
||||
|
||||
tests := []struct {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"maps"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -273,9 +274,7 @@ func SharedLibraryLookup(sharedLibraryPattern string, sharedLibraryMatcher Evide
|
||||
}
|
||||
for _, p := range pkgs {
|
||||
// set the source binary as the first location
|
||||
locationSet := file.NewLocationSet(context.Location)
|
||||
locationSet.Add(p.Locations.ToSlice()...)
|
||||
p.Locations = locationSet
|
||||
makePrimaryLocation(&p, context.Location)
|
||||
meta, _ := p.Metadata.(pkg.BinarySignature)
|
||||
p.Metadata = pkg.BinarySignature{
|
||||
Matches: append([]pkg.ClassifierMatch{
|
||||
@@ -309,6 +308,28 @@ func MatchPath(path string) EvidenceMatcher {
|
||||
}
|
||||
}
|
||||
|
||||
// SupportingEvidenceMatcher defines an evidence matcher that searches for secondary evidence with path globs
|
||||
// relative to a primary file, for example: a VERSION file in the same or a parent directory to another binary
|
||||
func SupportingEvidenceMatcher(relativePathGlob string, evidenceMatcher EvidenceMatcher) EvidenceMatcher {
|
||||
return func(classifier Classifier, context MatcherContext) ([]pkg.Package, error) {
|
||||
f := path.Dir(context.Location.RealPath)
|
||||
f = path.Join(f, relativePathGlob)
|
||||
f = path.Clean(f)
|
||||
// this would ideally be RelativeFileByPath but with a glob search:
|
||||
relativeFiles, err := context.Resolver.FilesByGlob(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, relativeFile := range relativeFiles {
|
||||
evidence, err := collectSupportingEvidence(classifier, context, relativeFile, evidenceMatcher)
|
||||
if evidence != nil || err != nil {
|
||||
return evidence, err
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func getReader(context MatcherContext) (unionreader.UnionReader, error) {
|
||||
if context.GetReader != nil {
|
||||
return context.GetReader(context)
|
||||
@@ -368,3 +389,43 @@ func sharedLibraries(context MatcherContext) ([]string, error) {
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func makePrimaryLocation(p *pkg.Package, primaryLocation file.Location) {
|
||||
locationSet := file.NewLocationSet(primaryLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation))
|
||||
for _, l := range p.Locations.ToSlice() {
|
||||
if locationSet.Contains(l) { // no need for duplicate locations
|
||||
continue
|
||||
}
|
||||
locationSet.Add(l.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation))
|
||||
}
|
||||
p.Locations = locationSet
|
||||
}
|
||||
|
||||
func collectSupportingEvidence(classifier Classifier, context MatcherContext, relativeFile file.Location, evidenceMatcher EvidenceMatcher) ([]pkg.Package, error) {
|
||||
rdr, err := context.Resolver.FileContentsByLocation(relativeFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer internal.CloseAndLogError(rdr, relativeFile.Path())
|
||||
ur, err := unionreader.GetUnionReader(rdr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newContext := MatcherContext{
|
||||
Resolver: context.Resolver,
|
||||
Location: relativeFile,
|
||||
GetReader: func(_ MatcherContext) (unionreader.UnionReader, error) {
|
||||
return ur, nil
|
||||
},
|
||||
}
|
||||
packages, err := evidenceMatcher(classifier, newContext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range packages {
|
||||
p := &(packages[i])
|
||||
// relative files are supporting evidence, like a VERSION file near a go binary, mark the results as supporting
|
||||
makePrimaryLocation(p, context.Location)
|
||||
}
|
||||
return packages, nil
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ import (
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/internal/unionreader"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
"github.com/anchore/syft/syft/source/directorysource"
|
||||
)
|
||||
|
||||
func Test_ClassifierCPEs(t *testing.T) {
|
||||
@@ -27,7 +29,7 @@ func Test_ClassifierCPEs(t *testing.T) {
|
||||
classifier: Classifier{
|
||||
Package: "some-app",
|
||||
FileGlob: "**/version.txt",
|
||||
EvidenceMatcher: FileContentsVersionMatcher("cataloger-name", `(?m)my-verison:(?P<version>[0-9.]+)`),
|
||||
EvidenceMatcher: FileContentsVersionMatcher("cataloger-name", `(?m)my-version:(?P<version>[0-9.]+)`),
|
||||
CPEs: []cpe.CPE{},
|
||||
},
|
||||
cpes: nil,
|
||||
@@ -38,7 +40,7 @@ func Test_ClassifierCPEs(t *testing.T) {
|
||||
classifier: Classifier{
|
||||
Package: "some-app",
|
||||
FileGlob: "**/version.txt",
|
||||
EvidenceMatcher: FileContentsVersionMatcher("cataloger-name", `(?m)my-verison:(?P<version>[0-9.]+)`),
|
||||
EvidenceMatcher: FileContentsVersionMatcher("cataloger-name", `(?m)my-version:(?P<version>[0-9.]+)`),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:some:app:*:*:*:*:*:*:*:*", cpe.GeneratedSource),
|
||||
},
|
||||
@@ -53,7 +55,7 @@ func Test_ClassifierCPEs(t *testing.T) {
|
||||
classifier: Classifier{
|
||||
Package: "some-app",
|
||||
FileGlob: "**/version.txt",
|
||||
EvidenceMatcher: FileContentsVersionMatcher("cataloger-name", `(?m)my-verison:(?P<version>[0-9.]+)`),
|
||||
EvidenceMatcher: FileContentsVersionMatcher("cataloger-name", `(?m)my-version:(?P<version>[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),
|
||||
@@ -183,3 +185,61 @@ func TestFileContentsVersionMatcher(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_SupportingEvidenceMatcher(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
classifier Classifier
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "simple version string regexp",
|
||||
classifier: Classifier{
|
||||
FileGlob: "**/some-binary",
|
||||
EvidenceMatcher: SupportingEvidenceMatcher("../version.txt",
|
||||
FileContentsVersionMatcher("cataloger-name", `(?m)my-version:(?P<version>[0-9.]+)`)),
|
||||
Package: "some-binary",
|
||||
},
|
||||
expected: "1.8",
|
||||
},
|
||||
{
|
||||
name: "not matching version string regexp",
|
||||
classifier: Classifier{
|
||||
FileGlob: "**/some-binary",
|
||||
EvidenceMatcher: SupportingEvidenceMatcher("../version.txt",
|
||||
FileContentsVersionMatcher("cataloger-name", `(?m)my-version:(?P<version>abdd)`)),
|
||||
Package: "some-binary",
|
||||
},
|
||||
expected: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s, err := directorysource.NewFromPath("test-fixtures")
|
||||
require.NoError(t, err)
|
||||
r, err := s.FileResolver(source.AllLayersScope)
|
||||
require.NoError(t, err)
|
||||
|
||||
results, err := r.FilesByGlob(tt.classifier.FileGlob)
|
||||
require.NoError(t, err)
|
||||
for _, result := range results {
|
||||
got, err := tt.classifier.EvidenceMatcher(tt.classifier, MatcherContext{
|
||||
Resolver: r,
|
||||
Location: result,
|
||||
GetReader: func(ctx MatcherContext) (unionreader.UnionReader, error) {
|
||||
return getReader(ctx)
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
if tt.expected != "" {
|
||||
require.NotEmpty(t, got)
|
||||
require.Equal(t, tt.expected, got[0].Version)
|
||||
} else {
|
||||
require.Empty(t, got)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
a binary
|
||||
@@ -1 +1 @@
|
||||
my-verison:1.8
|
||||
my-version:1.8
|
||||
@@ -635,6 +635,7 @@ func Test_PackageCataloger_Relationships(t *testing.T) {
|
||||
"jinja2 @ 3.1.4 (.) [dependency-of] fastapi @ 0.111.0 (.)",
|
||||
"jinja2 @ 3.1.4 (.) [dependency-of] starlette @ 0.37.2 (.)",
|
||||
"markdown-it-py @ 3.0.0 (.) [dependency-of] rich @ 13.7.1 (.)",
|
||||
"markupsafe @ 2.1.5 (.) [dependency-of] jinja2 @ 3.1.4 (.)", // MarkupSafe (mixed case) -> markupsafe
|
||||
"mdurl @ 0.1.2 (.) [dependency-of] markdown-it-py @ 3.0.0 (.)",
|
||||
"orjson @ 3.10.3 (.) [dependency-of] fastapi @ 0.111.0 (.)",
|
||||
"pydantic @ 2.7.1 (.) [dependency-of] fastapi @ 0.111.0 (.)",
|
||||
|
||||
@@ -74,8 +74,10 @@ func isDependencyForExtra(dep pkg.PythonPoetryLockDependencyEntry) bool {
|
||||
}
|
||||
|
||||
func packageRef(name, extra string) string {
|
||||
cleanExtra := strings.TrimSpace(extra)
|
||||
cleanName := strings.TrimSpace(name)
|
||||
// normalize both package name and extra to ensure case-insensitive matching per Python packaging spec
|
||||
// https://packaging.python.org/en/latest/specifications/name-normalization/
|
||||
cleanName := normalize(strings.TrimSpace(name))
|
||||
cleanExtra := normalize(strings.TrimSpace(extra))
|
||||
if cleanExtra == "" {
|
||||
return cleanName
|
||||
}
|
||||
|
||||
@@ -181,6 +181,30 @@ func Test_poetryLockDependencySpecifier(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "dependency names with mixed case should be normalized",
|
||||
p: pkg.Package{
|
||||
Name: "dj-rest-auth",
|
||||
Metadata: pkg.PythonPoetryLockEntry{
|
||||
Dependencies: []pkg.PythonPoetryLockDependencyEntry{
|
||||
{
|
||||
Name: "Django", // note: capital D
|
||||
Version: ">=4.2,<6.0",
|
||||
},
|
||||
{
|
||||
Name: "djangorestframework",
|
||||
Version: ">=3.13.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: dependency.Specification{
|
||||
ProvidesRequires: dependency.ProvidesRequires{
|
||||
Provides: []string{"dj-rest-auth"},
|
||||
Requires: []string{"django", "djangorestframework"}, // "Django" should be normalized to "django"
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -195,6 +219,38 @@ func Test_poetryLockDependencySpecifier_againstPoetryLock(t *testing.T) {
|
||||
fixture string
|
||||
want []dependency.Specification
|
||||
}{
|
||||
{
|
||||
name: "case-insensitive dependency resolution",
|
||||
fixture: "test-fixtures/poetry/case-sensitivity/poetry.lock",
|
||||
want: []dependency.Specification{
|
||||
// packages are in the order they appear in the lock file
|
||||
{
|
||||
ProvidesRequires: dependency.ProvidesRequires{
|
||||
Provides: []string{"django"},
|
||||
Requires: []string{"asgiref", "sqlparse"},
|
||||
},
|
||||
},
|
||||
{
|
||||
ProvidesRequires: dependency.ProvidesRequires{
|
||||
Provides: []string{"djangorestframework"},
|
||||
Requires: []string{"django"},
|
||||
},
|
||||
},
|
||||
{
|
||||
// dj-rest-auth depends on Django (capital D) which should resolve to django
|
||||
ProvidesRequires: dependency.ProvidesRequires{
|
||||
Provides: []string{"dj-rest-auth"},
|
||||
Requires: []string{"django", "djangorestframework"}, // Django normalized to django
|
||||
},
|
||||
Variants: []dependency.ProvidesRequires{
|
||||
{
|
||||
Provides: []string{"dj-rest-auth[with-social]"},
|
||||
Requires: []string{"django-allauth"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "simple dependencies with extras",
|
||||
fixture: "test-fixtures/poetry/simple-deps/poetry.lock",
|
||||
@@ -276,6 +332,64 @@ func Test_poetryLockDependencySpecifier_againstPoetryLock(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test_packageRef verifies that package references are normalized according to
|
||||
// the Python Packaging specification for names and extras:
|
||||
// https://packaging.python.org/en/latest/specifications/name-normalization/
|
||||
func Test_packageRef(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pkg string
|
||||
extra string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "simple package name",
|
||||
pkg: "requests",
|
||||
want: "requests",
|
||||
},
|
||||
{
|
||||
name: "package with extra",
|
||||
pkg: "requests",
|
||||
extra: "security",
|
||||
want: "requests[security]",
|
||||
},
|
||||
{
|
||||
name: "package name with mixed case",
|
||||
pkg: "Django",
|
||||
want: "django",
|
||||
},
|
||||
{
|
||||
name: "package name with underscores",
|
||||
pkg: "some_package",
|
||||
want: "some-package",
|
||||
},
|
||||
{
|
||||
name: "package name with mixed case and extra",
|
||||
pkg: "Django",
|
||||
extra: "argon2",
|
||||
want: "django[argon2]",
|
||||
},
|
||||
{
|
||||
name: "extra with mixed case",
|
||||
pkg: "package",
|
||||
extra: "Security",
|
||||
want: "package[security]",
|
||||
},
|
||||
{
|
||||
name: "both with mixed case and separators",
|
||||
pkg: "Some_Package",
|
||||
extra: "Dev_Extra",
|
||||
want: "some-package[dev-extra]",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := packageRef(tt.pkg, tt.extra)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_extractPackageName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# This file is automatically @generated by Poetry and should not be edited manually.
|
||||
|
||||
[[package]]
|
||||
name = "django"
|
||||
version = "5.2.6"
|
||||
description = "A high-level Python web framework"
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "Django-5.2.6-py3-none-any.whl", hash = "sha256:example1"},
|
||||
{file = "django-5.2.6.tar.gz", hash = "sha256:example2"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
asgiref = ">=3.8.1,<4"
|
||||
sqlparse = ">=0.3.1"
|
||||
|
||||
[[package]]
|
||||
name = "djangorestframework"
|
||||
version = "3.16.1"
|
||||
description = "Web APIs for Django, made easy."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "djangorestframework-3.16.1-py3-none-any.whl", hash = "sha256:example3"},
|
||||
{file = "djangorestframework-3.16.1.tar.gz", hash = "sha256:example4"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
django = ">=4.2"
|
||||
|
||||
[[package]]
|
||||
name = "dj-rest-auth"
|
||||
version = "7.0.1"
|
||||
description = "Authentication and Registration in Django Rest Framework"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "dj-rest-auth-7.0.1.tar.gz", hash = "sha256:3f8c744cbcf05355ff4bcbef0c8a63645da38e29a0fdef3c3332d4aced52fb90"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
Django = ">=4.2,<6.0"
|
||||
djangorestframework = ">=3.13.0"
|
||||
|
||||
[package.extras]
|
||||
with-social = ["django-allauth[socialaccount] (>=64.0.0)"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = "^3.10"
|
||||
content-hash = "example"
|
||||
@@ -118,29 +118,3 @@ catalogers:
|
||||
default: false
|
||||
- name: package_manager.package_integrity_hash
|
||||
default: false
|
||||
- function: parseSnapYaml
|
||||
detector: # AUTO-GENERATED
|
||||
method: glob # AUTO-GENERATED
|
||||
criteria: # AUTO-GENERATED
|
||||
- '**/meta/snap.yaml'
|
||||
metadata_types: # AUTO-GENERATED
|
||||
- pkg.SnapEntry
|
||||
package_types: # AUTO-GENERATED
|
||||
- deb
|
||||
json_schema_types: # AUTO-GENERATED
|
||||
- SnapEntry
|
||||
capabilities: # MANUAL - preserved across regeneration
|
||||
- name: license
|
||||
default: false
|
||||
- name: dependency.depth
|
||||
default: []
|
||||
- name: dependency.edges
|
||||
default: ""
|
||||
- name: dependency.kinds
|
||||
default: []
|
||||
- name: package_manager.files.listing
|
||||
default: false
|
||||
- name: package_manager.files.digests
|
||||
default: false
|
||||
- name: package_manager.package_integrity_hash
|
||||
default: false
|
||||
|
||||
@@ -15,8 +15,6 @@ 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
|
||||
|
||||
@@ -19,17 +19,13 @@ func TestCataloger_Globs(t *testing.T) {
|
||||
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").
|
||||
IgnoreUnfulfilledPathResponses("**/usr/share/snappy/dpkg.yaml", "**/doc/linux-modules-*/changelog.Debian.gz", "**/snap/manifest.yaml", "**/snap/snapcraft.yaml").
|
||||
TestCataloger(t, NewCataloger())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -8,30 +8,6 @@ import (
|
||||
"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))
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
@@ -58,7 +59,7 @@ func readChangelogLines(reader file.LocationReadCloser) ([]string, error) {
|
||||
}
|
||||
defer gzReader.Close()
|
||||
|
||||
content, err := readAll(gzReader)
|
||||
content, err := io.ReadAll(gzReader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read changelog content: %w", err)
|
||||
}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
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)
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
name: test-snap
|
||||
version: 1.0
|
||||
type: app
|
||||
@@ -1,7 +0,0 @@
|
||||
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
|
||||
Reference in New Issue
Block a user