Compare commits

..

No commits in common. "main" and "v1.42.2" have entirely different histories.

86 changed files with 839 additions and 1242 deletions

View File

@ -1,13 +1,8 @@
# only pull in version updates that were released more than a week ago (low-pass filter for quickly-retracted releases)
cooldown: 7d
tools: tools:
## internal tools ############################################################################
# we want to use a pinned version of binny to manage the toolchain (so binny manages itself!) # we want to use a pinned version of binny to manage the toolchain (so binny manages itself!)
- name: binny - name: binny
version: version:
want: v0.13.0 want: v0.11.3
method: github-release method: github-release
with: with:
repo: anchore/binny repo: anchore/binny
@ -15,7 +10,7 @@ tools:
# used to produce SBOMs during release # used to produce SBOMs during release
- name: syft - name: syft
version: version:
want: v1.42.3 want: latest
method: github-release method: github-release
with: with:
repo: anchore/syft repo: anchore/syft
@ -23,25 +18,15 @@ tools:
# used to sign mac binaries at release # used to sign mac binaries at release
- name: quill - name: quill
version: version:
want: v0.7.1 want: v0.5.1
method: github-release method: github-release
with: with:
repo: anchore/quill repo: anchore/quill
# used at release to generate the changelog
- name: chronicle
version:
want: v0.8.0
method: github-release
with:
repo: anchore/chronicle
## external tools ############################################################################
# used for linting # used for linting
- name: golangci-lint - name: golangci-lint
version: version:
want: v2.11.4 want: v2.11.2
method: github-release method: github-release
with: with:
repo: golangci/golangci-lint repo: golangci/golangci-lint
@ -73,7 +58,7 @@ tools:
# used to release all artifacts # used to release all artifacts
- name: goreleaser - name: goreleaser
version: version:
want: v2.15.2 want: v2.14.2
method: github-release method: github-release
with: with:
repo: goreleaser/goreleaser repo: goreleaser/goreleaser
@ -86,6 +71,14 @@ tools:
with: with:
repo: rinchsan/gosimports repo: rinchsan/gosimports
# used at release to generate the changelog
- name: chronicle
version:
want: v0.8.0
method: github-release
with:
repo: anchore/chronicle
# used during static analysis for license compliance # used during static analysis for license compliance
- name: bouncer - name: bouncer
version: version:
@ -105,7 +98,7 @@ tools:
# used for triggering a release # used for triggering a release
- name: gh - name: gh
version: version:
want: v2.89.0 want: v2.87.3
method: github-release method: github-release
with: with:
repo: cli/cli repo: cli/cli
@ -113,7 +106,7 @@ tools:
# used to upload test fixture cache # used to upload test fixture cache
- name: oras - name: oras
version: version:
want: v1.3.1 want: v1.3.0
method: github-release method: github-release
with: with:
repo: oras-project/oras repo: oras-project/oras
@ -121,7 +114,7 @@ tools:
# used to upload test fixture cache # used to upload test fixture cache
- name: yq - name: yq
version: version:
want: v4.52.5 want: v4.52.4
method: github-release method: github-release
with: with:
repo: mikefarah/yq repo: mikefarah/yq

View File

@ -23,11 +23,6 @@ updates:
open-pull-requests-limit: 10 open-pull-requests-limit: 10
labels: labels:
- "dependencies" - "dependencies"
ignore:
- dependency-name: "github.com/aquasecurity/go-pep440-version"
- dependency-name: "github.com/aquasecurity/go-version"
- dependency-name: "github.com/knqyf263/go-apk-version"
- dependency-name: "github.com/knqyf263/go-deb-version"
groups: groups:
go-minor-patch: go-minor-patch:
applies-to: version-updates # security updates get individual PRs applies-to: version-updates # security updates get individual PRs
@ -40,7 +35,7 @@ updates:
- package-ecosystem: "github-actions" - package-ecosystem: "github-actions"
directories: directories:
- "/" - "/"
- "/.github/actions/*" - "/.github/actions/bootstrap"
cooldown: cooldown:
default-days: 7 default-days: 7
schedule: schedule:

76
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@ -0,0 +1,76 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
name: "CodeQL Security Scan"
on:
push:
branches:
# only run when there are pushes to the main branch (not on PRs)
- main
schedule:
- cron: '0 0 * * 3'
permissions:
contents: read
jobs:
analyze:
name: Analyze
runs-on: ubuntu-22.04-4core-16gb
if: github.repository == 'anchore/syft' # only run for main repo
permissions:
security-events: write
strategy:
fail-fast: false
matrix:
# Override automatic language detection by changing the below list
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ['go', 'python']
# Learn more...
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
persist-credentials: false
- name: Install Go
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 #v6.3.0
with:
go-version-file: go.mod
check-latest: true
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# 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@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3

View File

@ -1,81 +0,0 @@
# CodeQL scans for security vulnerabilities and coding errors across all
# languages in this repo. Results appear in the "Security" tab under
# "Code scanning alerts" and are enforced by branch protection rules.
name: "CodeQL"
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
# Weekly scheduled scan catches newly disclosed vulnerabilities in
# existing code, not just changes introduced by PRs.
schedule:
- cron: '38 11 * * 3'
jobs:
analyze:
name: Analyze (${{ matrix.language }})
runs-on: ubuntu-latest
permissions:
# Required to upload SARIF results to the "Security" tab.
security-events: write
# Required to fetch internal or private CodeQL packs.
packages: read
# Only required for workflows in private repositories.
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
# GitHub Actions workflow linting — no build needed.
- language: actions
build-mode: none
# Go uses "manual" build mode so we control exactly what gets
# compiled. The default "autobuild" finds the Makefile and runs
# the full CI pipeline (lint, test, snapshot release, etc.),
# which is far more work than CodeQL needs. All it requires is
# compiled Go source so it can build a type-resolved code graph
# for analysis.
- language: go
build-mode: manual
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
# Pin the Go toolchain to whatever go.mod declares so CodeQL
# analyzes with the same version the project actually uses.
# Only runs for the Go matrix entry.
- name: Setup Go
if: matrix.language == 'go'
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version-file: go.mod
- name: Initialize CodeQL
uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# Minimal build for Go: compile all packages so CodeQL gets a full
# type-resolved code graph for analysis.
- name: Build (Go)
if: matrix.build-mode == 'manual'
shell: bash
run: go build ./...
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
with:
# The category tag lets GitHub associate SARIF results with the
# correct language when branch protection checks for required
# code scanning results.
category: "/language:${{matrix.language}}"

View File

@ -1,5 +1,3 @@
# Note: this workflow has been disabled manually in the UI and will be replaced in short order
name: "Detect schema changes" name: "Detect schema changes"
on: on:
@ -39,8 +37,6 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with: with:
persist-credentials: false persist-credentials: false
repository: anchore/syft # IMPORTANT! An additional protection that this is checking out code from the expected repository
ref: main # IMPORTANT! It is CRITICAL that this only ever considers the code from main and NEVER EVER from a fork.
- run: python .github/scripts/labeler.py - run: python .github/scripts/labeler.py
env: env:
@ -50,7 +46,7 @@ jobs:
- name: Delete existing comment - name: Delete existing comment
if: ${{ hashFiles( env.CI_COMMENT_FILE ) == '' }} if: ${{ hashFiles( env.CI_COMMENT_FILE ) == '' }}
uses: marocchino/sticky-pull-request-comment@70d2764d1a7d5d9560b100cbea0077fc8f633987 #v3.0.2 uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 #v2.9.4
with: with:
header: ${{ env.COMMENT_HEADER }} header: ${{ env.COMMENT_HEADER }}
hide: true hide: true
@ -58,7 +54,7 @@ jobs:
- name: Add comment - name: Add comment
if: ${{ hashFiles( env.CI_COMMENT_FILE ) != '' }} if: ${{ hashFiles( env.CI_COMMENT_FILE ) != '' }}
uses: marocchino/sticky-pull-request-comment@70d2764d1a7d5d9560b100cbea0077fc8f633987 #v3.0.2 uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 #v2.9.4
with: with:
header: ${{ env.COMMENT_HEADER }} header: ${{ env.COMMENT_HEADER }}
path: ${{ env.CI_COMMENT_FILE }} path: ${{ env.CI_COMMENT_FILE }}

View File

@ -150,13 +150,13 @@ jobs:
uses: ./.github/actions/bootstrap uses: ./.github/actions/bootstrap
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 #v4.0.0 uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 #v3.7.0
with: with:
username: ${{ secrets.ANCHOREOSSWRITE_DH_USERNAME }} username: ${{ secrets.ANCHOREOSSWRITE_DH_USERNAME }}
password: ${{ secrets.ANCHOREOSSWRITE_DH_PAT }} password: ${{ secrets.ANCHOREOSSWRITE_DH_PAT }}
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 #v4.0.0 uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 #v3.7.0
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
@ -193,7 +193,7 @@ jobs:
artifact-name: sbom.spdx.json artifact-name: sbom.spdx.json
- name: Notify Slack of new release - name: Notify Slack of new release
uses: slackapi/slack-github-action@af78098f536edbc4de71162a307590698245be95 #v3.0.1 uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a #v2.1.1
continue-on-error: true continue-on-error: true
with: with:
webhook: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }} webhook: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}

View File

@ -0,0 +1,48 @@
name: "Test fixture cache: publish"
on:
workflow_dispatch:
schedule:
# run nightly at 4AM UTC
- cron: "0 4 * * *"
permissions:
contents: read
jobs:
Publish:
name: "Publish test fixture image cache"
# runs-on.com: general purpose instances for building test fixture cache
# spot disabled: can run up to an hour, avoid interruptions
# s3-cache: faster actions cache
# family: note that m*d instances have local nvme storage which is beneficial for building large test fixture images
runs-on: "runs-on=${{ github.run_id }}/cpu=8+16/ram=32+64/family=m5d+m5ad+m5dn+m6gd+m6id+m6idn+m7gd+m8gd/spot=false/extras=s3-cache"
if: github.repository == 'anchore/syft' # only run for main repo
permissions:
packages: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
persist-credentials: false
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
with:
# we want to rebuild the cache with no previous state
download-test-fixture-cache: false
- name: Run all tests
run: |
make test
env:
# we want to rebuild the cache with no previous state
DOWNLOAD_TEST_FIXTURE_CACHE: "false"
- name: Login to GitHub Container Registry (ORAS)
run: echo "${{ secrets.GITHUB_TOKEN }}" | .tool/oras login ghcr.io -u "$ACTOR" --password-stdin
env:
ACTOR: ${{ github.actor }}
- name: Publish test fixture cache
run: make upload-test-fixture-cache

View File

@ -0,0 +1,51 @@
name: PR to update Anchore dependencies
on:
workflow_dispatch:
inputs:
repos:
description: "List of dependencies to update"
required: true
type: string
permissions:
contents: read
jobs:
update:
runs-on: ubuntu-latest
if: github.repository_owner == 'anchore' # only run for main repo (not forks)
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
persist-credentials: false
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
with:
tools: false
bootstrap-apt-packages: ""
- name: Update dependencies
id: update
uses: anchore/workflows/.github/actions/update-go-dependencies@main
with:
repos: ${{ github.event.inputs.repos }}
- uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf #v2.2.1
id: generate-token
with:
app-id: ${{ secrets.TOKEN_APP_ID }}
private-key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
- uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 #v8.1.0
with:
signoff: true
delete-branch: true
draft: ${{ steps.update.outputs.draft }}
# do not change this branch, as other workflows depend on it
branch: auto/integration
labels: dependencies,pre-release
commit-message: "chore(deps): update anchore dependencies"
title: "chore(deps): update anchore dependencies"
body: ${{ steps.update.outputs.summary }}
token: ${{ steps.generate-token.outputs.token }}

View File

@ -0,0 +1,67 @@
name: PR for latest versions of tools
on:
schedule:
- cron: "0 8 * * *" # 3 AM EST
workflow_dispatch:
permissions:
contents: read
jobs:
update-bootstrap-tools:
runs-on: ubuntu-latest
if: github.repository == 'anchore/syft' # only run for main repo
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
persist-credentials: false
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
with:
bootstrap-apt-packages: ""
go-dependencies: false
- name: "Update tool versions"
id: latest-versions
run: |
make update-tools
make list-tools
export NO_COLOR=1
delimiter="$(openssl rand -hex 8)"
{
echo "status<<${delimiter}"
make list-tool-updates
echo "${delimiter}"
} >> $GITHUB_OUTPUT
{
echo "### Tool version status"
echo "\`\`\`"
make list-tool-updates
echo "\`\`\`"
} >> $GITHUB_STEP_SUMMARY
- uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf #v2.2.1
id: generate-token
with:
app-id: ${{ secrets.TOKEN_APP_ID }}
private-key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
- uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 #v8.1.0
with:
signoff: true
delete-branch: true
branch: auto/latest-tools
labels: dependencies
commit-message: 'chore(deps): update tools to latest versions'
title: 'chore(deps): update tools to latest versions'
body: |
```
${{ steps.latest-versions.outputs.status }}
```
This is an auto-generated pull request to update all of the tools to the latest versions.
token: ${{ steps.generate-token.outputs.token }}

View File

@ -0,0 +1,84 @@
name: PR to update CPE dictionary index
on:
schedule:
- cron: "0 1 * * 1" # every monday at 1 AM
workflow_dispatch:
permissions:
contents: read
env:
SLACK_NOTIFICATIONS: true
jobs:
upgrade-cpe-dictionary-index:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
if: github.repository == 'anchore/syft' # only run for main repo
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
persist-credentials: false
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
id: bootstrap
- name: Login to GitHub Container Registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | .tool/oras login ghcr.io -u "$ACTOR" --password-stdin
env:
ACTOR: ${{ github.actor }}
- name: Pull CPE cache from registry
run: make generate:cpe-index:cache:pull
- name: Update CPE cache from NVD API
run: make generate:cpe-index:cache:update
env:
NVD_API_KEY: ${{ secrets.NVD_API_KEY }}
- name: Generate CPE dictionary index
run: make generate:cpe-index:build
- name: Push updated CPE cache to registry
run: make generate:cpe-index:cache:push
- uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf #v2.2.1
id: generate-token
with:
app-id: ${{ secrets.TOKEN_APP_ID }}
private-key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
- uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 #v8.1.0
with:
signoff: true
delete-branch: true
branch: auto/latest-cpe-dictionary-index
labels: dependencies
commit-message: "chore(deps): update CPE dictionary index"
title: "chore(deps): update CPE dictionary index"
body: |
Update CPE dictionary index based on the latest available CPE dictionary
token: ${{ steps.generate-token.outputs.token }}
- name: Notify Slack on failure
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a #v2.1.1
with:
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' }}

View File

@ -0,0 +1,64 @@
name: PR to update SPDX license list
on:
schedule:
- cron: "0 6 * * 1" # every monday at 6 AM UTC
workflow_dispatch:
permissions:
contents: read
env:
SLACK_NOTIFICATIONS: true
jobs:
upgrade-spdx-license-list:
runs-on: ubuntu-latest
if: github.repository == 'anchore/syft' # only run for main repo
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
persist-credentials: false
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
- run: |
make generate-license-list
- uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a #v2.1.0
id: generate-token
with:
app_id: ${{ secrets.TOKEN_APP_ID }}
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
- uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 #v8.1.0
with:
signoff: true
delete-branch: true
branch: auto/latest-spdx-license-list
labels: dependencies
commit-message: "chore(deps): update SPDX license list"
title: "chore(deps): update SPDX license list"
body: |
Update SPDX license list based on the latest available list from spdx.org
token: ${{ steps.generate-token.outputs.token }}
- name: Notify Slack on failure
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a #v2.1.1
with:
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' }}

View File

@ -1,8 +1,10 @@
name: "Validate GitHub Actions" name: "Validate GitHub Actions"
on: on:
workflow_dispatch:
pull_request: pull_request:
paths:
- '.github/workflows/**'
- '.github/actions/**'
push: push:
branches: branches:
- main - main
@ -26,8 +28,9 @@ jobs:
persist-credentials: false persist-credentials: false
- name: "Run zizmor" - name: "Run zizmor"
uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2 uses: zizmorcore/zizmor-action@0dce2577a4760a2749d8cfb7a84b7d5585ebcb7d # v0.5.0
with: with:
# there is a pass/fail gate as a repo ruleset (if there is no ruleset configured then the action will pass by default) config: .github/zizmor.yml
advanced-security: true # Disable SARIF upload so the step is a simple pass/fail gate
advanced-security: false
inputs: .github inputs: .github

View File

@ -14,23 +14,3 @@ affected versions, and, if known, mitigations for the issue.
All support will be made on a best effort basis, so please indicate the "urgency level" of the vulnerability as Critical, High, Medium or Low. All support will be made on a best effort basis, so please indicate the "urgency level" of the vulnerability as Critical, High, Medium or Low.
For more details, see our [security policy documentation](https://oss.anchore.com/docs/contributing/security/). For more details, see our [security policy documentation](https://oss.anchore.com/docs/contributing/security/).
## Trust Boundary
Syft is a tool to scan content and product an SBOM. Syft is not a tool designed to scan malicious content. Detecting and properly reporting on purposely malicious artifacts is outside the scope of Syft's expected operating environment.
There are many possible ways for malicious content to cause Syft to become confused or fail to include results in an SBOM. We do not consider this to be a security vulnerability.
**Examples**
- Removing or altering a package lock file
- Removing or altering an RPM or DEB database
- A malicious archive that Syft will skip but the runtime may not
- Self modifying systems that change state when running
We consider the security trust boundary for Syft to be anything that causes problems for the overall system running Syft, or Syft operating in a way that is dangerous to itself, the system, or the operator.
**Examples**
- Filling up temp space permanently
- Syft executing arbitrary code when scanning an artifact
- Syft leaking secrets from the environment or configuration files into logs or SBOMs
- Syft operating outside of the expected artifact or directory (directory traversal)

View File

@ -10,8 +10,7 @@ vars:
# v1: when fixtures were located at test-fixtures dirs # v1: when fixtures were located at test-fixtures dirs
# v2: migration to testdata dirs # v2: migration to testdata dirs
CACHE_REPO: oss-cache CACHE_IMAGE: ghcr.io/{{ .OWNER }}/{{ .PROJECT }}/test-fixture-cache:v2
CACHE_IMAGE: ghcr.io/{{ .OWNER }}/{{ .CACHE_REPO }}/syft-test-fixture-cache:v2
# static file dirs # static file dirs
TOOL_DIR: .tool TOOL_DIR: .tool
@ -425,7 +424,7 @@ tasks:
done done
oras_command+=" {{ .CACHE_PATHS_FILE }}" oras_command+=" {{ .CACHE_PATHS_FILE }}"
oras_command+=" --annotation org.opencontainers.image.source=https://github.com/{{ .OWNER }}/{{ .CACHE_REPO }}" oras_command+=" --annotation org.opencontainers.image.source=https://github.com/{{ .OWNER }}/{{ .PROJECT }}"
oras_command+=" --annotation fingerprint=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.digest')" oras_command+=" --annotation fingerprint=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.digest')"
echo "Executing: $oras_command" echo "Executing: $oras_command"

View File

@ -107,7 +107,7 @@ func fetchLatestApplicationVersion(id clio.Identification) (*hashiVersion.Versio
return nil, fmt.Errorf("HTTP %d on fetching latest version: %s", resp.StatusCode, resp.Status) return nil, fmt.Errorf("HTTP %d on fetching latest version: %s", resp.StatusCode, resp.Status)
} }
versionBytes, err := io.ReadAll(io.LimitReader(resp.Body, 500)) versionBytes, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read latest version: %w", err) return nil, fmt.Errorf("failed to read latest version: %w", err)
} }

View File

@ -94,7 +94,7 @@ func getVersion(resolver file.Resolver) (string, []file.Location, error) {
} }
defer internal.CloseAndLogError(reader, locations[0].RealPath) defer internal.CloseAndLogError(reader, locations[0].RealPath)
version, err := io.ReadAll(reader) //nolint:gocritic // example code version, err := io.ReadAll(reader)
if err != nil { if err != nil {
return "", nil, fmt.Errorf("unable to read alpine version: %w", err) return "", nil, fmt.Errorf("unable to read alpine version: %w", err)
} }
@ -117,7 +117,7 @@ func getAPKKeys(resolver file.Resolver) (map[string]string, []file.Location, err
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("unable to resolve file contents by location at %s: %w", location.RealPath, err) return nil, nil, fmt.Errorf("unable to resolve file contents by location at %s: %w", location.RealPath, err)
} }
content, err := io.ReadAll(reader) //nolint:gocritic // example code content, err := io.ReadAll(reader)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("unable to read apk key content at %s: %w", location.RealPath, err) return nil, nil, fmt.Errorf("unable to read apk key content at %s: %w", location.RealPath, err)
} }

108
go.mod
View File

@ -1,6 +1,6 @@
module github.com/anchore/syft module github.com/anchore/syft
go 1.25.8 go 1.25.6
require ( require (
github.com/BurntSushi/toml v1.6.0 github.com/BurntSushi/toml v1.6.0
@ -9,6 +9,7 @@ require (
github.com/Masterminds/sprig/v3 v3.3.0 github.com/Masterminds/sprig/v3 v3.3.0
github.com/OneOfOne/xxhash v1.2.8 github.com/OneOfOne/xxhash v1.2.8
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/acobaugh/osrelease v0.1.0
github.com/adrg/xdg v0.5.3 github.com/adrg/xdg v0.5.3
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9 github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9
github.com/anchore/clio v0.0.0-20250319180342-2cfe4b0cb716 github.com/anchore/clio v0.0.0-20250319180342-2cfe4b0cb716
@ -21,7 +22,7 @@ require (
github.com/anchore/go-sync v0.0.0-20250326131806-4eda43a485b6 github.com/anchore/go-sync v0.0.0-20250326131806-4eda43a485b6
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b 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/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115
github.com/anchore/stereoscope v0.1.22 github.com/anchore/stereoscope v0.1.21
github.com/aquasecurity/go-pep440-version v0.0.1 github.com/aquasecurity/go-pep440-version v0.0.1
github.com/bitnami/go-version v0.0.0-20250131085805-b1f57a8634ef github.com/bitnami/go-version v0.0.0-20250131085805-b1f57a8634ef
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
@ -37,19 +38,19 @@ require (
github.com/elliotchance/phpserialize v1.4.0 github.com/elliotchance/phpserialize v1.4.0
github.com/facebookincubator/nvdtools v0.1.5 github.com/facebookincubator/nvdtools v0.1.5
github.com/github/go-spdx/v2 v2.4.0 github.com/github/go-spdx/v2 v2.4.0
github.com/gkampitakis/go-snaps v0.5.21 github.com/gkampitakis/go-snaps v0.5.20
github.com/go-git/go-billy/v5 v5.8.0 github.com/go-git/go-billy/v5 v5.8.0
github.com/go-git/go-git/v5 v5.17.0 github.com/go-git/go-git/v5 v5.17.0
github.com/go-test/deep v1.1.1 github.com/go-test/deep v1.1.1
github.com/go-viper/mapstructure/v2 v2.5.0 github.com/go-viper/mapstructure/v2 v2.5.0
github.com/gohugoio/hashstructure v0.6.0 github.com/gohugoio/hashstructure v0.6.0
github.com/google/go-cmp v0.7.0 github.com/google/go-cmp v0.7.0
github.com/google/go-containerregistry v0.21.2 github.com/google/go-containerregistry v0.21.1
github.com/google/licensecheck v0.3.1 github.com/google/licensecheck v0.3.1
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/gookit/color v1.6.0 github.com/gookit/color v1.6.0
github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-cleanhttp v0.5.2
github.com/hashicorp/go-getter v1.8.5 github.com/hashicorp/go-getter v1.8.4
github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/hcl/v2 v2.24.0 github.com/hashicorp/hcl/v2 v2.24.0
github.com/iancoleman/strcase v0.3.0 github.com/iancoleman/strcase v0.3.0
@ -61,7 +62,7 @@ require (
github.com/mholt/archives v0.1.5 github.com/mholt/archives v0.1.5
github.com/moby/sys/mountinfo v0.7.2 github.com/moby/sys/mountinfo v0.7.2
github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1
github.com/olekukonko/tablewriter v1.1.4 github.com/olekukonko/tablewriter v1.1.3
github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/go-digest v1.0.0
github.com/pelletier/go-toml v1.9.5 github.com/pelletier/go-toml v1.9.5
github.com/quasilyte/go-ruleguard/dsl v0.3.23 github.com/quasilyte/go-ruleguard/dsl v0.3.23
@ -86,24 +87,24 @@ require (
go.uber.org/goleak v1.3.0 go.uber.org/goleak v1.3.0
go.yaml.in/yaml/v3 v3.0.4 go.yaml.in/yaml/v3 v3.0.4
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546
golang.org/x/mod v0.34.0 golang.org/x/mod v0.33.0
golang.org/x/net v0.52.0 golang.org/x/net v0.51.0
modernc.org/sqlite v1.46.2 modernc.org/sqlite v1.46.1
) )
require ( require (
cloud.google.com/go v0.123.0 // indirect cloud.google.com/go v0.123.0 // indirect
cloud.google.com/go/auth v0.18.1 // indirect cloud.google.com/go/auth v0.17.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.9.0 // indirect cloud.google.com/go/compute/metadata v0.9.0 // indirect
cloud.google.com/go/iam v1.5.3 // indirect cloud.google.com/go/iam v1.5.3 // indirect
cloud.google.com/go/storage v1.60.0 // indirect cloud.google.com/go/storage v1.58.0 // indirect
dario.cat/mergo v1.0.2 // indirect dario.cat/mergo v1.0.2 // indirect
github.com/DataDog/zstd v1.5.5 // indirect github.com/DataDog/zstd v1.5.5 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/Microsoft/hcsshim v0.14.0-rc.1 // indirect github.com/Microsoft/hcsshim v0.14.0-rc.1 // indirect
github.com/ProtonMail/go-crypto v1.4.0 // indirect github.com/ProtonMail/go-crypto v1.3.0 // indirect
github.com/STARRY-S/zip v0.2.3 // indirect github.com/STARRY-S/zip v0.2.3 // indirect
github.com/agext/levenshtein v1.2.1 // indirect; indirectt github.com/agext/levenshtein v1.2.1 // indirect; indirectt
github.com/anchore/go-lzo v0.1.0 // indirect github.com/anchore/go-lzo v0.1.0 // indirect
@ -136,7 +137,7 @@ require (
github.com/containerd/typeurl/v2 v2.2.3 // indirect github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/cyphar/filepath-securejoin v0.6.0 // indirect github.com/cyphar/filepath-securejoin v0.6.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/docker/cli v29.3.0+incompatible // indirect github.com/docker/cli v29.2.1+incompatible // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.5 // indirect github.com/docker/docker-credential-helpers v0.9.5 // indirect
github.com/docker/go-connections v0.6.0 // indirect github.com/docker/go-connections v0.6.0 // indirect
@ -159,8 +160,8 @@ require (
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect
github.com/google/s2a-go v0.1.9 // indirect github.com/google/s2a-go v0.1.9 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.11 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.7 // indirect
github.com/googleapis/gax-go/v2 v2.17.0 // indirect github.com/googleapis/gax-go/v2 v2.15.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-version v1.8.0 // indirect github.com/hashicorp/go-version v1.8.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
@ -221,7 +222,7 @@ require (
github.com/spf13/viper v1.20.0 // indirect github.com/spf13/viper v1.20.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.6.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect
github.com/sylabs/sif/v2 v2.24.0 // indirect github.com/sylabs/sif/v2 v2.23.0 // indirect
github.com/sylabs/squashfs v1.0.6 // indirect github.com/sylabs/squashfs v1.0.6 // indirect
github.com/therootcompany/xz v1.0.1 // indirect github.com/therootcompany/xz v1.0.1 // indirect
github.com/tidwall/gjson v1.18.0 // indirect github.com/tidwall/gjson v1.18.0 // indirect
@ -246,30 +247,29 @@ require (
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect
golang.org/x/crypto v0.49.0 // indirect golang.org/x/crypto v0.48.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect golang.org/x/oauth2 v0.35.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.42.0 // indirect golang.org/x/sys v0.41.0 // indirect
golang.org/x/term v0.41.0 // indirect golang.org/x/term v0.40.0 // indirect
golang.org/x/text v0.35.0 // indirect golang.org/x/text v0.34.0 // indirect
golang.org/x/time v0.15.0 golang.org/x/time v0.14.0
golang.org/x/tools v0.43.0 golang.org/x/tools v0.42.0
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/api v0.267.0 // indirect google.golang.org/api v0.256.0 // indirect
google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 // indirect google.golang.org/genproto v0.0.0-20250922171735-9219d122eba9 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260203192932-546029d2fa20 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba // indirect
google.golang.org/grpc v1.79.3 // indirect google.golang.org/grpc v1.76.0 // indirect
google.golang.org/protobuf v1.36.11 // indirect google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
modernc.org/libc v1.70.0 // indirect modernc.org/libc v1.67.6 // indirect
modernc.org/mathutil v1.7.1 // indirect modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect modernc.org/memory v1.11.0 // indirect
) )
require ( require (
github.com/acobaugh/osrelease v0.1.0
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
github.com/cespare/xxhash/v2 v2.3.0 github.com/cespare/xxhash/v2 v2.3.0
github.com/gpustack/gguf-parser-go v0.24.0 github.com/gpustack/gguf-parser-go v0.24.0
@ -277,12 +277,12 @@ require (
) )
require ( require (
cel.dev/expr v0.25.1 // indirect cel.dev/expr v0.24.0 // indirect
cloud.google.com/go/monitoring v1.24.3 // indirect cloud.google.com/go/monitoring v1.24.2 // indirect
cyphar.com/go-pathrs v0.2.1 // indirect cyphar.com/go-pathrs v0.2.1 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.54.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.54.0 // indirect
github.com/aws/aws-sdk-go-v2 v1.41.2 // indirect github.com/aws/aws-sdk-go-v2 v1.41.2 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 // indirect
github.com/aws/aws-sdk-go-v2/config v1.32.10 // indirect github.com/aws/aws-sdk-go-v2/config v1.32.10 // indirect
@ -291,44 +291,46 @@ require (
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.18 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.18 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.17 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.16 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.8 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.7 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.17 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.16 // indirect
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.0 // indirect github.com/aws/aws-sdk-go-v2/service/s3 v1.95.0 // indirect
github.com/aws/aws-sdk-go-v2/service/signin v1.0.6 // indirect github.com/aws/aws-sdk-go-v2/service/signin v1.0.6 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.30.11 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.30.11 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.15 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.15 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.41.7 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.41.7 // indirect
github.com/aws/smithy-go v1.24.1 // indirect github.com/aws/smithy-go v1.24.1 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.2 // indirect github.com/buger/jsonparser v1.1.1 // indirect
github.com/clipperhouse/displaywidth v0.10.0 // indirect github.com/clipperhouse/displaywidth v0.9.0 // indirect
github.com/clipperhouse/uax29/v2 v2.6.0 // indirect github.com/clipperhouse/stringish v0.1.1 // indirect
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect github.com/clipperhouse/uax29/v2 v2.5.0 // indirect
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect
github.com/containerd/cgroups/v3 v3.1.2 // indirect github.com/containerd/cgroups/v3 v3.1.2 // indirect
github.com/containerd/containerd/v2 v2.2.1 // indirect github.com/containerd/containerd/v2 v2.2.1 // indirect
github.com/containerd/plugin v1.0.0 // indirect github.com/containerd/plugin v1.0.0 // indirect
github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
github.com/go-jose/go-jose/v4 v4.1.3 // indirect github.com/go-jose/go-jose/v4 v4.1.2 // indirect
github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.70 // indirect github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.70 // indirect
github.com/henvic/httpretty v0.1.4 // indirect github.com/henvic/httpretty v0.1.4 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
github.com/moby/moby/api v1.54.0 // indirect github.com/moby/moby/api v1.53.0 // indirect
github.com/moby/moby/client v0.3.0 // indirect github.com/moby/moby/client v0.2.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/nwaples/rardecode/v2 v2.2.0 // indirect github.com/nwaples/rardecode/v2 v2.2.0 // indirect
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect
github.com/olekukonko/errors v1.2.0 // indirect github.com/olekukonko/errors v1.1.0 // indirect
github.com/olekukonko/ll v0.1.6 // 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/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d // indirect github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d // indirect
github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect github.com/zeebo/errs v1.4.0 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.36.0 // indirect
go.opentelemetry.io/otel/sdk v1.40.0 // indirect go.opentelemetry.io/otel/sdk v1.40.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.40.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.40.0 // indirect
gonum.org/v1/gonum v0.16.0 // indirect gonum.org/v1/gonum v0.16.0 // indirect

244
go.sum
View File

@ -1,5 +1,5 @@
cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
@ -31,8 +31,8 @@ cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0c
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
cloud.google.com/go/auth v0.18.1 h1:IwTEx92GFUo2pJ6Qea0EU3zYvKnTAeRCODxfA/G5UWs= cloud.google.com/go/auth v0.17.0 h1:74yCm7hCj2rUyyAocqnFzsAYXgJhrG26XCFimrc/Kz4=
cloud.google.com/go/auth v0.18.1/go.mod h1:GfTYoS9G3CWpRA3Va9doKN9mjPGRS+v41jmZAhBzbrA= cloud.google.com/go/auth v0.17.0/go.mod h1:6wv/t5/6rOPAX4fJiRjKkJCvswLwdet7G8+UGXt7nCQ=
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
@ -48,12 +48,12 @@ cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1
cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
cloud.google.com/go/iam v1.5.3 h1:+vMINPiDF2ognBJ97ABAYYwRgsaqxPbQDlMnbHMjolc= cloud.google.com/go/iam v1.5.3 h1:+vMINPiDF2ognBJ97ABAYYwRgsaqxPbQDlMnbHMjolc=
cloud.google.com/go/iam v1.5.3/go.mod h1:MR3v9oLkZCTlaqljW6Eb2d3HGDGK5/bDv93jhfISFvU= cloud.google.com/go/iam v1.5.3/go.mod h1:MR3v9oLkZCTlaqljW6Eb2d3HGDGK5/bDv93jhfISFvU=
cloud.google.com/go/logging v1.13.1 h1:O7LvmO0kGLaHY/gq8cV7T0dyp6zJhYAOtZPX4TF3QtY= cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc=
cloud.google.com/go/logging v1.13.1/go.mod h1:XAQkfkMBxQRjQek96WLPNze7vsOmay9H5PqfsNYDqvw= cloud.google.com/go/logging v1.13.0/go.mod h1:36CoKh6KA/M0PbhPKMq6/qety2DCAErbhXT62TuXALA=
cloud.google.com/go/longrunning v0.8.0 h1:LiKK77J3bx5gDLi4SMViHixjD2ohlkwBi+mKA7EhfW8= cloud.google.com/go/longrunning v0.7.0 h1:FV0+SYF1RIj59gyoWDRi45GiYUMM3K1qO51qoboQT1E=
cloud.google.com/go/longrunning v0.8.0/go.mod h1:UmErU2Onzi+fKDg2gR7dusz11Pe26aknR4kHmJJqIfk= cloud.google.com/go/longrunning v0.7.0/go.mod h1:ySn2yXmjbK9Ba0zsQqunhDkYi0+9rlXIwnoAf+h+TPY=
cloud.google.com/go/monitoring v1.24.3 h1:dde+gMNc0UhPZD1Azu6at2e79bfdztVDS5lvhOdsgaE= cloud.google.com/go/monitoring v1.24.2 h1:5OTsoJ1dXYIiMiuL+sYscLc9BumrL3CarVLL7dd7lHM=
cloud.google.com/go/monitoring v1.24.3/go.mod h1:nYP6W0tm3N9H/bOw8am7t62YTzZY+zUeQ+Bi6+2eonI= cloud.google.com/go/monitoring v1.24.2/go.mod h1:x7yzPWcgDRnPEv3sI+jJGBkwl5qINf+6qY4eq0I9B4U=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
@ -63,10 +63,10 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.60.0 h1:oBfZrSOCimggVNz9Y/bXY35uUcts7OViubeddTTVzQ8= cloud.google.com/go/storage v1.58.0 h1:PflFXlmFJjG/nBeR9B7pKddLQWaFaRWx4uUi/LyNxxo=
cloud.google.com/go/storage v1.60.0/go.mod h1:q+5196hXfejkctrnx+VYU8RKQr/L3c0cBIlrjmiAKE0= cloud.google.com/go/storage v1.58.0/go.mod h1:cMWbtM+anpC74gn6qjLh+exqYcfmB9Hqe5z6adx+CLI=
cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U= cloud.google.com/go/trace v1.11.6 h1:2O2zjPzqPYAHrn3OKl029qlqG6W8ZdYaOWRyr8NgMT4=
cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= cloud.google.com/go/trace v1.11.6/go.mod h1:GA855OeDEBiBMzcckLPE2kDunIpC72N+Pq8WFieFjnI=
cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8= cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8=
cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc= cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
@ -84,14 +84,14 @@ github.com/CycloneDX/cyclonedx-go v0.10.0/go.mod h1:vUvbCXQsEm48OI6oOlanxstwNByX
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ=
github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 h1:sBEjpZlNHzK1voKq9695PJSX2o5NEXl7/OL3coiIY0c= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 h1:UQUsRi8WTzhZntp5313l+CHIAT95ojUI2lpP/ExlZa4=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0/go.mod h1:Cz6ft6Dkn3Et6l2v2a9/RpN7epQ1GtDlO6lj8bEcOvw=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 h1:UnDZ/zFfG1JhH/DqxIZYU/1CUAlTUScoXD/LcM2Ykk8= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.54.0 h1:lhhYARPUu3LmHysQ/igznQphfzynnqI3D75oUyw1HXk=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0/go.mod h1:IA1C1U7jO/ENqm/vhi7V9YYpBsp+IMyqNrEN94N7tVc= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.54.0/go.mod h1:l9rva3ApbBpEJxSNYnwT9N4CDLrWgtq3u8736C5hyJw=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.55.0 h1:7t/qx5Ost0s0wbA/VDrByOooURhp+ikYwv20i9Y07TQ= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.54.0 h1:xfK3bbi6F2RDtaZFtUdKO3osOBIhNb+xTs8lFW6yx9o=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.55.0/go.mod h1:vB2GH9GAYYJTO3mEn8oYwzEdhlayZIdQz6zdzgUIRvA= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.54.0/go.mod h1:vB2GH9GAYYJTO3mEn8oYwzEdhlayZIdQz6zdzgUIRvA=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 h1:0s6TxfCu2KHkkZPnBfsQ2y5qia0jl3MMrmBhu3nCOYk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.54.0 h1:s0WlVbf9qpvkh1c/uDAPElam0WrL7fHRIidgZJ7UqZI=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0/go.mod h1:Mf6O40IAyB9zR/1J8nGDDPirZQQPbYJni8Yisy7NTMc= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.54.0/go.mod h1:Mf6O40IAyB9zR/1J8nGDDPirZQQPbYJni8Yisy7NTMc=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
@ -106,8 +106,8 @@ github.com/Microsoft/hcsshim v0.14.0-rc.1/go.mod h1:hTKFGbnDtQb1wHiOWv4v0eN+7boS
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/ProtonMail/go-crypto v1.4.0 h1:Zq/pbM3F5DFgJiMouxEdSVY44MVoQNEKp5d5QxIQceQ= github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
github.com/ProtonMail/go-crypto v1.4.0/go.mod h1:e1OaTyu5SYVrO9gKOEhTc+5UcXtTUa+P3uLudwcgPqo= github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
github.com/STARRY-S/zip v0.2.3 h1:luE4dMvRPDOWQdeDdUxUoZkzUIpTccdKdhHHsQJ1fm4= github.com/STARRY-S/zip v0.2.3 h1:luE4dMvRPDOWQdeDdUxUoZkzUIpTccdKdhHHsQJ1fm4=
github.com/STARRY-S/zip v0.2.3/go.mod h1:lqJ9JdeRipyOQJrYSOtpNAiaesFO6zVDsE8GIGFaoSk= github.com/STARRY-S/zip v0.2.3/go.mod h1:lqJ9JdeRipyOQJrYSOtpNAiaesFO6zVDsE8GIGFaoSk=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
@ -148,8 +148,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/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 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/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115/go.mod h1:KoYIv7tdP5+CC9VGkeZV4/vGCKsY55VvoG+5dadg4YI=
github.com/anchore/stereoscope v0.1.22 h1:L807G/kk0WZzOCGuRGF7knxMKzwW2PGdbPVRystryd8= github.com/anchore/stereoscope v0.1.21 h1:rIwPDjJQdOdIvMrkNyZFkUS5dSyQPDjAwUqU0XjVF74=
github.com/anchore/stereoscope v0.1.22/go.mod h1:FikPtAb/WnbqwgLHAvQA9O+fWez0K4pbjxzghz++iy4= github.com/anchore/stereoscope v0.1.21/go.mod h1:8652axKmO8itOcGX8gzAvHW3cVWvbxpJ4woLNMEO4a0=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= 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 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
@ -187,18 +187,18 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18 h1:xCeWVjj0ki0l3nruoy
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18/go.mod h1:r/eLGuGCBw6l36ZRWiw6PaZwPXb6YOj+i/7MizNl5/k= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18/go.mod h1:r/eLGuGCBw6l36ZRWiw6PaZwPXb6YOj+i/7MizNl5/k=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.17 h1:JqcdRG//czea7Ppjb+g/n4o8i/R50aTBHkA7vu0lK+k= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.16 h1:CjMzUs78RDDv4ROu3JnJn/Ig1r6ZD7/T2DXLLRpejic=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.17/go.mod h1:CO+WeGmIdj/MlPel2KwID9Gt7CNq4M65HUfBW97liM0= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.16/go.mod h1:uVW4OLBqbJXSHJYA9svT9BluSvvwbzLQ2Crf6UPzR3c=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5 h1:CeY9LUdur+Dxoeldqoun6y4WtJ3RQtzk0JMP2gfUay0= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5 h1:CeY9LUdur+Dxoeldqoun6y4WtJ3RQtzk0JMP2gfUay0=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5/go.mod h1:AZLZf2fMaahW5s/wMRciu1sYbdsikT/UHwbUjOdEVTc= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5/go.mod h1:AZLZf2fMaahW5s/wMRciu1sYbdsikT/UHwbUjOdEVTc=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.8 h1:Z5EiPIzXKewUQK0QTMkutjiaPVeVYXX7KIqhXu/0fXs= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.7 h1:DIBqIrJ7hv+e4CmIk2z3pyKT+3B6qVMgRsawHiR3qso=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.8/go.mod h1:FsTpJtvC4U1fyDXk7c71XoDv3HlRm8V3NiYLeYLh5YE= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.7/go.mod h1:vLm00xmBke75UmpNvOcZQ/Q30ZFjbczeLFqGx5urmGo=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18 h1:LTRCYFlnnKFlKsyIQxKhJuDuA3ZkrDQMRYm6rXiHlLY= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18 h1:LTRCYFlnnKFlKsyIQxKhJuDuA3ZkrDQMRYm6rXiHlLY=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18/go.mod h1:XhwkgGG6bHSd00nO/mexWTcTjgd6PjuvWQMqSn2UaEk= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18/go.mod h1:XhwkgGG6bHSd00nO/mexWTcTjgd6PjuvWQMqSn2UaEk=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.17 h1:bGeHBsGZx0Dvu/eJC0Lh9adJa3M1xREcndxLNZlve2U= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.16 h1:NSbvS17MlI2lurYgXnCOLvCFX38sBW4eiVER7+kkgsU=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.17/go.mod h1:dcW24lbU0CzHusTE8LLHhRLI42ejmINN8Lcr22bwh/g= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.16/go.mod h1:SwT8Tmqd4sA6G1qaGdzWCJN99bUmPGHfRwwq3G5Qb+A=
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.0 h1:oeu8VPlOre74lBA/PMhxa5vewaMIMmILM+RraSyB8KA= github.com/aws/aws-sdk-go-v2/service/s3 v1.95.0 h1:MIWra+MSq53CFaXXAywB2qg9YvVZifkk6vEGl/1Qor0=
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.0/go.mod h1:5jggDlZ2CLQhwJBiZJb4vfk4f0GxWdEDruWKEJ1xOdo= github.com/aws/aws-sdk-go-v2/service/s3 v1.95.0/go.mod h1:79S2BdqCJpScXZA2y+cpZuocWsjGjJINyXnOsf5DTz8=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.6 h1:MzORe+J94I+hYu2a6XmV5yC9huoTv8NRcCrUNedDypQ= github.com/aws/aws-sdk-go-v2/service/signin v1.0.6 h1:MzORe+J94I+hYu2a6XmV5yC9huoTv8NRcCrUNedDypQ=
github.com/aws/aws-sdk-go-v2/service/signin v1.0.6/go.mod h1:hXzcHLARD7GeWnifd8j9RWqtfIgxj4/cAtIVIK7hg8g= github.com/aws/aws-sdk-go-v2/service/signin v1.0.6/go.mod h1:hXzcHLARD7GeWnifd8j9RWqtfIgxj4/cAtIVIK7hg8g=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.11 h1:7oGD8KPfBOJGXiCoRKrrrQkbvCp8N++u36hrLMPey6o= github.com/aws/aws-sdk-go-v2/service/sso v1.30.11 h1:7oGD8KPfBOJGXiCoRKrrrQkbvCp8N++u36hrLMPey6o=
@ -237,8 +237,8 @@ github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4=
github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM= github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
github.com/buger/jsonparser v1.1.2 h1:frqHqw7otoVbk5M8LlE/L7HTnIq2v9RX6EJ48i9AxJk= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.2/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
@ -276,10 +276,12 @@ 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/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/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/clipperhouse/displaywidth v0.10.0 h1:GhBG8WuerxjFQQYeuZAeVTuyxuX+UraiZGD4HJQ3Y8g= github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA=
github.com/clipperhouse/displaywidth v0.10.0/go.mod h1:XqJajYsaiEwkxOj4bowCTMcT1SgvHo9flfF3jQasdbs= github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA=
github.com/clipperhouse/uax29/v2 v2.6.0 h1:z0cDbUV+aPASdFb2/ndFnS9ts/WNXgTNNGFoKXuhpos= github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
github.com/clipperhouse/uax29/v2 v2.6.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U=
github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
@ -292,8 +294,8 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv1aFbZMiM9vblcSArJRf2Irls=
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
github.com/containerd/cgroups/v3 v3.1.2 h1:OSosXMtkhI6Qove637tg1XgK4q+DhR0mX8Wi8EhrHa4= github.com/containerd/cgroups/v3 v3.1.2 h1:OSosXMtkhI6Qove637tg1XgK4q+DhR0mX8Wi8EhrHa4=
github.com/containerd/cgroups/v3 v3.1.2/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= github.com/containerd/cgroups/v3 v3.1.2/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw=
github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o= github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o=
@ -343,8 +345,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/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 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c=
github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0=
github.com/docker/cli v29.3.0+incompatible h1:z3iWveU7h19Pqx7alZES8j+IeFQZ1lhTwb2F+V9SVvk= github.com/docker/cli v29.2.1+incompatible h1:n3Jt0QVCN65eiVBoUTZQM9mcQICCJt3akW4pKAbKdJg=
github.com/docker/cli v29.3.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v29.2.1+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 h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY= github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY=
@ -375,16 +377,16 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M=
github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA=
github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A=
github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98= github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw=
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI=
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4= github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8=
github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/facebookincubator/flog v0.0.0-20190930132826-d2511d0ce33c/go.mod h1:QGzNH9ujQ2ZUr/CjDGZGWeDAVStrWNjHeEcjJL96Nuk= github.com/facebookincubator/flog v0.0.0-20190930132826-d2511d0ce33c/go.mod h1:QGzNH9ujQ2ZUr/CjDGZGWeDAVStrWNjHeEcjJL96Nuk=
@ -414,8 +416,8 @@ github.com/github/go-spdx/v2 v2.4.0 h1:+4IwVwJJbm3rzvrQ6P1nI9BDMcy3la4RchRy5uehV
github.com/github/go-spdx/v2 v2.4.0/go.mod h1:/5rwgS0txhGtRdUZwc02bTglzg6HK3FfuEbECKlK2Sg= github.com/github/go-spdx/v2 v2.4.0/go.mod h1:/5rwgS0txhGtRdUZwc02bTglzg6HK3FfuEbECKlK2Sg=
github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs= github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs=
github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo= github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo=
github.com/gkampitakis/go-snaps v0.5.21 h1:SvhSFeZviQXwlT+dnGyAIATVehkhqRVW6qfQZhCZH+Y= github.com/gkampitakis/go-snaps v0.5.20 h1:FGKonEeQPJ12t7RQj6cTPa881fl5c8HYarMLv5vP7sg=
github.com/gkampitakis/go-snaps v0.5.21/go.mod h1:gC3YqxQTPyIXvQrw/Vpt3a8VqR1MO8sVpZFWN4DGwNs= github.com/gkampitakis/go-snaps v0.5.20/go.mod h1:gC3YqxQTPyIXvQrw/Vpt3a8VqR1MO8sVpZFWN4DGwNs=
github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4= github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4=
github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3q+ihjqxC9u0= github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3q+ihjqxC9u0=
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
@ -431,8 +433,8 @@ github.com/go-git/go-git/v5 v5.17.0/go.mod h1:f82C4YiLx+Lhi8eHxltLeGC5uBTXSFa6PC
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= github.com/go-jose/go-jose/v4 v4.1.2 h1:TK/7NqRQZfgAh+Td8AlsrvtPoUyiHh0LqVvokh+1vHI=
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-jose/go-jose/v4 v4.1.2/go.mod h1:22cg9HWM1pOlnRiY+9cQYJ9XHmya1bYW8OeDM6Ku6Oo=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@ -513,8 +515,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-containerregistry v0.21.2 h1:vYaMU4nU55JJGFC9JR/s8NZcTjbE9DBBbvusTW9NeS0= github.com/google/go-containerregistry v0.21.1 h1:sOt/o9BS2b87FnR7wxXPvRKU1XVJn2QCwOS5g8zQXlc=
github.com/google/go-containerregistry v0.21.2/go.mod h1:ctO5aCaewH4AK1AumSF5DPW+0+R+d2FmylMJdp5G7p0= github.com/google/go-containerregistry v0.21.1/go.mod h1:ctO5aCaewH4AK1AumSF5DPW+0+R+d2FmylMJdp5G7p0=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/licensecheck v0.3.1 h1:QoxgoDkaeC4nFrtGN1jV7IPmDCHFNIVh54e5hSt6sPs= github.com/google/licensecheck v0.3.1 h1:QoxgoDkaeC4nFrtGN1jV7IPmDCHFNIVh54e5hSt6sPs=
github.com/google/licensecheck v0.3.1/go.mod h1:ORkR35t/JjW+emNKtfJDII0zlciG9JgbT7SmsohlHmY= github.com/google/licensecheck v0.3.1/go.mod h1:ORkR35t/JjW+emNKtfJDII0zlciG9JgbT7SmsohlHmY=
@ -549,14 +551,14 @@ github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.11 h1:vAe81Msw+8tKUxi2Dqh/NZMz7475yUvmRIkXr4oN2ao= github.com/googleapis/enterprise-certificate-proxy v0.3.7 h1:zrn2Ee/nWmHulBx5sAVrGgAa0f2/R35S4DJwfFaUPFQ=
github.com/googleapis/enterprise-certificate-proxy v0.3.11/go.mod h1:RFV7MUdlb7AgEq2v7FmMCfeSMCllAzWxFgRdusoGks8= github.com/googleapis/enterprise-certificate-proxy v0.3.7/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
github.com/googleapis/gax-go/v2 v2.17.0 h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc= github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo=
github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY= github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc=
github.com/gookit/assert v0.1.1 h1:lh3GcawXe/p+cU7ESTZ5Ui3Sm/x8JWpIis4/1aF0mY0= github.com/gookit/assert v0.1.1 h1:lh3GcawXe/p+cU7ESTZ5Ui3Sm/x8JWpIis4/1aF0mY0=
github.com/gookit/assert v0.1.1/go.mod h1:jS5bmIVQZTIwk42uXl4lyj4iaaxx32tqH16CFj0VX2E= github.com/gookit/assert v0.1.1/go.mod h1:jS5bmIVQZTIwk42uXl4lyj4iaaxx32tqH16CFj0VX2E=
github.com/gookit/color v1.2.5/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg= github.com/gookit/color v1.2.5/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg=
@ -576,8 +578,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-getter v1.8.5 h1:DMPV5CSw5JrNg/IK7kDZt3+l2REKXOi3oAw7uYLh2NM= github.com/hashicorp/go-getter v1.8.4 h1:hGEd2xsuVKgwkMtPVufq73fAmZU/x65PPcqH3cb0D9A=
github.com/hashicorp/go-getter v1.8.5/go.mod h1:WIffejwAyDSJhoVptc3UEshEMkR9O63rw34V7k43O3Q= github.com/hashicorp/go-getter v1.8.4/go.mod h1:x27pPGSg9kzoB147QXI8d/nDvp2IgYGcwuRjpaXE9Yg=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
@ -725,10 +727,10 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/moby/api v1.54.0 h1:7kbUgyiKcoBhm0UrWbdrMs7RX8dnwzURKVbZGy2GnL0= github.com/moby/moby/api v1.53.0 h1:PihqG1ncw4W+8mZs69jlwGXdaYBeb5brF6BL7mPIS/w=
github.com/moby/moby/api v1.54.0/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc= github.com/moby/moby/api v1.53.0/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc=
github.com/moby/moby/client v0.3.0 h1:UUGL5okry+Aomj3WhGt9Aigl3ZOxZGqR7XPo+RLPlKs= github.com/moby/moby/client v0.2.2 h1:Pt4hRMCAIlyjL3cr8M5TrXCwKzguebPAc2do2ur7dEM=
github.com/moby/moby/client v0.3.0/go.mod h1:HJgFbJRvogDQjbM8fqc1MCEm4mIAGMLjXbgwoZp6jCQ= github.com/moby/moby/client v0.2.2/go.mod h1:2EkIPVNCqR05CMIzL1mfA07t0HvVUUOl85pasRz/GmQ=
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
@ -764,12 +766,12 @@ github.com/nwaples/rardecode/v2 v2.2.0 h1:4ufPGHiNe1rYJxYfehALLjup4Ls3ck42CWwjKi
github.com/nwaples/rardecode/v2 v2.2.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw= github.com/nwaples/rardecode/v2 v2.2.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw=
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc= github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc=
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0= github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0=
github.com/olekukonko/errors v1.2.0 h1:10Zcn4GeV59t/EGqJc8fUjtFT/FuUh5bTMzZ1XwmCRo= github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM=
github.com/olekukonko/errors v1.2.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
github.com/olekukonko/ll v0.1.6 h1:lGVTHO+Qc4Qm+fce/2h2m5y9LvqaW+DCN7xW9hsU3uA= github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0 h1:jrYnow5+hy3WRDCBypUFvVKNSPPCdqgSXIE9eJDD8LM=
github.com/olekukonko/ll v0.1.6/go.mod h1:NVUmjBb/aCtUpjKk75BhWrOlARz3dqsM+OtszpY4o88= github.com/olekukonko/ll v0.1.4-0.20260115111900-9e59c2286df0/go.mod h1:b52bVQRRPObe+yyBl0TxNfhesL0nedD4Cht0/zx55Ew=
github.com/olekukonko/tablewriter v1.1.4 h1:ORUMI3dXbMnRlRggJX3+q7OzQFDdvgbN9nVWj1drm6I= github.com/olekukonko/tablewriter v1.1.3 h1:VSHhghXxrP0JHl+0NnKid7WoEmd9/urKRJLysb70nnA=
github.com/olekukonko/tablewriter v1.1.4/go.mod h1:+kedxuyTtgoZLwif3P1Em4hARJs+mVnzKxmsCL/C5RY= 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 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
@ -900,8 +902,8 @@ github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3A
github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM=
github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY= github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY=
github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE=
github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
@ -923,8 +925,8 @@ github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/sylabs/sif/v2 v2.24.0 h1:1wB5uMDUQYjk8AckTySaDcP9YnpMb1LyDRr1Jt9A10w= github.com/sylabs/sif/v2 v2.23.0 h1:VWJC7iryINdIgyIK8EdxMCJkx8EDPVlvFaskgY+ruFk=
github.com/sylabs/sif/v2 v2.24.0/go.mod h1:DbXWqWZ1hdLSU+K9ipdds5AmZeHWsyxCOj/oQakBa88= github.com/sylabs/sif/v2 v2.23.0/go.mod h1:0UJk7MMSQS2n/95yYd+CvAfK7K2mE0aWHRYYybd+ouw=
github.com/sylabs/squashfs v1.0.6 h1:PvJcDzxr+vIm2kH56mEMbaOzvGu79gK7P7IX+R7BDZI= github.com/sylabs/squashfs v1.0.6 h1:PvJcDzxr+vIm2kH56mEMbaOzvGu79gK7P7IX+R7BDZI=
github.com/sylabs/squashfs v1.0.6/go.mod h1:DlDeUawVXLWAsSRa085Eo0ZenGzAB32JdAUFaB0LZfE= github.com/sylabs/squashfs v1.0.6/go.mod h1:DlDeUawVXLWAsSRa085Eo0ZenGzAB32JdAUFaB0LZfE=
github.com/terminalstatic/go-xsd-validate v0.1.6 h1:TenYeQ3eY631qNi1/cTmLH/s2slHPRKTTHT+XSHkepo= github.com/terminalstatic/go-xsd-validate v0.1.6 h1:TenYeQ3eY631qNi1/cTmLH/s2slHPRKTTHT+XSHkepo=
@ -982,6 +984,8 @@ github.com/zclconf/go-cty v1.16.3 h1:osr++gw2T61A8KVYHoQiFbFd1Lh3JOCXc/jFLJXKTxk
github.com/zclconf/go-cty v1.16.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= github.com/zclconf/go-cty v1.16.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo=
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM=
github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM=
github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1 h1:V+UsotZpAVvfj3X/LMoEytoLzSiP6Lg0F7wdVyu9gGg= github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1 h1:V+UsotZpAVvfj3X/LMoEytoLzSiP6Lg0F7wdVyu9gGg=
github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1/go.mod h1:ly2RBz4mnz1yeuVbQA/VFwGjK3mnHGRj1JuoG336Bis= github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1/go.mod h1:ly2RBz4mnz1yeuVbQA/VFwGjK3mnHGRj1JuoG336Bis=
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
@ -998,16 +1002,16 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/detectors/gcp v1.39.0 h1:kWRNZMsfBHZ+uHjiH4y7Etn2FK26LAGkNFw7RHv1DhE= go.opentelemetry.io/contrib/detectors/gcp v1.36.0 h1:F7q2tNlCaHY9nMKHR6XH9/qkp8FktLnIcy6jJNyOCQw=
go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= go.opentelemetry.io/contrib/detectors/gcp v1.36.0/go.mod h1:IbBN8uAIIx734PTonTPxAxnjc2pQTxWNkwfstZ+6H2k=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.39.0 h1:5gn2urDL/FBnK8OkCfD1j3/ER79rUuTYmCvlXBKeYL8= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.38.0 h1:wm/Q0GAAykXv83wzcKzGGqAnnfLFyFe7RslekZuv+VI=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.39.0/go.mod h1:0fBG6ZJxhqByfFZDwSwpZGzJU671HkwpWaNe2t4VUPI= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.38.0/go.mod h1:ra3Pa40+oKjvYh+ZD3EdxFZZB0xdMfuileHAm4nNN7w=
go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g= go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc= go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8= go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=
@ -1042,8 +1046,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -1083,8 +1087,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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= 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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1129,8 +1133,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-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.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.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 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-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1148,8 +1152,8 @@ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ=
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -1162,8 +1166,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -1238,13 +1242,13 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU= golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1255,13 +1259,13 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@ -1317,8 +1321,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.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/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.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s= golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1359,8 +1363,8 @@ google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdr
google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw=
google.golang.org/api v0.267.0 h1:w+vfWPMPYeRs8qH1aYYsFX68jMls5acWl/jocfLomwE= google.golang.org/api v0.256.0 h1:u6Khm8+F9sxbCTYNoBHg6/Hwv0N/i+V94MvkOSor6oI=
google.golang.org/api v0.267.0/go.mod h1:Jzc0+ZfLnyvXma3UtaTl023TdhZu6OMBP9tJ+0EmFD0= google.golang.org/api v0.256.0/go.mod h1:KIgPhksXADEKJlnEoRa9qAII4rXcy40vfI8HRqcU964=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -1431,12 +1435,12 @@ google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ6
google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= google.golang.org/genproto v0.0.0-20250922171735-9219d122eba9 h1:LvZVVaPE0JSqL+ZWb6ErZfnEOKIqqFWUJE2D0fObSmc=
google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= google.golang.org/genproto v0.0.0-20250922171735-9219d122eba9/go.mod h1:QFOrLhdAe2PsTp3vQY4quuLKTi9j3XG3r6JPPaw7MSc=
google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20 h1:7ei4lp52gK1uSejlA8AZl5AJjeLUOHBQscRQZUgAcu0= google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba h1:B14OtaXuMaCQsl2deSvNkyPKIzq3BjfxQp8d00QyWx4=
google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20/go.mod h1:ZdbssH/1SOVnjnDlXzxDHK2MCidiqXtbYccJNzNYPEE= google.golang.org/genproto/googleapis/api v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:G5IanEx8/PgI9w6CFcYQf7jMtHQhZruvfM1i3qOqk5U=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260203192932-546029d2fa20 h1:Jr5R2J6F6qWyzINc+4AM8t5pfUz6beZpHp678GNrMbE= google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba h1:UKgtfRM7Yh93Sya0Fo8ZzhDP4qBckrrxEr2oF5UIVb8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260203192932-546029d2fa20/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@ -1464,8 +1468,8 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@ -1514,18 +1518,18 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.0.1-2020.1.4/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.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis= modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=
modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.32.0 h1:hjG66bI/kqIPX1b2yT6fr/jt+QedtP2fqojG2VrFuVw= modernc.org/ccgo/v4 v4.30.1 h1:4r4U1J6Fhj98NKfSjnPUN7Ze2c6MnAdL0hWw6+LrJpc=
modernc.org/ccgo/v4 v4.32.0/go.mod h1:6F08EBCx5uQc38kMGl+0Nm0oWczoo1c7cgpzEry7Uc0= modernc.org/ccgo/v4 v4.30.1/go.mod h1:bIOeI1JL54Utlxn+LwrFyjCx2n2RDiYEaJVSrgdrRfM=
modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM= modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA=
modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU= 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 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo= modernc.org/gc/v3 v3.1.1 h1:k8T3gkXWY9sEiytKhcgyiZ2L0DTyCQ/nvX+LoCljoRE=
modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= 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 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.70.0 h1:U58NawXqXbgpZ/dcdS9kMshu08aiA6b7gusEusqzNkw= modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI=
modernc.org/libc v1.70.0/go.mod h1:OVmxFGP1CI/Z4L3E0Q3Mf1PDE0BucwMkcXjjLntvHJo= 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 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
@ -1534,8 +1538,8 @@ modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= 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 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.46.2 h1:gkXQ6R0+AjxFC/fTDaeIVLbNLNrRoOK7YYVz5BKhTcE= modernc.org/sqlite v1.46.1 h1:eFJ2ShBLIEnUWlLy12raN0Z1plqmFX9Qe3rjQTKt6sU=
modernc.org/sqlite v1.46.2/go.mod h1:hWjRO6Tj/5Ik8ieqxQybiEOUXy0NJFNp2tpvVpKlvig= modernc.org/sqlite v1.46.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=

View File

@ -215,7 +215,7 @@ func write(schema []byte) {
panic(err) panic(err)
} }
existingSchemaBytes, err := io.ReadAll(existingFh) //nolint:gocritic // offline code generator existingSchemaBytes, err := io.ReadAll(existingFh)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -10,7 +10,7 @@ func (s *scanner) FindEvidence(_ context.Context, reader io.Reader) (evidence []
return nil, nil, nil return nil, nil, nil
} }
content, err = io.ReadAll(reader) //nolint:gocritic // license scanner requires full content content, err = io.ReadAll(reader)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -31,7 +31,7 @@ func UpdateGoldenFileContents(t *testing.T, contents []byte) {
t.Log(dangerText("!!! UPDATING GOLDEN FILE !!!"), goldenFilePath) t.Log(dangerText("!!! UPDATING GOLDEN FILE !!!"), goldenFilePath)
err := os.WriteFile(goldenFilePath, contents, 0o600) err := os.WriteFile(goldenFilePath, contents, 0600)
if err != nil { if err != nil {
t.Fatalf("could not update golden file (%s): %+v", goldenFilePath, err) t.Fatalf("could not update golden file (%s): %+v", goldenFilePath, err)
} }
@ -50,9 +50,7 @@ func GetGoldenFileContents(t *testing.T) []byte {
} }
defer f.Close() defer f.Close()
// suppress lint prohibiting ReadAll since golden files are source files in Syft's repository bytes, err := io.ReadAll(f)
// and not user provided artifacts.
bytes, err := io.ReadAll(f) //nolint:gocritic // golden files are trusted source files, not user artifacts
if err != nil { if err != nil {
t.Fatalf("could not read file (%s): %+v", goldenPath, err) t.Fatalf("could not read file (%s): %+v", goldenPath, err)
} }

View File

@ -1,121 +0,0 @@
package tmpdir
import (
"context"
"fmt"
"os"
"sync"
"sync/atomic"
)
type ctxKey struct{}
// Root creates a new root temp directory with the given prefix and returns a context with the
// TempDir attached. Callers should defer Cleanup() on the returned TempDir to ensure all
// temp files are removed.
func Root(ctx context.Context, prefix string) (context.Context, *TempDir) {
td := &TempDir{prefix: prefix}
return context.WithValue(ctx, ctxKey{}, td), td
}
// FromPath creates a TempDir backed by an existing directory. The caller owns the lifecycle of
// the directory; Cleanup() is a no-op. This is useful for wrapping a directory from t.TempDir()
// where the test framework handles cleanup automatically.
func FromPath(dir string) *TempDir {
td := &TempDir{}
td.root = dir
td.initOnce.Do(func() {}) // mark as initialized
return td
}
// WithValue returns a new context with the given TempDir attached. Use this to inject an
// existing TempDir into a context (e.g., sharing a TempDir across multiple test contexts).
func WithValue(ctx context.Context, td *TempDir) context.Context {
return context.WithValue(ctx, ctxKey{}, td)
}
// FromContext returns the TempDir from the context, or nil if none is set.
func FromContext(ctx context.Context) *TempDir {
td, _ := ctx.Value(ctxKey{}).(*TempDir)
return td
}
// TempDir manages a tree of temporary directories. All files and child directories live under
// a single root path that can be removed in one shot via Cleanup(). After initialization, the
// struct has no mutable state — NewChild and NewFile delegate uniqueness to os.MkdirTemp and
// os.CreateTemp respectively, so no locking is needed on the hot path.
type TempDir struct {
prefix string
root string // set exactly once by initOnce
initOnce sync.Once
initErr error
cleanupOnce sync.Once
cleaned atomic.Bool
}
func noop() {}
// path returns the root directory, lazily creating it on the first call.
func (t *TempDir) path() (string, error) {
t.initOnce.Do(func() {
t.root, t.initErr = os.MkdirTemp("", t.prefix+"-")
})
if t.initErr != nil {
return "", fmt.Errorf("failed to create root temp dir: %w", t.initErr)
}
if t.cleaned.Load() {
return "", fmt.Errorf("temp dir has been cleaned up")
}
return t.root, nil
}
// NewChild creates a named subdirectory under this TempDir. The returned cleanup function removes
// the subdirectory and all contents; callers should defer it to reclaim space early. The root
// Cleanup acts as a safety net if the per-child cleanup is missed. The cleanup function is safe
// to call multiple times and is safe to call after the root has already been cleaned up.
func (t *TempDir) NewChild(name string) (string, func(), error) {
root, err := t.path()
if err != nil {
return "", noop, err
}
dir, err := os.MkdirTemp(root, name+"-")
if err != nil {
return "", noop, fmt.Errorf("failed to create child temp dir: %w", err)
}
cleanup := func() {
_ = os.RemoveAll(dir)
}
return dir, cleanup, nil
}
// NewFile creates a new temp file under this TempDir with the given name pattern (as in os.CreateTemp).
// The caller is responsible for closing the file. The returned cleanup function removes the file;
// callers should defer it to reclaim space early. The root Cleanup acts as a safety net if the
// per-file cleanup is missed. The cleanup function is safe to call multiple times.
func (t *TempDir) NewFile(pattern string) (*os.File, func(), error) {
root, err := t.path()
if err != nil {
return nil, noop, err
}
f, err := os.CreateTemp(root, pattern)
if err != nil {
return nil, noop, fmt.Errorf("failed to create temp file: %w", err)
}
cleanup := func() {
_ = os.Remove(f.Name())
}
return f, cleanup, nil
}
// Cleanup removes the entire root directory and all contents. Safe to call multiple times.
func (t *TempDir) Cleanup() error {
var err error
t.cleanupOnce.Do(func() {
t.cleaned.Store(true)
if t.root == "" {
return
}
err = os.RemoveAll(t.root)
})
return err
}

View File

@ -1,295 +0,0 @@
package tmpdir
import (
"context"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRootAndFromContext(t *testing.T) {
ctx := context.Background()
assert.Nil(t, FromContext(ctx))
ctx, td := Root(ctx, "test")
require.NotNil(t, FromContext(ctx))
assert.Same(t, td, FromContext(ctx))
}
func TestWithValue(t *testing.T) {
_, td := Root(context.Background(), "test")
defer td.Cleanup()
// inject the existing TempDir into a fresh context
ctx := WithValue(context.Background(), td)
assert.Same(t, td, FromContext(ctx))
// the injected TempDir is fully functional
f, cleanup, err := FromContext(ctx).NewFile("with-value-*.txt")
require.NoError(t, err)
defer cleanup()
require.NoError(t, f.Close())
}
func TestNewChild(t *testing.T) {
ctx, td := Root(context.Background(), "test")
defer td.Cleanup()
_ = ctx
child1, cleanup1, err := td.NewChild("sub")
require.NoError(t, err)
defer cleanup1()
child2, cleanup2, err := td.NewChild("sub")
require.NoError(t, err)
defer cleanup2()
// children are distinct
assert.NotEqual(t, child1, child2)
// both exist and are under the same root
info1, err := os.Stat(child1)
require.NoError(t, err)
assert.True(t, info1.IsDir())
info2, err := os.Stat(child2)
require.NoError(t, err)
assert.True(t, info2.IsDir())
assert.Equal(t, filepath.Dir(child1), filepath.Dir(child2))
}
func TestNewFile(t *testing.T) {
_, td := Root(context.Background(), "test")
defer td.Cleanup()
f, cleanup, err := td.NewFile("hello-*.txt")
require.NoError(t, err)
defer cleanup()
_, err = f.WriteString("hello")
require.NoError(t, err)
require.NoError(t, f.Close())
content, err := os.ReadFile(f.Name())
require.NoError(t, err)
assert.Equal(t, "hello", string(content))
}
func TestCleanup(t *testing.T) {
_, td := Root(context.Background(), "test")
child, _, err := td.NewChild("sub")
require.NoError(t, err)
f, _, err := td.NewFile("file-*")
require.NoError(t, err)
fname := f.Name()
f.Close()
// write a file inside the child dir too
require.NoError(t, os.WriteFile(filepath.Join(child, "inner.txt"), []byte("x"), 0600))
// everything exists
_, err = os.Stat(child)
require.NoError(t, err)
_, err = os.Stat(fname)
require.NoError(t, err)
// cleanup
require.NoError(t, td.Cleanup())
// everything is gone
_, err = os.Stat(child)
assert.True(t, os.IsNotExist(err))
_, err = os.Stat(fname)
assert.True(t, os.IsNotExist(err))
// double cleanup is safe
require.NoError(t, td.Cleanup())
}
func TestCleanupPreventsNewAllocation(t *testing.T) {
_, td := Root(context.Background(), "test")
require.NoError(t, td.Cleanup())
_, _, err := td.NewChild("nope")
assert.Error(t, err)
_, _, err = td.NewFile("nope-*")
assert.Error(t, err)
}
func TestEarlyCleanupFile(t *testing.T) {
_, td := Root(context.Background(), "test")
defer td.Cleanup()
f, cleanup, err := td.NewFile("early-*.txt")
require.NoError(t, err)
fname := f.Name()
require.NoError(t, f.Close())
// file exists before cleanup
_, err = os.Stat(fname)
require.NoError(t, err)
// early cleanup removes the file
cleanup()
_, err = os.Stat(fname)
assert.True(t, os.IsNotExist(err))
// calling cleanup again is safe (idempotent)
cleanup()
}
func TestEarlyCleanupChild(t *testing.T) {
_, td := Root(context.Background(), "test")
defer td.Cleanup()
child, cleanup, err := td.NewChild("early")
require.NoError(t, err)
// child dir exists
_, err = os.Stat(child)
require.NoError(t, err)
// early cleanup removes it
cleanup()
_, err = os.Stat(child)
assert.True(t, os.IsNotExist(err))
// calling cleanup again is safe (idempotent)
cleanup()
}
func TestEarlyCleanupThenRootCleanup(t *testing.T) {
_, td := Root(context.Background(), "test")
f, cleanupFile, err := td.NewFile("combo-*.txt")
require.NoError(t, err)
fname := f.Name()
f.Close()
child, cleanupChild, err := td.NewChild("combo")
require.NoError(t, err)
// early cleanup both
cleanupFile()
cleanupChild()
// files are already gone
_, err = os.Stat(fname)
assert.True(t, os.IsNotExist(err))
_, err = os.Stat(child)
assert.True(t, os.IsNotExist(err))
// root cleanup still works (no error on already-removed contents)
require.NoError(t, td.Cleanup())
}
func TestConcurrentNewChildAndNewFile(t *testing.T) {
_, td := Root(context.Background(), "test")
defer td.Cleanup()
const goroutines = 20
errs := make(chan error, goroutines)
paths := make(chan string, goroutines)
for i := 0; i < goroutines; i++ {
go func(i int) {
if i%2 == 0 {
child, cleanup, err := td.NewChild("concurrent")
if err != nil {
errs <- err
return
}
defer cleanup()
paths <- child
} else {
f, cleanup, err := td.NewFile("concurrent-*.txt")
if err != nil {
errs <- err
return
}
defer cleanup()
_ = f.Close()
paths <- f.Name()
}
errs <- nil
}(i)
}
seen := make(map[string]bool)
for i := 0; i < goroutines; i++ {
err := <-errs
require.NoError(t, err)
}
close(paths)
for p := range paths {
assert.False(t, seen[p], "duplicate path: %s", p)
seen[p] = true
}
assert.Len(t, seen, goroutines)
}
func TestConcurrentNewChildDuringCleanup(t *testing.T) {
_, td := Root(context.Background(), "test")
// trigger root creation
_, cleanup, err := td.NewChild("init")
require.NoError(t, err)
cleanup()
// cleanup and concurrent NewChild should not panic
done := make(chan struct{})
go func() {
_ = td.Cleanup()
close(done)
}()
// try creating children concurrently with cleanup — should get errors, not panics
for i := 0; i < 10; i++ {
_, c, _ := td.NewChild("race")
if c != nil {
c()
}
}
<-done
}
func TestLazyCreation(t *testing.T) {
_, td := Root(context.Background(), "test")
// root dir is not created until needed
assert.Equal(t, "", td.root)
_, _, err := td.NewFile("trigger-*")
require.NoError(t, err)
assert.NotEmpty(t, td.root)
require.NoError(t, td.Cleanup())
}
func TestFromPath(t *testing.T) {
dir := t.TempDir()
td := FromPath(dir)
// can create children
child, cleanup, err := td.NewChild("sub")
require.NoError(t, err)
defer cleanup()
assert.DirExists(t, child)
// can create files
f, cleanupFile, err := td.NewFile("file-*.txt")
require.NoError(t, err)
defer cleanupFile()
require.NoError(t, f.Close())
assert.FileExists(t, f.Name())
// root is the provided dir
assert.Equal(t, dir, filepath.Dir(child))
}

View File

@ -12,10 +12,8 @@ import (
"github.com/anchore/go-sync" "github.com/anchore/go-sync"
"github.com/anchore/syft/internal/bus" "github.com/anchore/syft/internal/bus"
"github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/internal/licenses"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/internal/sbomsync" "github.com/anchore/syft/internal/sbomsync"
"github.com/anchore/syft/internal/task" "github.com/anchore/syft/internal/task"
"github.com/anchore/syft/internal/tmpdir"
"github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/cataloging" "github.com/anchore/syft/syft/cataloging"
"github.com/anchore/syft/syft/event/monitor" "github.com/anchore/syft/syft/event/monitor"
@ -26,8 +24,6 @@ import (
// CreateSBOM creates a software bill-of-materials from the given source. If the CreateSBOMConfig is nil, then // CreateSBOM creates a software bill-of-materials from the given source. If the CreateSBOMConfig is nil, then
// default options will be used. // default options will be used.
//
//nolint:funlen
func CreateSBOM(ctx context.Context, src source.Source, cfg *CreateSBOMConfig) (*sbom.SBOM, error) { func CreateSBOM(ctx context.Context, src source.Source, cfg *CreateSBOMConfig) (*sbom.SBOM, error) {
if cfg == nil { if cfg == nil {
cfg = DefaultCreateSBOMConfig() cfg = DefaultCreateSBOMConfig()
@ -69,25 +65,12 @@ func CreateSBOM(ctx context.Context, src source.Source, cfg *CreateSBOMConfig) (
}, },
} }
// check if the caller already provided a TempDir; if so, don't clean it up (the caller owns it) // setup everything we need in context: license scanner, executors, etc.
callerOwnsTempDir := tmpdir.FromContext(ctx) != nil
// setup everything we need in context: license scanner, executors, temp storage, etc.
ctx, err = setupContext(ctx, cfg) ctx, err = setupContext(ctx, cfg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if !callerOwnsTempDir {
if td := tmpdir.FromContext(ctx); td != nil {
defer func() {
if err := td.Cleanup(); err != nil {
log.Warnf("failed to clean up temp dir: %v", err)
}
}()
}
}
catalogingProgress := monitorCatalogingTask(src.ID(), taskGroups) catalogingProgress := monitorCatalogingTask(src.ID(), taskGroups)
packageCatalogingProgress := monitorPackageCatalogingTask() packageCatalogingProgress := monitorPackageCatalogingTask()
@ -112,11 +95,6 @@ func setupContext(ctx context.Context, cfg *CreateSBOMConfig) (context.Context,
// configure parallel executors // configure parallel executors
ctx = setContextExecutors(ctx, cfg) ctx = setContextExecutors(ctx, cfg)
// configure temp dir factory for catalogers (if not already set)
if tmpdir.FromContext(ctx) == nil {
ctx, _ = tmpdir.Root(ctx, "syft-cataloger")
}
// configure license scanner // configure license scanner
// skip injecting a license scanner if one already set on context // skip injecting a license scanner if one already set on context
if licenses.IsContextLicenseScannerSet(ctx) { if licenses.IsContextLicenseScannerSet(ctx) {

View File

@ -22,7 +22,7 @@ tools-check:
# docker buildx build --platform linux/amd64 -t $(TOOL_IMAGE) . # docker buildx build --platform linux/amd64 -t $(TOOL_IMAGE) .
tools: tools:
@(docker image inspect $(TOOL_IMAGE) > /dev/null 2>&1 && make tools-check) || (docker build -t $(TOOL_IMAGE) . && sha256sum Dockerfile > Dockerfile.sha256) @(docker inspect $(TOOL_IMAGE) > /dev/null && make tools-check) || (docker build -t $(TOOL_IMAGE) . && sha256sum Dockerfile > Dockerfile.sha256)
build: tools build: tools
mkdir -p $(BIN) mkdir -p $(BIN)
@ -31,7 +31,7 @@ build: tools
verify: tools verify: tools
@rm -f $(VERIFY_FILE) @rm -f $(VERIFY_FILE)
docker run -i -v $(shell pwd):/mount -w /mount/project $(TOOL_IMAGE) make verify > $(VERIFY_FILE) docker run -i -v $(shell pwd):/mount -w /mount/project $(TOOL_IMAGE) make verify > $(VERIFY_FILE)
@python3 ./differ expected_verify $(VERIFY_FILE) @python ./differ expected_verify $(VERIFY_FILE)
debug: debug:
docker run -i --rm -v $(shell pwd):/mount -w /mount/project $(TOOL_IMAGE) bash docker run -i --rm -v $(shell pwd):/mount -w /mount/project $(TOOL_IMAGE) bash

View File

@ -1,9 +1,10 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
ARG OSXCROSS_VERSION=13.1 ARG OSXCROSS_VERSION=13.1
FROM --platform=linux/amd64 crazymax/osxcross:${OSXCROSS_VERSION}-ubuntu AS osxcross ARG BUILDPLATFORM=linux/amd64
FROM --platform=$BUILDPLATFORM crazymax/osxcross:${OSXCROSS_VERSION}-ubuntu AS osxcross
FROM --platform=linux/amd64 ubuntu:22.04 FROM --platform=$BUILDPLATFORM ubuntu:22.04
RUN apt update -y && apt install -y \ RUN apt update -y && apt install -y \
curl wget \ curl wget \

View File

@ -19,7 +19,7 @@ tools-check:
@sha256sum -c Dockerfile.sha256 || (echo "Tools Dockerfile has changed" && exit 1) @sha256sum -c Dockerfile.sha256 || (echo "Tools Dockerfile has changed" && exit 1)
tools: tools:
@(docker image inspect $(TOOL_IMAGE) > /dev/null 2>&1 && make tools-check) || (docker build --platform linux/amd64 -t $(TOOL_IMAGE) . && sha256sum Dockerfile > Dockerfile.sha256) @(docker inspect $(TOOL_IMAGE) > /dev/null && make tools-check) || (docker build -t $(TOOL_IMAGE) . && sha256sum Dockerfile > Dockerfile.sha256)
build: tools build: tools
@mkdir -p $(BIN) @mkdir -p $(BIN)

View File

@ -20,7 +20,7 @@ func SeekableReader(reader io.Reader) (io.ReadSeeker, error) {
return getOffsetReadSeeker(r) return getOffsetReadSeeker(r)
} }
content, err := io.ReadAll(reader) //nolint:gocritic // buffering non-seekable to seekable reader content, err := io.ReadAll(reader)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -62,7 +62,7 @@ func GetUnionReader(readerCloser io.ReadCloser) (UnionReader, error) {
return newReaderAtAdapter(r), nil return newReaderAtAdapter(r), nil
} }
b, err := io.ReadAll(readerCloser) //nolint:gocritic // buffering non-seekable to ReaderAt b, err := io.ReadAll(readerCloser)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to read contents from binary: %w", err) return nil, fmt.Errorf("unable to read contents from binary: %w", err)
} }

View File

@ -92,7 +92,7 @@ func tryParseReleaseInfo(resolver file.Resolver, location file.Location, logger
} }
defer internal.CloseAndLogError(contentReader, location.AccessPath) defer internal.CloseAndLogError(contentReader, location.AccessPath)
content, err := io.ReadAll(io.LimitReader(contentReader, 5*1024*1024)) content, err := io.ReadAll(contentReader)
if err != nil { if err != nil {
logger.WithFields("error", err, "path", location.RealPath).Trace("unable to read contents") logger.WithFields("error", err, "path", location.RealPath).Trace("unable to read contents")
return nil return nil

View File

@ -38,7 +38,7 @@ func readDebianVersionFile(resolver file.Resolver, location file.Location) strin
return "" return ""
} }
defer internal.CloseAndLogError(rdr, location.RealPath) defer internal.CloseAndLogError(rdr, location.RealPath)
contents, err := io.ReadAll(io.LimitReader(rdr, 5*1024*1024)) contents, err := io.ReadAll(rdr)
if err != nil { if err != nil {
log.Debugf("error reading %s: %v", location.RealPath, err) log.Debugf("error reading %s: %v", location.RealPath, err)
return "" return ""

View File

@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"os"
"path/filepath" "path/filepath"
"sort" "sort"
"strings" "strings"
@ -14,7 +15,6 @@ import (
"github.com/anchore/syft/internal" "github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/log"
"github.com/anchore/syft/internal/tmpdir"
"github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/internal/unknown"
"github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
@ -24,19 +24,17 @@ import (
// parseGGUFModel parses a GGUF model file and returns the discovered package. // parseGGUFModel parses a GGUF model file and returns the discovered package.
// This implementation only reads the header portion of the file, not the entire model. // This implementation only reads the header portion of the file, not the entire model.
func parseGGUFModel(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { func parseGGUFModel(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
defer internal.CloseAndLogError(reader, reader.Path()) defer internal.CloseAndLogError(reader, reader.Path())
td := tmpdir.FromContext(ctx) // Create a temporary file for the library to parse
if td == nil { // The library requires a file path, so we create a temp file
return nil, nil, fmt.Errorf("no temp dir factory in context") tempFile, err := os.CreateTemp("", "syft-gguf-*.gguf")
}
tempFile, cleanup, err := td.NewFile("syft-gguf-*.gguf")
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("failed to create temp file: %w", err) return nil, nil, fmt.Errorf("failed to create temp file: %w", err)
} }
defer cleanup()
tempPath := tempFile.Name() tempPath := tempFile.Name()
defer os.Remove(tempPath)
// Copy and validate the GGUF file header using LimitedReader to prevent OOM // Copy and validate the GGUF file header using LimitedReader to prevent OOM
// We use LimitedReader to cap reads at maxHeaderSize (50MB) // We use LimitedReader to cap reads at maxHeaderSize (50MB)

View File

@ -171,7 +171,7 @@ func findReleases(resolver file.Resolver, dbPath string) []linux.Release {
func parseReleasesFromAPKRepository(reader file.LocationReadCloser) []linux.Release { func parseReleasesFromAPKRepository(reader file.LocationReadCloser) []linux.Release {
var releases []linux.Release var releases []linux.Release
reposB, err := io.ReadAll(reader) //nolint:gocritic // regex matching requires full buffer reposB, err := io.ReadAll(reader)
if err != nil { if err != nil {
log.Tracef("unable to read APK repositories file %q: %+v", reader.RealPath, err) log.Tracef("unable to read APK repositories file %q: %+v", reader.RealPath, err)
return nil return nil

View File

@ -61,28 +61,6 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
Metadata: metadata("arangodb-binary"), Metadata: metadata("arangodb-binary"),
}, },
}, },
{
logicalFixture: "arangodb/3.12.5/linux-amd64",
expected: pkg.Package{
Name: "arangodb",
Version: "3.12.5",
Type: "binary",
PURL: "pkg:generic/arangodb@3.12.5",
Locations: locations("arangosh"),
Metadata: metadata("arangodb-binary"),
},
},
{
logicalFixture: "arangodb/3.12.5-2/linux-amd64",
expected: pkg.Package{
Name: "arangodb",
Version: "3.12.5-2",
Type: "binary",
PURL: "pkg:generic/arangodb@3.12.5-2",
Locations: locations("arangosh"),
Metadata: metadata("arangodb-binary"),
},
},
{ {
logicalFixture: "postgres/15beta4/linux-amd64", logicalFixture: "postgres/15beta4/linux-amd64",
expected: pkg.Package{ expected: pkg.Package{
@ -749,16 +727,6 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
{ {
// TODO: find original binary... // TODO: find original binary...
// note: cannot find the original binary, using a custom snippet based on the original snippet in the repo // note: cannot find the original binary, using a custom snippet based on the original snippet in the repo
logicalFixture: "go-version-hint/1.15-dev/any",
expected: pkg.Package{
Name: "go",
Version: "1.15",
PURL: "pkg:generic/go@1.15",
Locations: locations("bin/go", "VERSION"),
Metadata: metadata("go-binary"),
},
},
{
logicalFixture: "go-version-hint/1.15/any", logicalFixture: "go-version-hint/1.15/any",
expected: pkg.Package{ expected: pkg.Package{
Name: "go", Name: "go",

View File

@ -76,10 +76,10 @@ func DefaultClassifiers() []binutils.Classifier {
`(?m)go(?P<version>[0-9]+\.[0-9]+(\.[0-9]+|beta[0-9]+|alpha[0-9]+|rc[0-9]+)?)\x00`), `(?m)go(?P<version>[0-9]+\.[0-9]+(\.[0-9]+|beta[0-9]+|alpha[0-9]+|rc[0-9]+)?)\x00`),
binutils.SupportingEvidenceMatcher("VERSION*", binutils.SupportingEvidenceMatcher("VERSION*",
m.FileContentsVersionMatcher( m.FileContentsVersionMatcher(
`(?m)go(?P<version>[0-9]+\.[0-9]+(\.[0-9]+|beta[0-9]+|alpha[0-9]+|rc[0-9]+|-[_0-9a-z]+)?)`)), `(?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*", binutils.SupportingEvidenceMatcher("../VERSION*",
m.FileContentsVersionMatcher( m.FileContentsVersionMatcher(
`(?m)go(?P<version>[0-9]+\.[0-9]+(\.[0-9]+|beta[0-9]+|alpha[0-9]+|rc[0-9]+|-[_0-9a-z]+)?)`)), `(?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", Package: "go",
PURL: mustPURL("pkg:generic/go@version"), PURL: mustPURL("pkg:generic/go@version"),
@ -232,7 +232,7 @@ func DefaultClassifiers() []binutils.Classifier {
Class: "arangodb-binary", Class: "arangodb-binary",
FileGlob: "**/arangosh", FileGlob: "**/arangosh",
EvidenceMatcher: m.FileContentsVersionMatcher( EvidenceMatcher: m.FileContentsVersionMatcher(
`(?m)\x00*(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?)\s(enterprise\s)?\[linux\]`), `(?m)\x00*(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?)\s\[linux\]`),
Package: "arangodb", Package: "arangodb",
PURL: mustPURL("pkg:generic/arangodb@version"), PURL: mustPURL("pkg:generic/arangodb@version"),
CPEs: singleCPE("cpe:2.3:a:arangodb:arangodb:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource), CPEs: singleCPE("cpe:2.3:a:arangodb:arangodb:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),

View File

@ -127,83 +127,23 @@ func pullDockerImage(imageReference, platform string) error {
} }
func checkArchitecturesMatch(imageReference, platform string) (bool, string, error) { func checkArchitecturesMatch(imageReference, platform string) (bool, string, error) {
// first check if the image exists locally
cmd := exec.Command("docker", "image", "inspect", imageReference)
if err := cmd.Run(); err != nil {
return false, "", err
}
// prefer the manifest list for platform info — with Docker's containerd image store,
// platform metadata lives on the manifest list entry, not in the image config.
if found, err := platformInManifest(imageReference, platform); err == nil {
return found, platform, nil
}
// fall back to image config for older Docker daemons that don't support "docker manifest inspect"
gotPlatform, err := platformFromImageInspect(imageReference)
if err != nil {
return false, "", err
}
return gotPlatform == platform, gotPlatform, nil
}
func platformFromImageInspect(imageReference string) (string, error) {
cmd := exec.Command("docker", "image", "inspect", imageReference) cmd := exec.Command("docker", "image", "inspect", imageReference)
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
if err != nil { if err != nil {
return "", err return false, "", err
} }
var inspect []imageInspect var inspect []imageInspect
if err := json.Unmarshal(out, &inspect); err != nil { if err := json.Unmarshal(out, &inspect); err != nil {
return "", fmt.Errorf("unable to unmarshal image inspect: %w", err) return false, "", fmt.Errorf("unable to unmarshal image inspect: %w", err)
} }
if len(inspect) != 1 { if len(inspect) != 1 {
return "", fmt.Errorf("expected 1 image inspect, got %d", len(inspect)) return false, "", fmt.Errorf("expected 1 image inspect, got %d", len(inspect))
} }
gotPlatform := inspect[0].Platform()
return inspect[0].Platform(), nil return gotPlatform == platform, gotPlatform, nil
}
type manifestList struct {
Manifests []manifestEntry `json:"manifests"`
}
type manifestEntry struct {
Platform manifestPlatform `json:"platform"`
}
type manifestPlatform struct {
Architecture string `json:"architecture"`
OS string `json:"os"`
}
// platformInManifest checks whether the wanted platform is available in the image's manifest list.
// With Docker's containerd image store, all images are distributed via manifest lists (indexes),
// and platform metadata may only be on the index entry — not in the image config that
// "docker image inspect" reads. "docker manifest inspect" reads the index directly.
func platformInManifest(imageReference, wantPlatform string) (bool, error) {
cmd := exec.Command("docker", "manifest", "inspect", imageReference)
out, err := cmd.CombinedOutput()
if err != nil {
return false, fmt.Errorf("manifest inspect failed: %w", err)
}
var ml manifestList
if err := json.Unmarshal(out, &ml); err != nil {
return false, fmt.Errorf("unable to unmarshal manifest: %w", err)
}
for _, m := range ml.Manifests {
p := fmt.Sprintf("%s/%s", m.Platform.OS, m.Platform.Architecture)
if p == wantPlatform {
return true, nil
}
}
return false, nil
} }
func copyBinariesFromDockerImages(config config.BinaryFromImage, destination string) (err error) { func copyBinariesFromDockerImages(config config.BinaryFromImage, destination string) (err error) {

View File

@ -151,4 +151,4 @@ while $CONTINUE_LOOP; do
done done
go run ../internal/manager write-snippet "$BINARY_FILE" --offset "$OFFSET" --length "$LENGTH" --name "$GROUP_NAME" --version "$VERSION" go run ./manager write-snippet "$BINARY_FILE" --offset "$OFFSET" --length "$LENGTH" --name "$GROUP_NAME" --version "$VERSION"

View File

@ -1 +0,0 @@
no version in this binary

View File

@ -458,20 +458,6 @@ from-images:
platform: linux/amd64 platform: linux/amd64
paths: paths:
- /usr/bin/arangosh - /usr/bin/arangosh
- name: arangodb
version: 3.12.5
images:
- ref: arangodb:3.12.5@sha256:1f9278fe17b200cf3aea2c7bd7fd571221b5b41a49b835a397c47eb970c952d6
platform: linux/amd64
paths:
- /usr/bin/arangosh
- name: arangodb
version: 3.12.5-2
images:
- ref: arangodb:3.12.5.2@sha256:5b0d1d2911ea864ea61d7e2357789004fe912606f5980cf481739601d7cb17a1
platform: linux/amd64
paths:
- /usr/bin/arangosh
- version: 15.1 - version: 15.1
images: images:
- ref: postgres:15.1@sha256:b4140dd3a62f364f16a82c1bd88d28b9887ecb47f07dbe2941237d073574d428 - ref: postgres:15.1@sha256:b4140dd3a62f364f16a82c1bd88d28b9887ecb47f07dbe2941237d073574d428

View File

@ -47,7 +47,7 @@ func node(value interface{}) erlangNode {
// parseErlang basic parser for erlang, used by rebar.lock // parseErlang basic parser for erlang, used by rebar.lock
func parseErlang(reader io.Reader) (erlangNode, error) { func parseErlang(reader io.Reader) (erlangNode, error) {
data, err := io.ReadAll(reader) //nolint:gocritic // custom parser requires []byte data, err := io.ReadAll(reader)
if err != nil { if err != nil {
return node(nil), err return node(nil), err
} }

View File

@ -3,6 +3,7 @@ package githubactions
import ( import (
"context" "context"
"fmt" "fmt"
"io"
"go.yaml.in/yaml/v3" "go.yaml.in/yaml/v3"
@ -24,9 +25,13 @@ type compositeActionRunsDef struct {
} }
func parseCompositeActionForActionUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { func parseCompositeActionForActionUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
contents, errs := io.ReadAll(reader)
if errs != nil {
return nil, nil, fmt.Errorf("unable to read yaml composite action file: %w", errs)
}
var ca compositeActionDef var ca compositeActionDef
var errs error if errs = yaml.Unmarshal(contents, &ca); errs != nil {
if errs = yaml.NewDecoder(reader).Decode(&ca); errs != nil {
return nil, nil, fmt.Errorf("unable to parse yaml composite action file: %w", errs) return nil, nil, fmt.Errorf("unable to parse yaml composite action file: %w", errs)
} }

View File

@ -3,6 +3,7 @@ package githubactions
import ( import (
"context" "context"
"fmt" "fmt"
"io"
"regexp" "regexp"
"go.yaml.in/yaml/v3" "go.yaml.in/yaml/v3"
@ -40,10 +41,14 @@ type stepDef struct {
} }
func parseWorkflowForWorkflowUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { func parseWorkflowForWorkflowUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
contents, errs := io.ReadAll(reader)
if errs != nil {
return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", errs)
}
// parse the yaml file into a generic node to preserve comments // parse the yaml file into a generic node to preserve comments
var node yaml.Node var node yaml.Node
var errs error if errs = yaml.Unmarshal(contents, &node); errs != nil {
if errs = yaml.NewDecoder(reader).Decode(&node); errs != nil {
return nil, nil, fmt.Errorf("unable to parse yaml workflow file: %w", errs) return nil, nil, fmt.Errorf("unable to parse yaml workflow file: %w", errs)
} }
@ -74,10 +79,14 @@ func parseWorkflowForWorkflowUsage(_ context.Context, _ file.Resolver, _ *generi
} }
func parseWorkflowForActionUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { func parseWorkflowForActionUsage(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
contents, errs := io.ReadAll(reader)
if errs != nil {
return nil, nil, fmt.Errorf("unable to read yaml workflow file: %w", errs)
}
// parse the yaml file into a generic node to preserve comments // parse the yaml file into a generic node to preserve comments
var node yaml.Node var node yaml.Node
var errs error if errs = yaml.Unmarshal(contents, &node); errs != nil {
if errs = yaml.NewDecoder(reader).Decode(&node); errs != nil {
return nil, nil, fmt.Errorf("unable to parse yaml workflow file: %w", errs) return nil, nil, fmt.Errorf("unable to parse yaml workflow file: %w", errs)
} }

View File

@ -23,7 +23,6 @@ import (
"github.com/anchore/syft/internal" "github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/cache" "github.com/anchore/syft/internal/cache"
"github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/log"
"github.com/anchore/syft/internal/tmpdir"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/internal/licenses" "github.com/anchore/syft/syft/pkg/cataloger/internal/licenses"
@ -164,10 +163,7 @@ func (c *goLicenseResolver) getLicensesFromRemote(ctx context.Context, moduleNam
return c.licenseCache.Resolve(fmt.Sprintf("%s/%s", moduleName, moduleVersion), func() ([]pkg.License, error) { return c.licenseCache.Resolve(fmt.Sprintf("%s/%s", moduleName, moduleVersion), func() ([]pkg.License, error) {
proxies := remotesForModule(c.opts.Proxies, c.opts.NoProxy, moduleName) proxies := remotesForModule(c.opts.Proxies, c.opts.NoProxy, moduleName)
urlPrefix, fsys, cleanup, err := getModule(ctx, proxies, moduleName, moduleVersion) urlPrefix, fsys, err := getModule(proxies, moduleName, moduleVersion)
if cleanup != nil {
defer cleanup()
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -262,7 +258,7 @@ func processCaps(s string) string {
}) })
} }
func getModule(ctx context.Context, proxies []string, moduleName, moduleVersion string) (urlPrefix string, fsys fs.FS, cleanup func(), err error) { func getModule(proxies []string, moduleName, moduleVersion string) (urlPrefix string, fsys fs.FS, err error) {
for _, proxy := range proxies { for _, proxy := range proxies {
u, _ := url.Parse(proxy) u, _ := url.Parse(proxy)
if proxy == "direct" { if proxy == "direct" {
@ -271,7 +267,7 @@ func getModule(ctx context.Context, proxies []string, moduleName, moduleVersion
} }
switch u.Scheme { switch u.Scheme {
case "https", "http": case "https", "http":
urlPrefix, fsys, cleanup, err = getModuleProxy(ctx, proxy, moduleName, moduleVersion) urlPrefix, fsys, err = getModuleProxy(proxy, moduleName, moduleVersion)
case "file": case "file":
p := filepath.Join(u.Path, moduleName, "@v", moduleVersion) p := filepath.Join(u.Path, moduleName, "@v", moduleVersion)
urlPrefix = path.Join("file://", p) + "/" urlPrefix = path.Join("file://", p) + "/"
@ -285,78 +281,42 @@ func getModule(ctx context.Context, proxies []string, moduleName, moduleVersion
return return
} }
// getModuleProxy downloads a Go module zip from the given proxy and returns a filesystem view of its contents. func getModuleProxy(proxy string, moduleName string, moduleVersion string) (moduleURL string, out fs.FS, _ error) {
// The returned cleanup function closes the underlying temp file and removes it; callers must not use the
// returned fs.FS after calling cleanup.
func getModuleProxy(ctx context.Context, proxy string, moduleName string, moduleVersion string) (moduleURL string, out fs.FS, cleanup func(), _ error) {
u := fmt.Sprintf("%s/%s/@v/%s.zip", proxy, moduleName, moduleVersion) u := fmt.Sprintf("%s/%s/@v/%s.zip", proxy, moduleName, moduleVersion)
// get the module zip // get the module zip
log.WithFields("url", u).Info("downloading go module from proxy") log.WithFields("url", u).Info("downloading go module from proxy")
resp, err := http.Get(u) //nolint:gosec resp, err := http.Get(u) //nolint:gosec
if err != nil { if err != nil {
return "", nil, nil, err return "", nil, err
} }
defer func() { _ = resp.Body.Close() }() defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
// close the first response before retrying with a lowercased module name
_ = resp.Body.Close()
u = fmt.Sprintf("%s/%s/@v/%s.zip", proxy, strings.ToLower(moduleName), moduleVersion) u = fmt.Sprintf("%s/%s/@v/%s.zip", proxy, strings.ToLower(moduleName), moduleVersion)
// try lowercasing it; some packages have mixed casing that really messes up the proxy // try lowercasing it; some packages have mixed casing that really messes up the proxy
resp, err = http.Get(u) //nolint:gosec resp, err = http.Get(u) //nolint:gosec
if err != nil { if err != nil {
return "", nil, nil, err return "", nil, err
} }
defer func() { _ = resp.Body.Close() }() defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return "", nil, nil, fmt.Errorf("failed to get module zip: %s", resp.Status) return "", nil, fmt.Errorf("failed to get module zip: %s", resp.Status)
} }
} }
// stream the zip to a temp file to avoid unbounded memory usage // read the zip
td := tmpdir.FromContext(ctx) b, err := io.ReadAll(resp.Body)
if td == nil {
return "", nil, nil, fmt.Errorf("no temp dir factory in context")
}
tmpFile, cleanupFile, err := td.NewFile("gomodule-*.zip") //nolint:gocritic // cleanup is returned to caller, not deferred here
if err != nil { if err != nil {
return "", nil, nil, fmt.Errorf("failed to create temp file for module zip: %w", err) return "", nil, err
} }
cleanup = func() { out, err = zip.NewReader(bytes.NewReader(b), resp.ContentLength)
_ = tmpFile.Close()
cleanupFile()
}
// cap downloads at 500MB to prevent disk exhaustion from malicious proxies
const maxModuleZipSize = 500 * 1024 * 1024
size, err := io.Copy(tmpFile, io.LimitReader(resp.Body, maxModuleZipSize))
if err != nil {
cleanup()
return "", nil, nil, fmt.Errorf("failed to download module zip: %w", err)
}
if size >= maxModuleZipSize {
cleanup()
return "", nil, nil, fmt.Errorf("module zip exceeds %d byte size limit", maxModuleZipSize)
}
if _, err := tmpFile.Seek(0, io.SeekStart); err != nil {
cleanup()
return "", nil, nil, fmt.Errorf("failed to seek module zip: %w", err)
}
out, err = zip.NewReader(tmpFile, size)
if err != nil {
cleanup()
return "", nil, nil, fmt.Errorf("failed to read module zip: %w", err)
}
versionPath := findVersionPath(out, ".") versionPath := findVersionPath(out, ".")
out = getSubFS(out, versionPath) out = getSubFS(out, versionPath)
return u + "#" + versionPath + "/", out, cleanup, err return u + "#" + versionPath + "/", out, err
} }
func findVersionPath(f fs.FS, dir string) string { func findVersionPath(f fs.FS, dir string) string {

View File

@ -24,7 +24,7 @@ import (
) )
func Test_LicenseSearch(t *testing.T) { func Test_LicenseSearch(t *testing.T) {
ctx := pkgtest.Context(t) ctx := pkgtest.Context()
loc1 := file.NewLocation("github.com/someorg/somename@v0.3.2/LICENSE") loc1 := file.NewLocation("github.com/someorg/somename@v0.3.2/LICENSE")
loc2 := file.NewLocation("github.com/!cap!o!r!g/!cap!project@v4.111.5/LICENSE.txt") loc2 := file.NewLocation("github.com/!cap!o!r!g/!cap!project@v4.111.5/LICENSE.txt")
@ -321,7 +321,7 @@ func Test_noLocalGoModDir(t *testing.T) {
validTmp := t.TempDir() validTmp := t.TempDir()
require.NoError(t, os.MkdirAll(filepath.Join(validTmp, "mod@ver"), 0700|os.ModeDir)) require.NoError(t, os.MkdirAll(filepath.Join(validTmp, "mod@ver"), 0700|os.ModeDir))
ctx := pkgtest.Context(t) ctx := pkgtest.Context()
tests := []struct { tests := []struct {
name string name string
dir string dir string

View File

@ -324,7 +324,7 @@ func buildModuleRelationships(
} }
func (c *goModCataloger) parseModFileContents(reader file.LocationReadCloser) (*modfile.File, error) { func (c *goModCataloger) parseModFileContents(reader file.LocationReadCloser) (*modfile.File, error) {
contents, err := io.ReadAll(reader) //nolint:gocritic // modfile.Parse requires []byte contents, err := io.ReadAll(reader)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read go module: %w", err) return nil, fmt.Errorf("failed to read go module: %w", err)
} }

View File

@ -3,6 +3,7 @@ package haskell
import ( import (
"context" "context"
"fmt" "fmt"
"io"
"strings" "strings"
"go.yaml.in/yaml/v3" "go.yaml.in/yaml/v3"
@ -41,11 +42,16 @@ type completedSnapshot struct {
// parseStackLock is a parser function for stack.yaml.lock contents, returning all packages discovered. // parseStackLock is a parser function for stack.yaml.lock contents, returning all packages discovered.
func parseStackLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { func parseStackLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
bytes, err := io.ReadAll(reader)
if err != nil {
return nil, nil, fmt.Errorf("failed to load stack.yaml.lock file: %w", err)
}
var lockFile stackLock var lockFile stackLock
if err := yaml.NewDecoder(reader).Decode(&lockFile); err != nil { if err := yaml.Unmarshal(bytes, &lockFile); err != nil {
log.WithFields("error", err, "path", reader.RealPath).Trace("failed to parse stack.yaml.lock") log.WithFields("error", err, "path", reader.RealPath).Trace("failed to parse stack.yaml.lock")
return nil, nil, fmt.Errorf("failed to parse stack.yaml.lock file: %w", err) return nil, nil, fmt.Errorf("failed to parse stack.yaml.lock file")
} }
var ( var (

View File

@ -3,6 +3,7 @@ package haskell
import ( import (
"context" "context"
"fmt" "fmt"
"io"
"go.yaml.in/yaml/v3" "go.yaml.in/yaml/v3"
@ -22,11 +23,16 @@ type stackYaml struct {
// parseStackYaml is a parser function for stack.yaml contents, returning all packages discovered. // parseStackYaml is a parser function for stack.yaml contents, returning all packages discovered.
func parseStackYaml(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { func parseStackYaml(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
bytes, err := io.ReadAll(reader)
if err != nil {
return nil, nil, fmt.Errorf("failed to load stack.yaml file: %w", err)
}
var stackFile stackYaml var stackFile stackYaml
if err := yaml.NewDecoder(reader).Decode(&stackFile); err != nil { if err := yaml.Unmarshal(bytes, &stackFile); err != nil {
log.WithFields("error", err, "path", reader.RealPath).Trace("failed to parse stack.yaml") log.WithFields("error", err, "path", reader.RealPath).Trace("failed to parse stack.yaml")
return nil, nil, fmt.Errorf("failed to parse stack.yaml file: %w", err) return nil, nil, fmt.Errorf("failed to parse stack.yaml file")
} }
var pkgs []pkg.Package var pkgs []pkg.Package

View File

@ -22,9 +22,6 @@
"github.com/apptainer/apptainer": [ "github.com/apptainer/apptainer": [
"cpe:2.3:a:lfprojects:apptainer:*:*:*:*:*:go:*:*" "cpe:2.3:a:lfprojects:apptainer:*:*:*:*:*:go:*:*"
], ],
"github.com/aquasecurity/trivy/pkg/types": [
"cpe:2.3:a:aquasec:trivy:*:*:*:*:*:go:*:*"
],
"github.com/argoproj/argo-workflows/v3": [ "github.com/argoproj/argo-workflows/v3": [
"cpe:2.3:a:argoproj:argo_workflows:*:*:*:*:*:go:*:*" "cpe:2.3:a:argoproj:argo_workflows:*:*:*:*:*:go:*:*"
], ],
@ -55,12 +52,6 @@
"github.com/ecnepsnai/web": [ "github.com/ecnepsnai/web": [
"cpe:2.3:a:web_project:web:*:*:*:*:*:go:*:*" "cpe:2.3:a:web_project:web:*:*:*:*:*:go:*:*"
], ],
"github.com/free5gc/amf": [
"cpe:2.3:a:free5gc:amf:*:*:*:*:*:go:*:*"
],
"github.com/free5gc/go-upf": [
"cpe:2.3:a:free5gc:go-upf:*:*:*:*:*:go:*:*"
],
"github.com/free5gc/smf": [ "github.com/free5gc/smf": [
"cpe:2.3:a:free5gc:smf:*:*:*:*:*:go:*:*" "cpe:2.3:a:free5gc:smf:*:*:*:*:*:go:*:*"
], ],
@ -145,9 +136,6 @@
"github.com/quic-go/webtransport-go#section-readme": [ "github.com/quic-go/webtransport-go#section-readme": [
"cpe:2.3:a:quic-go:webtransport-go:*:*:*:*:*:go:*:*" "cpe:2.3:a:quic-go:webtransport-go:*:*:*:*:*:go:*:*"
], ],
"github.com/rezmoss/axios4go": [
"cpe:2.3:a:rezmoss:axios4go:*:*:*:*:*:go:*:*"
],
"github.com/sap/cloud-security-client-go": [ "github.com/sap/cloud-security-client-go": [
"cpe:2.3:a:sap:cloud-security-client-go:*:*:*:*:*:go:*:*" "cpe:2.3:a:sap:cloud-security-client-go:*:*:*:*:*:go:*:*"
], ],
@ -1274,9 +1262,6 @@
"literate": [ "literate": [
"cpe:2.3:a:jenkins:literate:*:*:*:*:*:jenkins:*:*" "cpe:2.3:a:jenkins:literate:*:*:*:*:*:jenkins:*:*"
], ],
"loadninja": [
"cpe:2.3:a:jenkins:loadninja:*:*:*:*:*:jenkins:*:*"
],
"lockable-resources": [ "lockable-resources": [
"cpe:2.3:a:jenkins:lockable_resources:*:*:*:*:*:jenkins:*:*" "cpe:2.3:a:jenkins:lockable_resources:*:*:*:*:*:jenkins:*:*"
], ],
@ -2326,9 +2311,6 @@
"@ckeditor/ckeditor5-widget": [ "@ckeditor/ckeditor5-widget": [
"cpe:2.3:a:ckeditor:ckeditor5-widget:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:ckeditor:ckeditor5-widget:*:*:*:*:*:node.js:*:*"
], ],
"@coding-solo/godot-mcp": [
"cpe:2.3:a:coding-solo:godot_mcp:*:*:*:*:*:*:*:*"
],
"@cookiex/deep": [ "@cookiex/deep": [
"cpe:2.3:a:cookiex-deep_project:cookiex-deep:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:cookiex-deep_project:cookiex-deep:*:*:*:*:*:node.js:*:*"
], ],
@ -2368,9 +2350,6 @@
"@google-cloud/firestore": [ "@google-cloud/firestore": [
"cpe:2.3:a:google:cloud_firestore:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:google:cloud_firestore:*:*:*:*:*:node.js:*:*"
], ],
"@graphprotocol/contracts": [
"cpe:2.3:a:thegraph:graph_protocol_contracts:*:*:*:*:*:node.js:*:*"
],
"@grpc/grpc-js": [ "@grpc/grpc-js": [
"cpe:2.3:a:grpc:grpc:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:grpc:grpc:*:*:*:*:*:node.js:*:*"
], ],
@ -2492,12 +2471,6 @@
"@thi.ng/egf": [ "@thi.ng/egf": [
"cpe:2.3:a:\\@thi.ng\\/egf_project:\\@thi.ng\\/egf:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:\\@thi.ng\\/egf_project:\\@thi.ng\\/egf:*:*:*:*:*:node.js:*:*"
], ],
"@tinacms/cli": [
"cpe:2.3:a:ssw:tinacms\\/cli:*:*:*:*:*:node.js:*:*"
],
"@tinacms/graphql": [
"cpe:2.3:a:ssw:tinacms\\/graphql:*:*:*:*:*:node.js:*:*"
],
"@tiptap/extension-link": [ "@tiptap/extension-link": [
"cpe:2.3:a:tiptap:tiptap\\/extension-link:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:tiptap:tiptap\\/extension-link:*:*:*:*:*:node.js:*:*"
], ],
@ -3097,9 +3070,6 @@
"defaults-deep": [ "defaults-deep": [
"cpe:2.3:a:defaults-deep_project:defaults-deep:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:defaults-deep_project:defaults-deep:*:*:*:*:*:node.js:*:*"
], ],
"defuddle": [
"cpe:2.3:a:kepano:defuddle:*:*:*:*:*:node.js:*:*"
],
"desafio": [ "desafio": [
"cpe:2.3:a:desafio_project:desafio:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:desafio_project:desafio:*:*:*:*:*:node.js:*:*"
], ],
@ -3303,9 +3273,6 @@
"express-openid-connect": [ "express-openid-connect": [
"cpe:2.3:a:auth0:express_openid_connect:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:auth0:express_openid_connect:*:*:*:*:*:node.js:*:*"
], ],
"express-rate-limit": [
"cpe:2.3:a:express-rate-limit:express-rate-limit:*:*:*:*:*:node.js:*:*"
],
"express-restify-mongoose": [ "express-restify-mongoose": [
"cpe:2.3:a:express-restify-mongoose_project:express-restify-mongoose:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:express-restify-mongoose_project:express-restify-mongoose:*:*:*:*:*:node.js:*:*"
], ],
@ -3352,6 +3319,7 @@
"cpe:2.3:a:fast_string_search_project:fast_string_search:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:fast_string_search_project:fast_string_search:*:*:*:*:*:node.js:*:*"
], ],
"fast-xml-parser": [ "fast-xml-parser": [
"cpe:2.3:a:fast-xml-parser_project:fast-xml-parser:*:*:*:*:*:node.js:*:*",
"cpe:2.3:a:naturalintelligence:fast-xml-parser:*:*:*:*:*:*:*:*" "cpe:2.3:a:naturalintelligence:fast-xml-parser:*:*:*:*:*:*:*:*"
], ],
"fastest-json-copy": [ "fastest-json-copy": [
@ -3388,7 +3356,7 @@
"cpe:2.3:a:fibjs_project:fibjs:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:fibjs_project:fibjs:*:*:*:*:*:node.js:*:*"
], ],
"file-type": [ "file-type": [
"cpe:2.3:a:sindresorhus:file-type:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:file-type_project:file-type:*:*:*:*:*:node.js:*:*"
], ],
"file-upload-with-preview": [ "file-upload-with-preview": [
"cpe:2.3:a:johndatserakis:file-upload-with-preview:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:johndatserakis:file-upload-with-preview:*:*:*:*:*:node.js:*:*"
@ -3638,9 +3606,6 @@
"hapi-auth-jwt2": [ "hapi-auth-jwt2": [
"cpe:2.3:a:hapi-auth-jwt2_project:hapi-auth-jwt2:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:hapi-auth-jwt2_project:hapi-auth-jwt2:*:*:*:*:*:node.js:*:*"
], ],
"happy-dom": [
"cpe:2.3:a:capricorn86:happy_dom:*:*:*:*:*:nodejs:*:*"
],
"harp": [ "harp": [
"cpe:2.3:a:npmjs:harp:*:*:*:*:*:*:*:*" "cpe:2.3:a:npmjs:harp:*:*:*:*:*:*:*:*"
], ],
@ -4187,9 +4152,6 @@
"madlib-object-utils": [ "madlib-object-utils": [
"cpe:2.3:a:springtree:madlib-object-utils:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:springtree:madlib-object-utils:*:*:*:*:*:node.js:*:*"
], ],
"mailparser": [
"cpe:2.3:a:nodemailer:mailparser:*:*:*:*:*:node.js:*:*"
],
"makerjs": [ "makerjs": [
"cpe:2.3:a:microsoft:maker.js:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:microsoft:maker.js:*:*:*:*:*:node.js:*:*"
], ],
@ -4431,8 +4393,7 @@
"cpe:2.3:a:mystem3_project:mystem3:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:mystem3_project:mystem3:*:*:*:*:*:node.js:*:*"
], ],
"n8n": [ "n8n": [
"cpe:2.3:a:n8n:n8n:*:*:*:*:community:node.js:*:*", "cpe:2.3:a:n8n:n8n:*:*:*:*:*:node.js:*:*"
"cpe:2.3:a:n8n:n8n:*:*:*:*:enterprise:node.js:*:*"
], ],
"nanoid": [ "nanoid": [
"cpe:2.3:a:nanoid_project:nanoid:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:nanoid_project:nanoid:*:*:*:*:*:node.js:*:*"
@ -5351,9 +5312,6 @@
"sly07": [ "sly07": [
"cpe:2.3:a:sly07_project:sly07:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:sly07_project:sly07:*:*:*:*:*:node.js:*:*"
], ],
"sm-crypto": [
"cpe:2.3:a:juneandgreen:sm-crypto:*:*:*:*:*:node.js:*:*"
],
"smb": [ "smb": [
"cpe:2.3:a:smb_project:smb:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:smb_project:smb:*:*:*:*:*:node.js:*:*"
], ],
@ -5444,9 +5402,6 @@
"stimulsoft-dashboards-js": [ "stimulsoft-dashboards-js": [
"cpe:2.3:a:stimulsoft:dashboard.js:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:stimulsoft:dashboard.js:*:*:*:*:*:node.js:*:*"
], ],
"storybook": [
"cpe:2.3:a:storybook:storybook:*:*:*:*:*:node.js:*:*"
],
"strapi": [ "strapi": [
"cpe:2.3:a:strapi:strapi:*:*:*:*:*:*:*:*", "cpe:2.3:a:strapi:strapi:*:*:*:*:*:*:*:*",
"cpe:2.3:a:strapi:strapi:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:strapi:strapi:*:*:*:*:*:node.js:*:*"
@ -5513,9 +5468,6 @@
"terminal-kit": [ "terminal-kit": [
"cpe:2.3:a:terminal-kit_project:terminal-kit:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:terminal-kit_project:terminal-kit:*:*:*:*:*:node.js:*:*"
], ],
"terriajs-server": [
"cpe:2.3:a:terria:terriajs-server:*:*:*:*:*:node.js:*:*"
],
"terser": [ "terser": [
"cpe:2.3:a:terser:terser:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:terser:terser:*:*:*:*:*:node.js:*:*"
], ],
@ -5531,9 +5483,6 @@
"timespan": [ "timespan": [
"cpe:2.3:a:timespan_project:timespan:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:timespan_project:timespan:*:*:*:*:*:node.js:*:*"
], ],
"tinacms": [
"cpe:2.3:a:ssw:tinacms:*:*:*:*:*:node.js:*:*"
],
"tiny-conf": [ "tiny-conf": [
"cpe:2.3:a:tiny-conf_project:tiny-conf:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:tiny-conf_project:tiny-conf:*:*:*:*:*:node.js:*:*"
], ],
@ -5642,9 +5591,6 @@
"ungit": [ "ungit": [
"cpe:2.3:a:ungit_project:ungit:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:ungit_project:ungit:*:*:*:*:*:node.js:*:*"
], ],
"unhead": [
"cpe:2.3:a:unjs:unhead:*:*:*:*:*:node.js:*:*"
],
"unicode": [ "unicode": [
"cpe:2.3:a:unicode_project:unicode:*:*:*:*:*:node.js:*:*" "cpe:2.3:a:unicode_project:unicode:*:*:*:*:*:node.js:*:*"
], ],
@ -6026,9 +5972,6 @@
"b2sdk": [ "b2sdk": [
"cpe:2.3:a:backblaze:b2-sdk-python:*:*:*:*:*:*:*:*" "cpe:2.3:a:backblaze:b2-sdk-python:*:*:*:*:*:*:*:*"
], ],
"black": [
"cpe:2.3:a:python:black:*:*:*:*:*:python:*:*"
],
"blackduck": [ "blackduck": [
"cpe:2.3:a:synopsys:hub-rest-api-python:*:*:*:*:*:*:*:*" "cpe:2.3:a:synopsys:hub-rest-api-python:*:*:*:*:*:*:*:*"
], ],
@ -6096,9 +6039,6 @@
"datapizza-ai": [ "datapizza-ai": [
"cpe:2.3:a:datapizza:datapizza_ai:*:*:*:*:*:*:*:*" "cpe:2.3:a:datapizza:datapizza_ai:*:*:*:*:*:*:*:*"
], ],
"dbt-common": [
"cpe:2.3:a:getdbt:dbt-common:*:*:*:*:*:*:*:*"
],
"decorator": [ "decorator": [
"cpe:2.3:a:python:decorator:*:*:*:*:*:*:*:*" "cpe:2.3:a:python:decorator:*:*:*:*:*:*:*:*"
], ],
@ -6223,18 +6163,12 @@
"lxml-html-clean": [ "lxml-html-clean": [
"cpe:2.3:a:fedoralovespython:lxml_html_clean:*:*:*:*:*:python:*:*" "cpe:2.3:a:fedoralovespython:lxml_html_clean:*:*:*:*:*:python:*:*"
], ],
"mad-proxy": [
"cpe:2.3:a:machphy:mad-proxy:*:*:*:*:*:python:*:*"
],
"mage-ai": [ "mage-ai": [
"cpe:2.3:a:mage:mage-ai:*:*:*:*:*:python:*:*" "cpe:2.3:a:mage:mage-ai:*:*:*:*:*:python:*:*"
], ],
"marshmallow": [ "marshmallow": [
"cpe:2.3:a:marshmallow_project:marshmallow:*:*:*:*:*:python:*:*" "cpe:2.3:a:marshmallow_project:marshmallow:*:*:*:*:*:python:*:*"
], ],
"mcp-memory-service": [
"cpe:2.3:a:doobidoo:mcp-memory-service:*:*:*:*:*:*:*:*"
],
"mltable": [ "mltable": [
"cpe:2.3:a:microsoft:azure_machine_learning_software_development_kit:*:*:*:*:*:*:*:*" "cpe:2.3:a:microsoft:azure_machine_learning_software_development_kit:*:*:*:*:*:*:*:*"
], ],
@ -6433,9 +6367,6 @@
"scoptrial": [ "scoptrial": [
"cpe:2.3:a:scoptrial_project:scoptrial:*:*:*:*:*:pypi:*:*" "cpe:2.3:a:scoptrial_project:scoptrial:*:*:*:*:*:pypi:*:*"
], ],
"semantic-kernel": [
"cpe:2.3:a:microsoft:semantic_kernel:*:*:*:*:*:python:*:*"
],
"sentry-sdk": [ "sentry-sdk": [
"cpe:2.3:a:sentry:sentry_software_development_kit:*:*:*:*:*:python:*:*" "cpe:2.3:a:sentry:sentry_software_development_kit:*:*:*:*:*:python:*:*"
], ],
@ -6685,9 +6616,6 @@
"gon": [ "gon": [
"cpe:2.3:a:gon_project:gon:*:*:*:*:*:ruby:*:*" "cpe:2.3:a:gon_project:gon:*:*:*:*:*:ruby:*:*"
], ],
"graphiti": [
"cpe:2.3:a:graphiti:graphiti:*:*:*:*:*:ruby:*:*"
],
"gyazo": [ "gyazo": [
"cpe:2.3:a:gyazo_project:gyazo:*:*:*:*:*:ruby:*:*" "cpe:2.3:a:gyazo_project:gyazo:*:*:*:*:*:ruby:*:*"
], ],
@ -7066,15 +6994,6 @@
"autorand": [ "autorand": [
"cpe:2.3:a:autorand_project:autorand:*:*:*:*:*:rust:*:*" "cpe:2.3:a:autorand_project:autorand:*:*:*:*:*:rust:*:*"
], ],
"aws-lc-fips-sys": [
"cpe:2.3:a:amazon:aws-lc-fips-sys:*:*:*:*:*:rust:*:*"
],
"aws-lc-rs": [
"cpe:2.3:a:amazon:aws-lc-rs:*:*:*:*:*:rust:*:*"
],
"aws-lc-sys": [
"cpe:2.3:a:amazon:aws-lc-sys:*:*:*:*:*:rust:*:*"
],
"axum-core": [ "axum-core": [
"cpe:2.3:a:axum-core_project:axum-core:*:*:*:*:*:rust:*:*" "cpe:2.3:a:axum-core_project:axum-core:*:*:*:*:*:rust:*:*"
], ],
@ -9253,9 +9172,6 @@
"bravo-translate": [ "bravo-translate": [
"cpe:2.3:a:guelbetech:bravo_translate:*:*:*:*:*:wordpress:*:*" "cpe:2.3:a:guelbetech:bravo_translate:*:*:*:*:*:wordpress:*:*"
], ],
"bread-butter": [
"cpe:2.3:a:breadbutter:bread_\\\u0026_butter:*:*:*:*:*:wordpress:*:*"
],
"breadcrumbs-by-menu": [ "breadcrumbs-by-menu": [
"cpe:2.3:a:holest:breadcrumbs_by_menu:*:*:*:*:*:wordpress:*:*" "cpe:2.3:a:holest:breadcrumbs_by_menu:*:*:*:*:*:wordpress:*:*"
], ],
@ -9494,7 +9410,8 @@
"cpe:2.3:a:kieranoshea:calendar:*:*:*:*:*:wordpress:*:*" "cpe:2.3:a:kieranoshea:calendar:*:*:*:*:*:wordpress:*:*"
], ],
"calendar-booking": [ "calendar-booking": [
"cpe:2.3:a:startbooking:scheduling_plugin:*:*:*:*:*:wordpress:*:*" "cpe:2.3:a:startbooking:scheduling_plugin:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:startbooking:scheduling_plugin_-_online_booking:*:*:*:*:*:wordpress:*:*"
], ],
"calendar-plugin": [ "calendar-plugin": [
"cpe:2.3:a:calendar_plugin_project:calendar_plugin:*:*:*:*:*:wordpress:*:*" "cpe:2.3:a:calendar_plugin_project:calendar_plugin:*:*:*:*:*:wordpress:*:*"
@ -10109,9 +10026,6 @@
"contact-form-7-paypal-add-on": [ "contact-form-7-paypal-add-on": [
"cpe:2.3:a:wpplugin:paypal_\\\u0026_stripe_add-on:*:*:*:*:*:wordpress:*:*" "cpe:2.3:a:wpplugin:paypal_\\\u0026_stripe_add-on:*:*:*:*:*:wordpress:*:*"
], ],
"contact-form-7-recaptcha": [
"cpe:2.3:a:iambriansreed:contact_form_7_recaptcha:*:*:*:*:*:wordpress:*:*"
],
"contact-form-7-simple-recaptcha": [ "contact-form-7-simple-recaptcha": [
"cpe:2.3:a:contact_form_7_captcha_project:contact_form_7_captcha:*:*:*:*:*:wordpress:*:*" "cpe:2.3:a:contact_form_7_captcha_project:contact_form_7_captcha:*:*:*:*:*:wordpress:*:*"
], ],
@ -13535,7 +13449,7 @@
"cpe:2.3:a:brijeshk89:ip_based_login:*:*:*:*:*:wordpress:*:*" "cpe:2.3:a:brijeshk89:ip_based_login:*:*:*:*:*:wordpress:*:*"
], ],
"ip-blacklist-cloud": [ "ip-blacklist-cloud": [
"cpe:2.3:a:ad33lx:ip_blacklist_cloud:*:*:*:*:*:wordpress:*:*" "cpe:2.3:a:ip_blacklist_cloud_project:ip_blacklist_cloud:*:*:*:*:*:wordpress:*:*"
], ],
"ip-vault-wp-firewall": [ "ip-vault-wp-firewall": [
"cpe:2.3:a:youtag:two-factor_authentication:*:*:*:*:*:wordpress:*:*" "cpe:2.3:a:youtag:two-factor_authentication:*:*:*:*:*:wordpress:*:*"

View File

@ -270,7 +270,7 @@ func (c *NVDAPIClient) fetchPage(ctx context.Context, startIndex int, start, end
// handleRateLimit handles HTTP 429 responses by parsing Retry-After and waiting // handleRateLimit handles HTTP 429 responses by parsing Retry-After and waiting
func (c *NVDAPIClient) handleRateLimit(ctx context.Context, httpResp *http.Response, attempt int) error { func (c *NVDAPIClient) handleRateLimit(ctx context.Context, httpResp *http.Response, attempt int) error {
body, _ := io.ReadAll(httpResp.Body) //nolint:gocritic // offline code generator body, _ := io.ReadAll(httpResp.Body)
httpResp.Body.Close() httpResp.Body.Close()
// parse Retry-After header // parse Retry-After header
@ -298,7 +298,7 @@ func checkHTTPStatus(httpResp *http.Response) error {
if httpResp.StatusCode == http.StatusOK { if httpResp.StatusCode == http.StatusOK {
return nil return nil
} }
body, _ := io.ReadAll(httpResp.Body) //nolint:gocritic // offline code generator body, _ := io.ReadAll(httpResp.Body)
httpResp.Body.Close() httpResp.Body.Close()
return fmt.Errorf("NVD API error (status %d): %s", httpResp.StatusCode, string(body)) return fmt.Errorf("NVD API error (status %d): %s", httpResp.StatusCode, string(body))
} }

View File

@ -24,7 +24,6 @@ import (
"github.com/anchore/syft/internal/cmptest" "github.com/anchore/syft/internal/cmptest"
"github.com/anchore/syft/internal/licenses" "github.com/anchore/syft/internal/licenses"
"github.com/anchore/syft/internal/relationship" "github.com/anchore/syft/internal/relationship"
"github.com/anchore/syft/internal/tmpdir"
"github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/internal/fileresolver" "github.com/anchore/syft/syft/internal/fileresolver"
@ -63,7 +62,7 @@ type CatalogTester struct {
skipTestObservations bool skipTestObservations bool
} }
func initLicenseScanner() { func Context() context.Context {
once.Do(func() { once.Do(func() {
// most of the time in testing is initializing the scanner. Let's do that just once // most of the time in testing is initializing the scanner. Let's do that just once
sc := &licenses.ScannerConfig{Scanner: licensecheck.Scan, CoverageThreshold: 75} sc := &licenses.ScannerConfig{Scanner: licensecheck.Scan, CoverageThreshold: 75}
@ -73,20 +72,13 @@ func initLicenseScanner() {
} }
licenseScanner = &scanner licenseScanner = &scanner
}) })
}
// Context returns a context with a shared license scanner and a TempDir backed by t.TempDir(), return licenses.SetContextLicenseScanner(context.Background(), *licenseScanner)
// so cleanup is handled automatically when the test finishes.
func Context(t *testing.T) context.Context {
t.Helper()
initLicenseScanner()
td := tmpdir.FromPath(t.TempDir())
ctx := tmpdir.WithValue(context.Background(), td)
return licenses.SetContextLicenseScanner(ctx, *licenseScanner)
} }
func NewCatalogTester() *CatalogTester { func NewCatalogTester() *CatalogTester {
return &CatalogTester{ return &CatalogTester{
context: Context(),
locationComparer: cmptest.DefaultLocationComparer, locationComparer: cmptest.DefaultLocationComparer,
licenseComparer: cmptest.DefaultLicenseComparer, licenseComparer: cmptest.DefaultLicenseComparer,
packageStringer: stringPackage, packageStringer: stringPackage,
@ -280,18 +272,9 @@ func (p *CatalogTester) WithoutTestObserver() *CatalogTester {
return p return p
} }
func (p *CatalogTester) ensureContext(t *testing.T) context.Context {
t.Helper()
if p.context != nil {
return p.context
}
return Context(t)
}
func (p *CatalogTester) TestParser(t *testing.T, parser generic.Parser) { func (p *CatalogTester) TestParser(t *testing.T, parser generic.Parser) {
t.Helper() t.Helper()
ctx := p.ensureContext(t) pkgs, relationships, err := parser(p.context, p.resolver, p.env, p.reader)
pkgs, relationships, err := parser(ctx, p.resolver, p.env, p.reader)
// only test for errors if explicitly requested // only test for errors if explicitly requested
if p.wantErr != nil { if p.wantErr != nil {
@ -306,11 +289,10 @@ func (p *CatalogTester) TestParser(t *testing.T, parser generic.Parser) {
func (p *CatalogTester) TestCataloger(t *testing.T, cataloger pkg.Cataloger) { func (p *CatalogTester) TestCataloger(t *testing.T, cataloger pkg.Cataloger) {
t.Helper() t.Helper()
ctx := p.ensureContext(t)
resolver := NewObservingResolver(p.resolver) resolver := NewObservingResolver(p.resolver)
pkgs, relationships, err := cataloger.Catalog(ctx, resolver) pkgs, relationships, err := cataloger.Catalog(p.context, resolver)
// this is a minimum set, the resolver may return more that just this list // this is a minimum set, the resolver may return more that just this list
for _, path := range p.expectedPathResponses { for _, path := range p.expectedPathResponses {

View File

@ -18,7 +18,6 @@ import (
"github.com/anchore/syft/internal" "github.com/anchore/syft/internal"
intFile "github.com/anchore/syft/internal/file" intFile "github.com/anchore/syft/internal/file"
"github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/log"
"github.com/anchore/syft/internal/tmpdir"
"github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/internal/unknown"
"github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
@ -105,11 +104,7 @@ func newJavaArchiveParser(ctx context.Context, reader file.LocationReadCloser, d
virtualElements := strings.Split(reader.Path(), ":") virtualElements := strings.Split(reader.Path(), ":")
currentFilepath := virtualElements[len(virtualElements)-1] currentFilepath := virtualElements[len(virtualElements)-1]
td := tmpdir.FromContext(ctx) contentPath, archivePath, cleanupFn, err := saveArchiveToTmp(currentFilepath, reader)
if td == nil {
return nil, func() {}, fmt.Errorf("no temp dir factory in context")
}
contentPath, archivePath, cleanupFn, err := saveArchiveToTmp(td, currentFilepath, reader)
if err != nil { if err != nil {
return nil, cleanupFn, fmt.Errorf("unable to process java archive: %w", err) return nil, cleanupFn, fmt.Errorf("unable to process java archive: %w", err)
} }

View File

@ -2,6 +2,7 @@ package java
import ( import (
"bufio" "bufio"
"context"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -29,7 +30,7 @@ import (
func TestSearchMavenForLicenses(t *testing.T) { func TestSearchMavenForLicenses(t *testing.T) {
url := maventest.MockRepo(t, "internal/maven/testdata/maven-repo") url := maventest.MockRepo(t, "internal/maven/testdata/maven-repo")
ctx := pkgtest.Context(t) ctx := pkgtest.Context()
tests := []struct { tests := []struct {
name string name string
@ -71,7 +72,7 @@ func TestSearchMavenForLicenses(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// setup parser // setup parser
ap, cleanupFn, err := newJavaArchiveParser(pkgtest.Context(t), ap, cleanupFn, err := newJavaArchiveParser(context.Background(),
file.LocationReadCloser{ file.LocationReadCloser{
Location: file.NewLocation(fixture.Name()), Location: file.NewLocation(fixture.Name()),
ReadCloser: fixture, ReadCloser: fixture,
@ -80,17 +81,17 @@ func TestSearchMavenForLicenses(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// assert licenses are discovered from upstream // assert licenses are discovered from upstream
_, _, _, parsedPom := ap.discoverMainPackageFromPomInfo(pkgtest.Context(t)) _, _, _, parsedPom := ap.discoverMainPackageFromPomInfo(context.Background())
require.NotNil(t, parsedPom, "expected to find pom information in the fixture") require.NotNil(t, parsedPom, "expected to find pom information in the fixture")
require.NotNil(t, parsedPom.project, "expected parsedPom to have a project") require.NotNil(t, parsedPom.project, "expected parsedPom to have a project")
resolvedLicenses, _ := ap.maven.ResolveLicenses(pkgtest.Context(t), parsedPom.project) resolvedLicenses, _ := ap.maven.ResolveLicenses(context.Background(), parsedPom.project)
assert.Equal(t, tc.expectedLicenses, toPkgLicenses(ctx, nil, resolvedLicenses)) assert.Equal(t, tc.expectedLicenses, toPkgLicenses(ctx, nil, resolvedLicenses))
}) })
} }
} }
func TestParseJar(t *testing.T) { func TestParseJar(t *testing.T) {
ctx := pkgtest.Context(t) ctx := pkgtest.Context()
tests := []struct { tests := []struct {
name string name string
fixture string fixture string
@ -371,7 +372,7 @@ func TestParseJar(t *testing.T) {
UseNetwork: false, UseNetwork: false,
UseMavenLocalRepository: false, UseMavenLocalRepository: false,
} }
parser, cleanupFn, err := newJavaArchiveParser(pkgtest.Context(t), parser, cleanupFn, err := newJavaArchiveParser(context.Background(),
file.LocationReadCloser{ file.LocationReadCloser{
Location: file.NewLocation(fixture.Name()), Location: file.NewLocation(fixture.Name()),
ReadCloser: fixture, ReadCloser: fixture,
@ -661,7 +662,7 @@ func TestParseNestedJar(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
gap := newGenericArchiveParserAdapter(ArchiveCatalogerConfig{}) gap := newGenericArchiveParserAdapter(ArchiveCatalogerConfig{})
actual, _, err := gap.processJavaArchive(pkgtest.Context(t), file.LocationReadCloser{ actual, _, err := gap.processJavaArchive(context.Background(), file.LocationReadCloser{
Location: file.NewLocation(fixture.Name()), Location: file.NewLocation(fixture.Name()),
ReadCloser: fixture, ReadCloser: fixture,
}, nil) }, nil)
@ -1079,7 +1080,7 @@ func Test_newPackageFromMavenData(t *testing.T) {
test.expectedParent.Locations = locations test.expectedParent.Locations = locations
r := maven.NewResolver(nil, maven.DefaultConfig()) r := maven.NewResolver(nil, maven.DefaultConfig())
actualPackage := newPackageFromMavenData(pkgtest.Context(t), r, test.props, test.project, test.parent, file.NewLocation(virtualPath)) actualPackage := newPackageFromMavenData(context.Background(), r, test.props, test.project, test.parent, file.NewLocation(virtualPath))
if test.expectedPackage == nil { if test.expectedPackage == nil {
require.Nil(t, actualPackage) require.Nil(t, actualPackage)
} else { } else {
@ -1119,7 +1120,7 @@ func Test_artifactIDMatchesFilename(t *testing.T) {
} }
func Test_parseJavaArchive_regressions(t *testing.T) { func Test_parseJavaArchive_regressions(t *testing.T) {
ctx := pkgtest.Context(t) ctx := context.TODO()
apiAll := pkg.Package{ apiAll := pkg.Package{
Name: "api-all", Name: "api-all",
Version: "2.0.0", Version: "2.0.0",
@ -1498,7 +1499,7 @@ func Test_deterministicMatchingPomProperties(t *testing.T) {
fixture, err := os.Open(fixturePath) fixture, err := os.Open(fixturePath)
require.NoError(t, err) require.NoError(t, err)
parser, cleanupFn, err := newJavaArchiveParser(pkgtest.Context(t), parser, cleanupFn, err := newJavaArchiveParser(context.Background(),
file.LocationReadCloser{ file.LocationReadCloser{
Location: file.NewLocation(fixture.Name()), Location: file.NewLocation(fixture.Name()),
ReadCloser: fixture, ReadCloser: fixture,
@ -1506,7 +1507,7 @@ func Test_deterministicMatchingPomProperties(t *testing.T) {
defer cleanupFn() defer cleanupFn()
require.NoError(t, err) require.NoError(t, err)
groupID, artifactID, version, _ := parser.discoverMainPackageFromPomInfo(pkgtest.Context(t)) groupID, artifactID, version, _ := parser.discoverMainPackageFromPomInfo(context.TODO())
require.Equal(t, test.expected, maven.NewID(groupID, artifactID, version)) require.Equal(t, test.expected, maven.NewID(groupID, artifactID, version))
}() }()
} }
@ -1633,9 +1634,9 @@ func Test_jarPomPropertyResolutionDoesNotPanic(t *testing.T) {
fixture, err := os.Open(jarName) fixture, err := os.Open(jarName)
require.NoError(t, err) require.NoError(t, err)
ctx := pkgtest.Context(t) ctx := context.TODO()
// setup parser // setup parser
ap, cleanupFn, err := newJavaArchiveParser(pkgtest.Context(t), ap, cleanupFn, err := newJavaArchiveParser(context.Background(),
file.LocationReadCloser{ file.LocationReadCloser{
Location: file.NewLocation(fixture.Name()), Location: file.NewLocation(fixture.Name()),
ReadCloser: fixture, ReadCloser: fixture,

View File

@ -40,7 +40,7 @@ func ParsePomXML(content io.Reader) (project *Project, err error) {
} }
func getUtf8Reader(content io.Reader) (io.Reader, error) { func getUtf8Reader(content io.Reader) (io.Reader, error) {
pomContents, err := io.ReadAll(content) //nolint:gocritic // charset detection requires full buffer pomContents, err := io.ReadAll(content)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -463,7 +463,7 @@ func (r *Resolver) cacheResolveReader(key string, resolve func() (io.ReadCloser,
defer internal.CloseAndLogError(contentReader, key) defer internal.CloseAndLogError(contentReader, key)
// store the contents to return a new reader with the same content // store the contents to return a new reader with the same content
contents, err := io.ReadAll(contentReader) //nolint:gocritic // caching requires full buffer contents, err := io.ReadAll(contentReader)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -1,6 +1,7 @@
package java package java
import ( import (
"context"
"os" "os"
"testing" "testing"
@ -193,7 +194,7 @@ func Test_parseCommonsTextPomXMLProject(t *testing.T) {
func Test_parsePomXMLProject(t *testing.T) { func Test_parsePomXMLProject(t *testing.T) {
// TODO: ideally we would have the path to the contained pom.xml, not the jar // TODO: ideally we would have the path to the contained pom.xml, not the jar
jarLocation := file.NewLocation("path/to/archive.jar") jarLocation := file.NewLocation("path/to/archive.jar")
ctx := pkgtest.Context(t) ctx := context.TODO()
tests := []struct { tests := []struct {
name string name string
project *pkg.JavaPomProject project *pkg.JavaPomProject
@ -264,11 +265,11 @@ func Test_parsePomXMLProject(t *testing.T) {
pom, err := maven.ParsePomXML(fixture) pom, err := maven.ParsePomXML(fixture)
require.NoError(t, err) require.NoError(t, err)
actual := newPomProject(pkgtest.Context(t), r, fixture.Name(), pom) actual := newPomProject(context.Background(), r, fixture.Name(), pom)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, test.project, actual) assert.Equal(t, test.project, actual)
licenses, err := r.ResolveLicenses(pkgtest.Context(t), pom) licenses, err := r.ResolveLicenses(context.Background(), pom)
//assert.NoError(t, err) //assert.NoError(t, err)
assert.Equal(t, test.licenses, toPkgLicenses(ctx, &jarLocation, licenses)) assert.Equal(t, test.licenses, toPkgLicenses(ctx, &jarLocation, licenses))
}) })
@ -330,7 +331,7 @@ func Test_pomParent(t *testing.T) {
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
r := maven.NewResolver(nil, maven.DefaultConfig()) r := maven.NewResolver(nil, maven.DefaultConfig())
assert.Equal(t, test.expected, pomParent(pkgtest.Context(t), r, &maven.Project{Parent: test.input})) assert.Equal(t, test.expected, pomParent(context.Background(), r, &maven.Project{Parent: test.input}))
}) })
} }
} }
@ -432,7 +433,7 @@ func Test_resolveLicenses(t *testing.T) {
fr, err := ds.FileResolver(source.AllLayersScope) fr, err := ds.FileResolver(source.AllLayersScope)
require.NoError(t, err) require.NoError(t, err)
ctx := pkgtest.Context(t) ctx := context.TODO()
pkgs, _, err := cat.Catalog(ctx, fr) pkgs, _, err := cat.Catalog(ctx, fr)
require.NoError(t, err) require.NoError(t, err)

View File

@ -6,16 +6,23 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/anchore/syft/internal/tmpdir" "github.com/anchore/syft/internal/log"
) )
func saveArchiveToTmp(td *tmpdir.TempDir, archiveVirtualPath string, reader io.Reader) (string, string, func(), error) { func saveArchiveToTmp(archiveVirtualPath string, reader io.Reader) (string, string, func(), error) {
name := filepath.Base(archiveVirtualPath) name := filepath.Base(archiveVirtualPath)
tempDir, cleanupFn, err := td.NewChild("archive-contents") //nolint:gocritic // cleanup is returned to caller, not deferred here tempDir, err := os.MkdirTemp("", "syft-archive-contents-")
if err != nil { if err != nil {
return "", "", func() {}, fmt.Errorf("unable to create tempdir for archive processing: %w", err) return "", "", func() {}, fmt.Errorf("unable to create tempdir for archive processing: %w", err)
} }
cleanupFn := func() {
err = os.RemoveAll(tempDir)
if err != nil {
log.Errorf("unable to cleanup archive tempdir: %+v", err)
}
}
archivePath := filepath.Join(tempDir, "archive-"+name) archivePath := filepath.Join(tempDir, "archive-"+name)
contentDir := filepath.Join(tempDir, "contents") contentDir := filepath.Join(tempDir, "contents")
@ -30,9 +37,6 @@ func saveArchiveToTmp(td *tmpdir.TempDir, archiveVirtualPath string, reader io.R
} }
defer archiveFile.Close() defer archiveFile.Close()
// note: no size limit here — the reader comes from a file already enumerated by the
// resolver, not from an untrusted network source. The file size is bounded by the
// source image/directory being scanned.
_, err = io.Copy(archiveFile, reader) _, err = io.Copy(archiveFile, reader)
if err != nil { if err != nil {
return contentDir, archivePath, cleanupFn, fmt.Errorf("unable to copy archive: %w", err) return contentDir, archivePath, cleanupFn, fmt.Errorf("unable to copy archive: %w", err)

View File

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
intFile "github.com/anchore/syft/internal/file" intFile "github.com/anchore/syft/internal/file"
"github.com/anchore/syft/internal/tmpdir"
"github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
@ -59,11 +58,7 @@ func newGenericTarWrappedJavaArchiveParser(cfg ArchiveCatalogerConfig) genericTa
} }
func (gtp genericTarWrappedJavaArchiveParser) parseTarWrappedJavaArchive(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { func (gtp genericTarWrappedJavaArchiveParser) parseTarWrappedJavaArchive(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
td := tmpdir.FromContext(ctx) contentPath, archivePath, cleanupFn, err := saveArchiveToTmp(reader.Path(), reader)
if td == nil {
return nil, nil, fmt.Errorf("no temp dir factory in context")
}
contentPath, archivePath, cleanupFn, err := saveArchiveToTmp(td, reader.Path(), reader)
// note: even on error, we should always run cleanup functions // note: even on error, we should always run cleanup functions
defer cleanupFn() defer cleanupFn()
if err != nil { if err != nil {

View File

@ -1,6 +1,7 @@
package java package java
import ( import (
"context"
"os" "os"
"path" "path"
"testing" "testing"
@ -49,7 +50,7 @@ func Test_parseTarWrappedJavaArchive(t *testing.T) {
} }
gtp := newGenericTarWrappedJavaArchiveParser(ArchiveCatalogerConfig{}) gtp := newGenericTarWrappedJavaArchiveParser(ArchiveCatalogerConfig{})
actualPkgs, _, err := gtp.parseTarWrappedJavaArchive(pkgtest.Context(t), nil, nil, file.LocationReadCloser{ actualPkgs, _, err := gtp.parseTarWrappedJavaArchive(context.Background(), nil, nil, file.LocationReadCloser{
Location: file.NewLocation(test.fixture), Location: file.NewLocation(test.fixture),
ReadCloser: fixture, ReadCloser: fixture,
}) })

View File

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
intFile "github.com/anchore/syft/internal/file" intFile "github.com/anchore/syft/internal/file"
"github.com/anchore/syft/internal/tmpdir"
"github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
@ -31,11 +30,7 @@ func newGenericZipWrappedJavaArchiveParser(cfg ArchiveCatalogerConfig) genericZi
} }
func (gzp genericZipWrappedJavaArchiveParser) parseZipWrappedJavaArchive(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { func (gzp genericZipWrappedJavaArchiveParser) parseZipWrappedJavaArchive(ctx context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
td := tmpdir.FromContext(ctx) contentPath, archivePath, cleanupFn, err := saveArchiveToTmp(reader.Path(), reader)
if td == nil {
return nil, nil, fmt.Errorf("no temp dir factory in context")
}
contentPath, archivePath, cleanupFn, err := saveArchiveToTmp(td, reader.Path(), reader)
// note: even on error, we should always run cleanup functions // note: even on error, we should always run cleanup functions
defer cleanupFn() defer cleanupFn()
if err != nil { if err != nil {

View File

@ -1,6 +1,7 @@
package java package java
import ( import (
"context"
"os" "os"
"path" "path"
"testing" "testing"
@ -9,7 +10,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
) )
func Test_parseZipWrappedJavaArchive(t *testing.T) { func Test_parseZipWrappedJavaArchive(t *testing.T) {
@ -36,7 +36,7 @@ func Test_parseZipWrappedJavaArchive(t *testing.T) {
gzp := newGenericZipWrappedJavaArchiveParser(ArchiveCatalogerConfig{}) gzp := newGenericZipWrappedJavaArchiveParser(ArchiveCatalogerConfig{})
actualPkgs, _, err := gzp.parseZipWrappedJavaArchive(pkgtest.Context(t), nil, nil, file.LocationReadCloser{ actualPkgs, _, err := gzp.parseZipWrappedJavaArchive(context.Background(), nil, nil, file.LocationReadCloser{
Location: file.NewLocation(test.fixture), Location: file.NewLocation(test.fixture),
ReadCloser: fixture, ReadCloser: fixture,
}) })

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"net/http" "net/http"
"net/url" "net/url"
"path" "path"
@ -256,12 +257,19 @@ func getLicenseFromNpmRegistry(baseURL, packageName, version string) (string, er
} }
}() }()
bytes, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("unable to parse package from npm registry: %w", err)
}
dec := json.NewDecoder(strings.NewReader(string(bytes)))
// Read "license" from the response // Read "license" from the response
var license struct { var license struct {
License string `json:"license"` License string `json:"license"`
} }
if err := json.NewDecoder(resp.Body).Decode(&license); err != nil { if err := dec.Decode(&license); err != nil {
return "", fmt.Errorf("unable to parse license from npm registry: %w", err) return "", fmt.Errorf("unable to parse license from npm registry: %w", err)
} }
@ -316,8 +324,14 @@ func parseLicensesFromLocation(l file.Location, resolver file.Resolver, pkgFile
} }
defer internal.CloseAndLogError(contentReader, l.RealPath) defer internal.CloseAndLogError(contentReader, l.RealPath)
contents, err := io.ReadAll(contentReader)
if err != nil {
log.Debugf("error reading file contents for %s: %v", pkgFile, err)
return nil, err
}
var pkgJSON packageJSON var pkgJSON packageJSON
err = json.NewDecoder(contentReader).Decode(&pkgJSON) err = json.Unmarshal(contents, &pkgJSON)
if err != nil { if err != nil {
log.Debugf("error parsing %s: %v", pkgFile, err) log.Debugf("error parsing %s: %v", pkgFile, err)
return nil, err return nil, err

View File

@ -179,7 +179,7 @@ func newPnpmLockfileParser(version float64) pnpmLockfileParser {
// parsePnpmLock is the main parser function for pnpm-lock.yaml files. // parsePnpmLock is the main parser function for pnpm-lock.yaml files.
func (a genericPnpmLockAdapter) parsePnpmLock(ctx context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { func (a genericPnpmLockAdapter) parsePnpmLock(ctx context.Context, resolver file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
data, err := io.ReadAll(reader) //nolint:gocritic // multi-pass parse requires []byte data, err := io.ReadAll(reader)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("failed to load pnpm-lock.yaml file: %w", err) return nil, nil, fmt.Errorf("failed to load pnpm-lock.yaml file: %w", err)
} }

View File

@ -166,8 +166,7 @@ func findDevOnlyPkgs(yarnPkgs []yarnPackage, prodDeps, devDeps map[string]string
} }
func parseYarnV1LockFile(reader io.ReadCloser) ([]yarnPackage, error) { func parseYarnV1LockFile(reader io.ReadCloser) ([]yarnPackage, error) {
// TODO: refactor to use bufio.Scanner for streaming line-by-line parsing instead of reading the entire file content, err := io.ReadAll(reader)
content, err := io.ReadAll(reader) //nolint:gocritic // stateful multi-line parser; candidate for streaming refactor
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read yarn.lock file: %w", err) return nil, fmt.Errorf("failed to read yarn.lock file: %w", err)
} }
@ -266,8 +265,7 @@ func (a genericYarnLockAdapter) parseYarnLock(ctx context.Context, resolver file
return nil, nil, nil return nil, nil, nil
} }
// TODO: refactor to detect version from the first line via bufio.Scanner, then dispatch to a streaming parser data, err := io.ReadAll(reader)
data, err := io.ReadAll(reader) //nolint:gocritic // two-pass parse: version detection then format-specific parsing
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("failed to load yarn.lock file: %w", err) return nil, nil, fmt.Errorf("failed to load yarn.lock file: %w", err)
} }

View File

@ -39,7 +39,7 @@ var noReturn = rockspec{
// parseRockspec basic parser for rockspec // parseRockspec basic parser for rockspec
func parseRockspecData(reader io.Reader) (rockspec, error) { func parseRockspecData(reader io.Reader) (rockspec, error) {
data, err := io.ReadAll(reader) //nolint:gocritic // custom parser requires []byte data, err := io.ReadAll(reader)
if err != nil { if err != nil {
return noReturn, err return noReturn, err
} }

View File

@ -46,7 +46,7 @@ func (c cataloger) Name() string {
func (c cataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) { func (c cataloger) Catalog(ctx context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
// always try the DB cataloger first (based off of information recorded by actions taken by nix tooling) // always try the DB cataloger first (based off of information recorded by actions taken by nix tooling)
pkgs, rels, err := c.dbParser.catalog(ctx, resolver) pkgs, rels, err := c.dbParser.catalog(resolver)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("failed to catalog nix packages from database: %w", err) return nil, nil, fmt.Errorf("failed to catalog nix packages from database: %w", err)
} }

View File

@ -1,9 +1,8 @@
package nix package nix
import ( import (
"bufio"
"context"
"fmt" "fmt"
"io"
"path" "path"
"strconv" "strconv"
"strings" "strings"
@ -18,7 +17,7 @@ import (
const defaultSchema = 10 const defaultSchema = 10
type dbProcessor func(ctx context.Context, config Config, dbLocation file.Location, resolver file.Resolver, catalogerName string) ([]pkg.Package, []artifact.Relationship, error) type dbProcessor func(config Config, dbLocation file.Location, resolver file.Resolver, catalogerName string) ([]pkg.Package, []artifact.Relationship, error)
type dbCataloger struct { type dbCataloger struct {
config Config config Config
@ -46,7 +45,7 @@ type dbPackageEntry struct {
Files []string Files []string
} }
func (c dbCataloger) catalog(ctx context.Context, resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) { func (c dbCataloger) catalog(resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) {
dbLocs, err := resolver.FilesByGlob("**/nix/var/nix/db/db.sqlite") dbLocs, err := resolver.FilesByGlob("**/nix/var/nix/db/db.sqlite")
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("failed to find Nix database: %w", err) return nil, nil, fmt.Errorf("failed to find Nix database: %w", err)
@ -66,7 +65,7 @@ func (c dbCataloger) catalog(ctx context.Context, resolver file.Resolver) ([]pkg
continue continue
} }
newPkgs, newRelationships, err := parser(ctx, c.config, dbLoc, resolver, c.catalogerName) newPkgs, newRelationships, err := parser(c.config, dbLoc, resolver, c.catalogerName)
if err != nil { if err != nil {
errs = unknown.Append(errs, dbLoc.Coordinates, err) errs = unknown.Append(errs, dbLoc.Coordinates, err)
continue continue
@ -93,13 +92,13 @@ func (c dbCataloger) selectDBParser(dbLocation file.Location, resolver file.Reso
return c.schemaProcessor[defaultSchema], 0 return c.schemaProcessor[defaultSchema], 0
} }
scanner := bufio.NewScanner(schemaContents) contents, err := io.ReadAll(schemaContents)
if !scanner.Scan() { if err != nil {
log.WithFields("path", loc.RealPath).Tracef("failed to read Nix database schema file, assuming %d", defaultSchema) log.WithFields("path", loc.RealPath).Tracef("failed to read Nix database schema file, assuming %d", defaultSchema)
return c.schemaProcessor[defaultSchema], 0 return c.schemaProcessor[defaultSchema], 0
} }
schema, err := strconv.Atoi(strings.TrimSpace(scanner.Text())) schema, err := strconv.Atoi(strings.TrimSpace(string(contents)))
if err != nil { if err != nil {
log.WithFields("path", loc.RealPath).Tracef("failed to parse Nix database schema file, assuming %d", defaultSchema) log.WithFields("path", loc.RealPath).Tracef("failed to parse Nix database schema file, assuming %d", defaultSchema)
return c.schemaProcessor[defaultSchema], 0 return c.schemaProcessor[defaultSchema], 0

View File

@ -1,7 +1,6 @@
package nix package nix
import ( import (
"context"
"database/sql" "database/sql"
"fmt" "fmt"
"io" "io"
@ -9,7 +8,6 @@ import (
"github.com/anchore/syft/internal" "github.com/anchore/syft/internal"
"github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/log"
"github.com/anchore/syft/internal/tmpdir"
"github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
@ -17,33 +15,26 @@ import (
var _ dbProcessor = processV10DB var _ dbProcessor = processV10DB
func processV10DB(ctx context.Context, config Config, dbLocation file.Location, resolver file.Resolver, catalogerName string) ([]pkg.Package, []artifact.Relationship, error) { func processV10DB(config Config, dbLocation file.Location, resolver file.Resolver, catalogerName string) ([]pkg.Package, []artifact.Relationship, error) {
dbContents, err := resolver.FileContentsByLocation(dbLocation) dbContents, err := resolver.FileContentsByLocation(dbLocation)
defer internal.CloseAndLogError(dbContents, dbLocation.RealPath) defer internal.CloseAndLogError(dbContents, dbLocation.RealPath)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("unable to read Nix database: %w", err) return nil, nil, fmt.Errorf("unable to read Nix database: %w", err)
} }
td := tmpdir.FromContext(ctx) tempDB, err := createTempDB(dbContents)
if td == nil {
return nil, nil, fmt.Errorf("no temp dir factory in context")
}
tempDB, cleanupDB, err := createTempDB(td, dbContents)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("failed to create temporary database: %w", err) return nil, nil, fmt.Errorf("failed to create temporary database: %w", err)
} }
// defer order is LIFO: cleanupDB (remove file) must run after db.Close and tempDB.Close defer os.RemoveAll(tempDB.Name())
defer cleanupDB()
// close order is LIFO: db.Close() (SQLite conn) → tempDB.Close() (file handle) → cleanupDB (remove file)
defer tempDB.Close()
db, err := sql.Open("sqlite", tempDB.Name()) db, err := sql.Open("sqlite", tempDB.Name())
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("failed to open database: %w", err) return nil, nil, fmt.Errorf("failed to open database: %w", err)
} }
defer db.Close()
db.SetConnMaxLifetime(0) db.SetConnMaxLifetime(0)
defer db.Close()
packageEntries, err := extractV10DBPackages(config, db, dbLocation, resolver) packageEntries, err := extractV10DBPackages(config, db, dbLocation, resolver)
if err != nil { if err != nil {
@ -241,20 +232,18 @@ func finalizeV10DBResults(db *sql.DB, packageEntries map[int]*dbPackageEntry, ca
return pkgs, relationships, nil return pkgs, relationships, nil
} }
func createTempDB(td *tmpdir.TempDir, content io.ReadCloser) (*os.File, func(), error) { func createTempDB(content io.ReadCloser) (*os.File, error) {
noop := func() {} tempFile, err := os.CreateTemp("", "nix-db-*.sqlite")
tempFile, cleanup, err := td.NewFile("nix-db-*.sqlite") //nolint:gocritic // cleanup is returned to caller, not deferred here
if err != nil { if err != nil {
return nil, noop, err return nil, err
} }
_, err = io.Copy(tempFile, content) _, err = io.Copy(tempFile, content)
if err != nil { if err != nil {
tempFile.Close() tempFile.Close()
cleanup() os.Remove(tempFile.Name())
return nil, noop, err return nil, err
} }
return tempFile, cleanup, nil return tempFile, nil
} }

View File

@ -25,7 +25,7 @@ func parseOpamPackage(ctx context.Context, _ file.Resolver, _ *generic.Environme
homepageRe := regexp.MustCompile(`(?m)homepage:\s*"(?P<url>[^"]+)"`) homepageRe := regexp.MustCompile(`(?m)homepage:\s*"(?P<url>[^"]+)"`)
urlRe := regexp.MustCompile(`(?m)url\s*{(?P<url>[^}]+)}`) urlRe := regexp.MustCompile(`(?m)url\s*{(?P<url>[^}]+)}`)
data, err := io.ReadAll(reader) //nolint:gocritic // regex matching requires full buffer data, err := io.ReadAll(reader)
if err != nil { if err != nil {
log.WithFields("error", err).Trace("unable to read opam package") log.WithFields("error", err).Trace("unable to read opam package")
return nil, nil, nil return nil, nil, nil

View File

@ -58,7 +58,7 @@ func parsePear(ctx context.Context, _ file.Resolver, _ *generic.Environment, rea
// parsePeclPearSerialized is a parser function for Pear metadata contents, returning "Default" php packages discovered. // parsePeclPearSerialized is a parser function for Pear metadata contents, returning "Default" php packages discovered.
func parsePeclPearSerialized(reader file.LocationReadCloser) (*peclPearData, error) { func parsePeclPearSerialized(reader file.LocationReadCloser) (*peclPearData, error) {
data, err := io.ReadAll(reader) //nolint:gocritic // phpserialize requires []byte data, err := io.ReadAll(reader)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read file: %w", err) return nil, fmt.Errorf("failed to read file: %w", err)

View File

@ -473,7 +473,7 @@ func Test_PackageCataloger_IgnorePackage(t *testing.T) {
t.Run(test.MetadataFixture, func(t *testing.T) { t.Run(test.MetadataFixture, func(t *testing.T) {
resolver := file.NewMockResolverForPaths(test.MetadataFixture) resolver := file.NewMockResolverForPaths(test.MetadataFixture)
actual, _, err := NewInstalledPackageCataloger().Catalog(pkgtest.Context(t), resolver) actual, _, err := NewInstalledPackageCataloger().Catalog(pkgtest.Context(), resolver)
require.NoError(t, err) require.NoError(t, err)
if len(actual) != 0 { if len(actual) != 0 {

View File

@ -4,8 +4,10 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"net/http" "net/http"
"net/url" "net/url"
"strings"
"time" "time"
"github.com/anchore/syft/internal/cache" "github.com/anchore/syft/internal/cache"
@ -98,6 +100,13 @@ func getLicenseFromPypiRegistry(baseURL, packageName, version string) (string, e
return "", fmt.Errorf("unable to get package from pypi registry") return "", fmt.Errorf("unable to get package from pypi registry")
} }
bytes, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("unable to parse package from pypi registry: %w", err)
}
dec := json.NewDecoder(strings.NewReader(string(bytes)))
// Read "license" from the response // Read "license" from the response
var pypiResponse struct { var pypiResponse struct {
Info struct { Info struct {
@ -106,7 +115,7 @@ func getLicenseFromPypiRegistry(baseURL, packageName, version string) (string, e
} `json:"info"` } `json:"info"`
} }
if err := json.NewDecoder(resp.Body).Decode(&pypiResponse); err != nil { if err := dec.Decode(&pypiResponse); err != nil {
return "", fmt.Errorf("unable to parse license from pypi registry: %w", err) return "", fmt.Errorf("unable to parse license from pypi registry: %w", err)
} }

View File

@ -143,7 +143,7 @@ func (ulp uvLockParser) uvLockPackages(ctx context.Context, reader file.Location
var parsedLockFileVersion uvLockFileVersion var parsedLockFileVersion uvLockFileVersion
// we cannot use the reader twice, so we read the contents first --uv.lock files tend to be small enough // we cannot use the reader twice, so we read the contents first --uv.lock files tend to be small enough
contents, err := io.ReadAll(reader) //nolint:gocritic // multi-pass parse requires []byte contents, err := io.ReadAll(reader)
if err != nil { if err != nil {
return nil, unknown.New(reader.Location, fmt.Errorf("failed to read uv lock file: %w", err)) return nil, unknown.New(reader.Location, fmt.Errorf("failed to read uv lock file: %w", err))
} }

View File

@ -4,6 +4,7 @@ import (
"bufio" "bufio"
"context" "context"
"encoding/json" "encoding/json"
"io"
"path" "path"
"path/filepath" "path/filepath"
"strings" "strings"
@ -173,8 +174,13 @@ func fetchDirectURLData(resolver file.Resolver, metadataLocation file.Location)
} }
defer internal.CloseAndLogError(directURLContents, directURLLocation.AccessPath) defer internal.CloseAndLogError(directURLContents, directURLLocation.AccessPath)
buffer, err := io.ReadAll(directURLContents)
if err != nil {
return nil, nil, err
}
var directURLJson directURLOrigin var directURLJson directURLOrigin
if err := json.NewDecoder(directURLContents).Decode(&directURLJson); err != nil { if err := json.Unmarshal(buffer, &directURLJson); err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -5,11 +5,11 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"os"
"strings" "strings"
rpmdb "github.com/anchore/go-rpmdb/pkg" rpmdb "github.com/anchore/go-rpmdb/pkg"
"github.com/anchore/syft/internal/log" "github.com/anchore/syft/internal/log"
"github.com/anchore/syft/internal/tmpdir"
"github.com/anchore/syft/internal/unknown" "github.com/anchore/syft/internal/unknown"
"github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file" "github.com/anchore/syft/syft/file"
@ -22,16 +22,21 @@ import (
// //
//nolint:funlen //nolint:funlen
func parseRpmDB(ctx context.Context, resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { func parseRpmDB(ctx context.Context, resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
td := tmpdir.FromContext(ctx) f, err := os.CreateTemp("", "rpmdb")
if td == nil {
return nil, nil, fmt.Errorf("no temp dir factory in context")
}
f, cleanup, err := td.NewFile("rpmdb-*")
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("failed to create temp rpmdb file: %w", err) return nil, nil, fmt.Errorf("failed to create temp rpmdb file: %w", err)
} }
defer cleanup()
defer f.Close() defer func() {
err = f.Close()
if err != nil {
log.Errorf("failed to close temp rpmdb file: %+v", err)
}
err = os.Remove(f.Name())
if err != nil {
log.Errorf("failed to remove temp rpmdb file: %+v", err)
}
}()
_, err = io.Copy(f, reader) _, err = io.Copy(f, reader)
if err != nil { if err != nil {

View File

@ -85,6 +85,6 @@ func adaptToReadSeeker(reader io.Reader) (io.ReadSeeker, error) {
log.Debug("SBOM cataloger reader is not a ReadSeeker, reading entire SBOM into memory") log.Debug("SBOM cataloger reader is not a ReadSeeker, reading entire SBOM into memory")
var buff bytes.Buffer var buff bytes.Buffer
_, err := io.Copy(&buff, reader) //nolint:gocritic // buffering to ReadSeeker _, err := io.Copy(&buff, reader)
return bytes.NewReader(buff.Bytes()), err return bytes.NewReader(buff.Bytes()), err
} }

View File

@ -3,6 +3,7 @@ package swift
import ( import (
"context" "context"
"fmt" "fmt"
"io"
"strings" "strings"
"go.yaml.in/yaml/v3" "go.yaml.in/yaml/v3"
@ -27,8 +28,12 @@ type podfileLock struct {
// parsePodfileLock is a parser function for Podfile.lock contents, returning all cocoapods pods discovered. // parsePodfileLock is a parser function for Podfile.lock contents, returning all cocoapods pods discovered.
func parsePodfileLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { func parsePodfileLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
bytes, err := io.ReadAll(reader)
if err != nil {
return nil, nil, fmt.Errorf("unable to read file: %w", err)
}
var podfile podfileLock var podfile podfileLock
if err := yaml.NewDecoder(reader).Decode(&podfile); err != nil { if err = yaml.Unmarshal(bytes, &podfile); err != nil {
return nil, nil, fmt.Errorf("unable to parse yaml: %w", err) return nil, nil, fmt.Errorf("unable to parse yaml: %w", err)
} }

View File

@ -20,7 +20,7 @@ func parsePackPackage(ctx context.Context, resolver file.Resolver, _ *generic.En
homeRe := regexp.MustCompile(`home\(\s*'([^']+)'\s*\)`) homeRe := regexp.MustCompile(`home\(\s*'([^']+)'\s*\)`)
authorRe := regexp.MustCompile(`(author|packager)\(\s*'([^']+)'\s*(?:,\s*'([^']+)'\s*)?\)`) authorRe := regexp.MustCompile(`(author|packager)\(\s*'([^']+)'\s*(?:,\s*'([^']+)'\s*)?\)`)
data, err := io.ReadAll(reader) //nolint:gocritic // regex matching requires full buffer data, err := io.ReadAll(reader)
if err != nil { if err != nil {
log.WithFields("error", err).Trace("unable to parse Rockspec app") log.WithFields("error", err).Trace("unable to parse Rockspec app")
return nil, nil, nil return nil, nil, nil

View File

@ -20,7 +20,7 @@ type terraformLockFile struct {
func parseTerraformLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { func parseTerraformLock(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
var lockFile terraformLockFile var lockFile terraformLockFile
contents, err := io.ReadAll(reader) //nolint:gocritic // hclsimple.Decode requires []byte contents, err := io.ReadAll(reader)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("failed to read terraform lock file: %w", err) return nil, nil, fmt.Errorf("failed to read terraform lock file: %w", err)
} }

View File

@ -411,7 +411,7 @@ func (b *licenseBuilder) licenseFromContentHash(content string) License {
} }
func contentFromReader(r io.Reader) (string, error) { func contentFromReader(r io.Reader) (string, error) {
bytes, err := io.ReadAll(r) //nolint:gocritic // reading license content for storage bytes, err := io.ReadAll(r)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -3,6 +3,7 @@ package snapsource
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"net/http" "net/http"
"regexp" "regexp"
"strconv" "strconv"
@ -214,8 +215,13 @@ func (c *snapcraftClient) GetSnapDownloadURL(id snapIdentity) (string, error) {
return "", fmt.Errorf("API request failed with status code %d", resp.StatusCode) return "", fmt.Errorf("API request failed with status code %d", resp.StatusCode)
} }
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("failed to read response body: %w", err)
}
var info snapcraftInfo var info snapcraftInfo
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil { if err := json.Unmarshal(body, &info); err != nil {
return "", fmt.Errorf("failed to parse JSON response: %w", err) return "", fmt.Errorf("failed to parse JSON response: %w", err)
} }
@ -253,8 +259,13 @@ func (c *snapcraftClient) CheckSnapExists(snapName string) (bool, string, error)
return false, "", fmt.Errorf("find API request failed with status code %d", resp.StatusCode) return false, "", fmt.Errorf("find API request failed with status code %d", resp.StatusCode)
} }
body, err := io.ReadAll(resp.Body)
if err != nil {
return false, "", fmt.Errorf("failed to read find response body: %w", err)
}
var findResp snapFindResponse var findResp snapFindResponse
if err := json.NewDecoder(resp.Body).Decode(&findResp); err != nil { if err := json.Unmarshal(body, &findResp); err != nil {
return false, "", fmt.Errorf("failed to parse find JSON response: %w", err) return false, "", fmt.Errorf("failed to parse find JSON response: %w", err)
} }

View File

@ -2,15 +2,14 @@ version: "3"
vars: vars:
CPE_CACHE_DIR: "syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/.cpe-cache" CPE_CACHE_DIR: "syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator/.cpe-cache"
CPE_CACHE_REGISTRY: "ghcr.io/anchore/oss-cache/cpe-cache:latest" CPE_CACHE_REGISTRY: "ghcr.io/anchore/syft/cpe-cache:latest"
CPE_CACHE_REPO: "oss-cache"
CPE_INDEX_OUTPUT: "syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json" CPE_INDEX_OUTPUT: "syft/pkg/cataloger/internal/cpegenerate/dictionary/data/cpe-index.json"
CPE_GENERATOR_DIR: "syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator" CPE_GENERATOR_DIR: "syft/pkg/cataloger/internal/cpegenerate/dictionary/index-generator"
tasks: tasks:
cache:pull: cache:pull:
desc: Pull CPE cache from ORAS registry (ghcr.io/anchore/oss-cache/cpe-cache:latest) desc: Pull CPE cache from ORAS registry (ghcr.io/anchore/syft/cpe-cache:latest)
deps: [':tools'] # deps: [tools]
cmds: cmds:
- cmd: | - cmd: |
set -eu set -eu
@ -117,7 +116,7 @@ tasks:
# push compressed files to ORAS (from cache directory, so only basenames are used) # push compressed files to ORAS (from cache directory, so only basenames are used)
echo "Pushing compressed files to registry..." echo "Pushing compressed files to registry..."
"$oras_bin" push {{ .CPE_CACHE_REGISTRY }} $compressed_files \ "$oras_bin" push {{ .CPE_CACHE_REGISTRY }} $compressed_files \
--annotation org.opencontainers.image.source=https://github.com/{{ .OWNER }}/{{ .CPE_CACHE_REPO }} \ --annotation org.opencontainers.image.source=https://github.com/{{ .OWNER }}/{{ .PROJECT }} \
--annotation org.opencontainers.image.created=$(date -u +"%Y-%m-%dT%H:%M:%SZ") --annotation org.opencontainers.image.created=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# clean up compressed files # clean up compressed files

View File

@ -24,50 +24,6 @@ func isPtr(ctx *dsl.VarFilterContext) bool {
return strings.HasPrefix(ctx.Type.String(), "*") || strings.HasPrefix(ctx.Type.Underlying().String(), "*") return strings.HasPrefix(ctx.Type.String(), "*") || strings.HasPrefix(ctx.Type.Underlying().String(), "*")
} }
// nolint:unused
func noUnboundedReads(m dsl.Matcher) {
// flag io.ReadAll where the argument is not already wrapped in io.LimitReader
m.Match(`io.ReadAll($reader)`).
Where(!m["reader"].Text.Matches(`(?i)LimitReader|LimitedReader`)).
Report("do not use unbounded io.ReadAll; wrap the reader with io.LimitReader or use a streaming parser")
// flag io.Copy only when the destination is an in-memory buffer
// io.Copy to files, hash writers, encoders, etc. is streaming and safe
m.Match(`io.Copy($dst, $src)`).
Where((m["dst"].Type.Is(`*bytes.Buffer`) || m["dst"].Type.Is(`*strings.Builder`)) && !m["src"].Text.Matches(`(?i)LimitReader|LimitedReader`)).
Report("do not use unbounded io.Copy to in-memory buffer; wrap the source reader with io.LimitReader")
}
// nolint:unused
func noDirectTempFiles(m dsl.Matcher) {
// catalogers must use tmpdir.FromContext(ctx) instead of creating temp files/dirs directly,
// so that all temp storage is centrally managed and cleaned up
m.Match(
`os.CreateTemp($*_)`,
`os.MkdirTemp($*_)`,
).
Where(m.File().PkgPath.Matches(`/cataloger/`)).
Report("do not use os.CreateTemp/os.MkdirTemp in catalogers; use tmpdir.FromContext(ctx) instead")
}
// nolint:unused
func tmpCleanupDeferred(m dsl.Matcher) {
// ensure the cleanup function returned by NewFile/NewChild is deferred, not discarded
m.Match(
`$_, $cleanup, $err := $x.NewFile($*_); if $*_ { $*_ }; $next`,
`$_, $cleanup, $err = $x.NewFile($*_); if $*_ { $*_ }; $next`,
).
Where(!m["next"].Text.Matches(`^defer `)).
Report("defer the cleanup function returned by NewFile immediately after the error check")
m.Match(
`$_, $cleanup, $err := $x.NewChild($*_); if $*_ { $*_ }; $next`,
`$_, $cleanup, $err = $x.NewChild($*_); if $*_ { $*_ }; $next`,
).
Where(!m["next"].Text.Matches(`^defer `)).
Report("defer the cleanup function returned by NewChild immediately after the error check")
}
// nolint:unused // nolint:unused
func packagesInRelationshipsAsValues(m dsl.Matcher) { func packagesInRelationshipsAsValues(m dsl.Matcher) {
m.Import("github.com/anchore/syft/syft/artifact") m.Import("github.com/anchore/syft/syft/artifact")