Compare commits

..
Author SHA1 Message Date
Alex Goodman dfde0974b0 address reading archives into memory
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-05-13 10:56:57 -04:00
Will Bates 9f047fdf11 fix: detect compressed kernel modules (.ko.gz, .ko.xz, .ko.zst)
The linux-kernel-cataloger only matched plain *.ko files, missing
compressed modules produced when CONFIG_MODULE_COMPRESS is enabled
(common on Debian 13 / Ubuntu 24.04+). This resulted in near-zero
module packages being reported for such filesystems.

Changes:
- Add *.ko.gz, *.ko.xz, *.ko.zst glob patterns to both the cataloger
  and capabilities.yaml so the file resolver picks up compressed modules
- Add decompressedModuleReader() which detects the extension and
  transparently decompresses via compress/gzip, ulikunitz/xz, or
  klauspost/compress/zstd before handing the ELF bytes to the existing
  parseLinuxKernelModuleMetadata parser
- Promote github.com/klauspost/compress from indirect to direct dependency
- Add unit tests covering all three compression formats plus the
  uncompressed baseline, using a programmatically generated minimal ELF

Fixes #4721

Signed-off-by: Will Bates <william.bates11@outlook.com>
2026-05-13 10:08:53 -04:00
70 changed files with 817 additions and 1595 deletions
+101 -5
View File
@@ -1,11 +1,67 @@
# only pull in version updates that were released more than a week ago (low-pass filter for quickly-retracted releases)
cooldown: 7d
# Most tools (binny, chronicle, cosign, golangci-lint, goreleaser, gosimports,
# bouncer, quill, syft, task, gh) are inherited from anchore/go-make's embedded
# .binny.yaml — see https://github.com/anchore/go-make. Only syft-specific tools
# or version overrides should live here.
tools:
## internal tools ############################################################################
# we want to use a pinned version of binny to manage the toolchain (so binny manages itself!)
- name: binny
version:
want: v0.13.0
method: github-release
with:
repo: anchore/binny
# used to produce SBOMs during release
- name: syft
version:
want: v1.42.3
method: github-release
with:
repo: anchore/syft
# used to sign mac binaries at release
- name: quill
version:
want: v0.7.1
method: github-release
with:
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
- name: golangci-lint
version:
want: v2.11.4
method: github-release
with:
repo: golangci/golangci-lint
# used for showing the changelog at release
- name: glow
version:
want: v2.1.1
method: github-release
with:
repo: charmbracelet/glow
# used for signing the checksums file at release
- name: cosign
version:
want: v3.0.5
method: github-release
with:
repo: sigstore/cosign
# used in integration tests to verify JSON schemas
- name: yajsv
version:
@@ -14,6 +70,46 @@ tools:
with:
repo: neilpa/yajsv
# used to release all artifacts
- name: goreleaser
version:
want: v2.15.2
method: github-release
with:
repo: goreleaser/goreleaser
# used for organizing imports during static analysis
- name: gosimports
version:
want: v0.3.8
method: github-release
with:
repo: rinchsan/gosimports
# used during static analysis for license compliance
- name: bouncer
version:
want: v0.4.0
method: github-release
with:
repo: wagoodman/go-bouncer
# used for running all local and CI tasks
- name: task
version:
want: v3.49.1
method: github-release
with:
repo: go-task/task
# used for triggering a release
- name: gh
version:
want: v2.89.0
method: github-release
with:
repo: cli/cli
# used to upload test fixture cache
- name: oras
version:
@@ -22,7 +118,7 @@ tools:
with:
repo: oras-project/oras
# used to parse JSON/YAML annotations on the fixture cache image
# used to upload test fixture cache
- name: yq
version:
want: v4.52.5
+33 -34
View File
@@ -1,45 +1,55 @@
name: "Bootstrap"
description: "Bootstrap all syft tools and dependencies on top of go-make's setup action"
# This action is a thin wrapper around anchore/go-make/.github/actions/setup which
# already handles checkout, setup-go, restore-only build/mod cache, and tool cache.
# We add the syft-specific extras here: apt packages and the test fixture cache.
description: "Bootstrap all tools and dependencies"
inputs:
go-version:
description: "Go version to install (passed to go-make/setup)"
description: "Go version to install"
required: true
default: "1.26.2"
cache-key-prefix:
description: "Prefix all cache keys with this value (passed to go-make/setup)"
required: true
default: "v1"
cache-enabled:
description: "Enable build/mod and tool caching (passed to go-make/setup)"
go-dependencies:
description: "Download go dependencies"
required: true
default: "true"
cache-key-prefix:
description: "Prefix all cache keys with this value"
required: true
default: "53ac821810"
download-test-fixture-cache:
description: "Download test fixture cache from OCI and github actions"
required: true
default: "false"
tools:
description: "whether to install tools"
default: "true"
bootstrap-apt-packages:
description: "Space delimited list of tools to install via apt"
default: "libxml2-utils"
runs:
using: "composite"
steps:
- name: Setup go + go-make tooling
uses: anchore/go-make/.github/actions/setup@9de27be11ed73e2f9d5406a836a492b7d8aa1225 # v0.5.0
# note: go mod and build is automatically cached on default with v4+
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
if: inputs.go-version != ''
with:
go-version: ${{ inputs.go-version }}
cache-key-prefix: ${{ inputs.cache-key-prefix }}
cache-enabled: ${{ inputs.cache-enabled }}
- name: Install binny-managed tools
check-latest: true
- name: Restore tool cache
if: inputs.tools == 'true'
id: tool-cache
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ github.workspace }}/.tool
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('.binny.yaml') }}
- name: Install project tools
shell: bash
run: make binny:install
if: inputs.tools == 'true'
run: |
make tools
.tool/binny list
.tool/binny check
- name: Install go dependencies
if: inputs.go-dependencies == 'true'
shell: bash
run: make ci-bootstrap-go
- name: Install apt packages
if: inputs.bootstrap-apt-packages != ''
shell: bash
@@ -48,23 +58,12 @@ runs:
run: |
IFS=' ' read -ra packages <<< "$APT_PACKAGES"
DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y "${packages[@]}"
# ORAS cache: restore-only on non-default branches / forks
- name: Restore ORAS cache from github actions
if: ${{ inputs.download-test-fixture-cache == 'true' && (github.ref != format('refs/heads/{0}', github.event.repository.default_branch) || github.event.repository.fork == true) }}
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ github.workspace }}/.tmp/oras-cache
key: ${{ inputs.cache-key-prefix }}-oras-cache
# ORAS cache: restore + save on the default branch of the canonical repo only.
- name: Restore and save ORAS cache from github actions
if: ${{ inputs.download-test-fixture-cache == 'true' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && github.event.repository.fork == false }}
if: inputs.download-test-fixture-cache == 'true'
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ github.workspace }}/.tmp/oras-cache
key: ${{ inputs.cache-key-prefix }}-oras-cache
- name: Download test fixture cache
if: inputs.download-test-fixture-cache == 'true'
shell: bash
+1 -3
View File
@@ -14,9 +14,7 @@ version: 2
updates:
- package-ecosystem: gomod
directories:
- "/"
- "/.make"
directory: "/"
cooldown:
default-days: 7
schedule:
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env bash
red=$(tput setaf 1)
bold=$(tput bold)
normal=$(tput sgr0)
# assert we are running in CI (or die!)
if [[ -z "$CI" ]]; then
echo "${bold}${red}This step should ONLY be run in CI. Exiting...${normal}"
exit 1
fi
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env python3
import subprocess
import sys
import shlex
class bcolors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKCYAN = '\033[96m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
if len(sys.argv) < 3:
print("Usage: coverage.py [threshold] [go-coverage-report]")
sys.exit(1)
threshold = float(sys.argv[1])
report = sys.argv[2]
args = shlex.split(f"go tool cover -func {report}")
p = subprocess.run(args, capture_output=True, text=True)
percent_coverage = float(p.stdout.splitlines()[-1].split()[-1].replace("%", ""))
print(f"{bcolors.BOLD}Coverage: {percent_coverage}%{bcolors.ENDC}")
if percent_coverage < threshold:
print(f"{bcolors.BOLD}{bcolors.FAIL}Coverage below threshold of {threshold}%{bcolors.ENDC}")
sys.exit(1)
+34 -51
View File
@@ -1,45 +1,35 @@
#!/usr/bin/env python3
from __future__ import annotations
import glob
import hashlib
import json
import os
import glob
import sys
import json
import hashlib
IGNORED_PREFIXES = []
def find_fingerprints_and_check_dirs(base_dir):
all_fingerprints = set(
glob.glob(
os.path.join(base_dir, "**", "test*", "**", "*.fingerprint"), recursive=True
)
)
all_fingerprints = set(glob.glob(os.path.join(base_dir, '**', 'test*', '**', '*.fingerprint'), recursive=True))
all_fingerprints = {
os.path.relpath(fp)
for fp in all_fingerprints
if not any(fp.startswith(prefix) for prefix in IGNORED_PREFIXES)
}
all_fingerprints = {os.path.relpath(fp) for fp in all_fingerprints
if not any(fp.startswith(prefix) for prefix in IGNORED_PREFIXES)}
if not all_fingerprints:
show("No .fingerprint files or cache directories found.")
exit(1)
orphan_fingerprints = []
empty_content = []
missing_content = []
valid_paths = set()
fingerprint_contents = []
for fingerprint in all_fingerprints:
path = fingerprint.replace(".fingerprint", "")
path = fingerprint.replace('.fingerprint', '')
if not os.path.exists(path):
# paired content path is entirely missing — the .fingerprint is likely
# leftover from a moved/deleted source (testdata trees are git-ignored,
# so they persist locally across rename refactors)
orphan_fingerprints.append(fingerprint)
missing_content.append(path)
continue
if not os.path.isdir(path):
@@ -49,13 +39,13 @@ def find_fingerprints_and_check_dirs(base_dir):
if os.listdir(path):
valid_paths.add(path)
else:
empty_content.append(path)
missing_content.append(path)
with open(fingerprint, "r") as f:
with open(fingerprint, 'r') as f:
content = f.read().strip()
fingerprint_contents.append((fingerprint, content))
return sorted(valid_paths), empty_content, orphan_fingerprints, fingerprint_contents
return sorted(valid_paths), missing_content, fingerprint_contents
def parse_fingerprint_contents(fingerprint_content):
@@ -69,9 +59,7 @@ def parse_fingerprint_contents(fingerprint_content):
def calculate_sha256(fingerprint_contents):
sorted_fingerprint_contents = sorted(fingerprint_contents, key=lambda x: x[0])
concatenated_contents = "".join(
content for _, content in sorted_fingerprint_contents
)
concatenated_contents = ''.join(content for _, content in sorted_fingerprint_contents)
sha256_hash = hashlib.sha256(concatenated_contents.encode()).hexdigest()
@@ -80,7 +68,7 @@ def calculate_sha256(fingerprint_contents):
def calculate_file_sha256(file_path):
sha256_hash = hashlib.sha256()
with open(file_path, "rb") as f:
with open(file_path, 'rb') as f:
for byte_block in iter(lambda: f.read(4096), b""):
sha256_hash.update(byte_block)
return sha256_hash.hexdigest()
@@ -91,28 +79,17 @@ def show(*s: str):
def main(file_path: str | None):
base_dir = "."
valid_paths, empty_content, orphan_fingerprints, fingerprint_contents = (
find_fingerprints_and_check_dirs(base_dir)
)
base_dir = '.'
valid_paths, missing_content, fingerprint_contents = find_fingerprints_and_check_dirs(base_dir)
if empty_content:
show(
"The following paths exist but are empty, and have corresponding .fingerprint files:"
)
for path in sorted(empty_content):
if missing_content:
show("The following paths are missing or have no content, but have corresponding .fingerprint files:")
for path in sorted(missing_content):
show(f"- {path}")
# when adding new cache directories there is a time where it is not possible to have this directory without
# running the tests first... but this step is a prerequisite for running the tests. We should not block on this.
if orphan_fingerprints:
show(
"The following .fingerprint files reference paths that no longer exist "
"(likely leftover from a moved/deleted cataloger — safe to delete, "
"or run `task prune-orphan-fingerprints`):"
)
for fp in sorted(orphan_fingerprints):
show(f"- {fp}")
# show("Please ensure these paths exist and have content if they are directories.")
# exit(1)
sha256_hash = calculate_sha256(fingerprint_contents)
@@ -124,24 +101,30 @@ def main(file_path: str | None):
file_digest = calculate_file_sha256(fingerprint_file)
# Parse the fingerprint file to get the digest/path tuples
with open(fingerprint_file, "r") as f:
with open(fingerprint_file, 'r') as f:
fingerprint_content = f.read().strip()
input_map = parse_fingerprint_contents(fingerprint_content)
paths_with_digests.append(
{"path": path, "digest": file_digest, "input": input_map}
)
paths_with_digests.append({
"path": path,
"digest": file_digest,
"input": input_map
})
except Exception as e:
show(f"Error processing {fingerprint_file}: {e}")
raise e
output = {"digest": sha256_hash, "paths": paths_with_digests}
output = {
"digest": sha256_hash,
"paths": paths_with_digests
}
content = json.dumps(output, indent=2, sort_keys=True)
if file_path:
with open(file_path, "w") as f:
with open(file_path, 'w') as f:
f.write(content)
print(content)
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
set -eu
ORIGINAL_STATE_DIR=$(mktemp -d "TEMP-original-state-XXXXXXXXX")
TIDY_STATE_DIR=$(mktemp -d "TEMP-tidy-state-XXXXXXXXX")
trap "cp -p ${ORIGINAL_STATE_DIR}/* ./ && git update-index -q --refresh && rm -fR ${ORIGINAL_STATE_DIR} ${TIDY_STATE_DIR}" EXIT
# capturing original state of files...
cp go.mod go.sum "${ORIGINAL_STATE_DIR}"
# capturing state of go.mod and go.sum after running go mod tidy...
go mod tidy
cp go.mod go.sum "${TIDY_STATE_DIR}"
set +e
# detect difference between the git HEAD state and the go mod tidy state
DIFF_MOD=$(diff -u "${ORIGINAL_STATE_DIR}/go.mod" "${TIDY_STATE_DIR}/go.mod")
DIFF_SUM=$(diff -u "${ORIGINAL_STATE_DIR}/go.sum" "${TIDY_STATE_DIR}/go.sum")
if [[ -n "${DIFF_MOD}" || -n "${DIFF_SUM}" ]]; then
echo "go.mod diff:"
echo "${DIFF_MOD}"
echo "go.sum diff:"
echo "${DIFF_SUM}"
echo ""
printf "FAILED! go.mod and/or go.sum are NOT tidy; please run 'go mod tidy'.\n\n"
exit 1
fi
@@ -1,102 +0,0 @@
#!/usr/bin/env python3
"""
Remove orphan *.fingerprint files left behind by moved/deleted catalogers.
A fingerprint is considered orphaned when:
1. its paired content path (the fingerprint path with `.fingerprint` stripped)
does not exist, AND
2. the nearest ancestor `testdata/` directory has no `Makefile` claiming
responsibility for generating that path.
The second condition is the safety check: if there is a Makefile, the
fingerprint is "live" and might just be waiting for fixtures to be built —
leave it alone. Without a Makefile, nothing in-repo will ever regenerate
the content, so the fingerprint is dead weight that triggers spurious
"missing path" warnings.
Empty parent directories are also pruned after removing the fingerprint.
Use --dry-run to preview without deleting.
"""
from __future__ import annotations
import argparse
import glob
import os
import sys
def find_ancestor_testdata(path: str) -> str | None:
d = os.path.dirname(path)
while d and d not in (".", os.sep):
if os.path.basename(d) == "testdata":
return d
d = os.path.dirname(d)
return None
def is_orphan(fingerprint: str) -> bool:
paired = fingerprint[: -len(".fingerprint")]
if os.path.exists(paired):
return False
testdata_dir = find_ancestor_testdata(fingerprint)
if testdata_dir and os.path.isfile(os.path.join(testdata_dir, "Makefile")):
# a Makefile exists that may regenerate this — not safe to prune
return False
return True
def prune_empty_parents(start: str, stop_at: str = ".") -> list[str]:
removed = []
d = os.path.dirname(start)
stop_at = os.path.abspath(stop_at)
while d and os.path.abspath(d) != stop_at:
try:
if not os.listdir(d):
os.rmdir(d)
removed.append(d)
d = os.path.dirname(d)
else:
break
except OSError:
break
return removed
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--dry-run",
action="store_true",
help="Show what would be removed without deleting anything",
)
args = parser.parse_args()
all_fingerprints = glob.glob("**/test*/**/*.fingerprint", recursive=True)
orphans = sorted(fp for fp in all_fingerprints if is_orphan(fp))
if not orphans:
print("no orphan fingerprints found")
return 0
verb = "would remove" if args.dry_run else "removing"
print(f"{verb} {len(orphans)} orphan fingerprint(s):")
for fp in orphans:
print(f"- {fp}")
if args.dry_run:
continue
try:
os.remove(fp)
except OSError as e:
print(f" ! failed to remove: {e}", file=sys.stderr)
continue
for d in prune_empty_parents(fp):
print(f" (also removed empty dir {d})")
return 0
if __name__ == "__main__":
sys.exit(main())
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env bash
set -eu
bold=$(tput bold)
normal=$(tput sgr0)
GH_CLI=.tool/gh
if ! [ -x "$(command -v $GH_CLI)" ]; then
echo "The GitHub CLI could not be found. run: make bootstrap"
exit 1
fi
$GH_CLI auth status
# set the default repo in cases where multiple remotes are defined
$GH_CLI repo set-default anchore/syft
export GITHUB_TOKEN="${GITHUB_TOKEN-"$($GH_CLI auth token)"}"
# we need all of the git state to determine the next version. Since tagging is done by
# the release pipeline it is possible to not have all of the tags from previous releases.
git fetch --tags
# populates the CHANGELOG.md and VERSION files
echo "${bold}Generating changelog...${normal}"
make changelog 2> /dev/null
NEXT_VERSION=$(cat VERSION)
if [[ "$NEXT_VERSION" == "" || "${NEXT_VERSION}" == "(Unreleased)" ]]; then
echo "Could not determine the next version to release. Exiting..."
exit 1
fi
while true; do
read -p "${bold}Do you want to trigger a release for version '${NEXT_VERSION}'?${normal} [y/n] " yn
case $yn in
[Yy]* ) echo; break;;
[Nn]* ) echo; echo "Cancelling release..."; exit;;
* ) echo "Please answer yes or no.";;
esac
done
echo "${bold}Kicking off release for ${NEXT_VERSION}${normal}..."
echo
$GH_CLI workflow run release.yaml -f version=${NEXT_VERSION}
echo
echo "${bold}Waiting for release to start...${normal}"
sleep 10
set +e
echo "${bold}Head to the release workflow to monitor the release:${normal} $($GH_CLI run list --workflow=release.yaml --limit=1 --json url --jq '.[].url')"
id=$($GH_CLI run list --workflow=release.yaml --limit=1 --json databaseId --jq '.[].databaseId')
$GH_CLI run watch $id --exit-status || (echo ; echo "${bold}Logs of failed step:${normal}" && GH_PAGER="" $GH_CLI run view $id --log-failed)
+1 -1
View File
@@ -13,7 +13,7 @@ permissions: {}
jobs:
analyze:
name: Analyze
uses: anchore/workflows/.github/workflows/codeql.yaml@b3e328b5ae31ba96297e2ed9a6124e5e6352a4c5 # v0.7.0
uses: anchore/workflows/.github/workflows/codeql.yaml@e8cee3a5916cebb68cda68b54c180f43394c1910 # v0.5.0
permissions:
security-events: write
packages: read
+43 -20
View File
@@ -23,20 +23,18 @@ on:
- "install-script-only"
jobs:
version-available:
if: ${{ github.event.inputs.phase == 'all' }}
permissions:
contents: read # required for fetching tags
uses: anchore/workflows/.github/workflows/check-version-available.yaml@b3e328b5ae31ba96297e2ed9a6124e5e6352a4c5 # v0.7.0
uses: anchore/workflows/.github/workflows/check-version-available.yaml@8b2b1caf40e03933c6807e03b99e883e2ceb5ac8 # v0.4.0
with:
version: ${{ github.event.inputs.version }}
check-gate:
if: ${{ github.event.inputs.phase == 'all' }}
permissions:
contents: read
checks: read # required for getting the status of specific check names
uses: anchore/workflows/.github/workflows/check-gate.yaml@b3e328b5ae31ba96297e2ed9a6124e5e6352a4c5 # v0.7.0
checks: read # required for getting the status of specific check names
uses: anchore/workflows/.github/workflows/check-gate.yaml@8b2b1caf40e03933c6807e03b99e883e2ceb5ac8 # v0.4.0
with:
# these are checks that should be run on pull-request and merges to main.
# we do NOT want to kick off a release if these have not been verified on main.
@@ -44,9 +42,8 @@ jobs:
checks: '["Acceptance tests (Linux)", "Acceptance tests (Mac)", "Build snapshot artifacts", "CLI tests (Linux)", "Integration tests", "Static analysis", "Unit tests"]'
release:
needs: [check-gate, version-available]
needs: [ check-gate, version-available ]
if: ${{ github.event.inputs.phase == 'all' }}
environment: release
# runs-on.com: compute instances for parallel builds
# spot disabled: reliability for build workflows (used for releases too)
# goreleaser uses parallelism of 12, so we need more CPUs
@@ -54,9 +51,10 @@ jobs:
# tmpfs: faster io-intensive workflows
runs-on: runs-on=${{ github.run_id }}/cpu=16+32/ram=32+128/family=c5+c6+c7+c8/spot=false/extras=s3-cache+tmpfs
permissions:
contents: write # required for creating the GitHub release and pushing the version tag
packages: write # required for publishing release artifacts to GitHub packages
id-token: write # required for keyless signing (cosign/sigstore OIDC)
contents: write
packages: write
# required for goreleaser signs section with cosign
id-token: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
@@ -67,24 +65,31 @@ jobs:
uses: ./.github/actions/bootstrap
- name: Login to Docker Hub
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee #v4.2.0
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
with:
username: ${{ secrets.ANCHOREOSSWRITE_DH_USERNAME }}
password: ${{ secrets.ANCHOREOSSWRITE_DH_PAT }}
- name: Login to GitHub Container Registry
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee #v4.2.0
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Tag release
run: |
git config --global user.name "anchoreci"
git config --global user.email "anchoreci@users.noreply.github.com"
git tag -a "$VERSION" -m "Release $VERSION"
git push origin --tags
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ github.event.inputs.version }}
- name: Build & publish release artifacts
run: make ci-release
env:
# used for pushing tags
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
RELEASE_VERSION: ${{ github.event.inputs.version }}
# for mac signing and notarization...
QUILL_SIGN_P12: ${{ secrets.ANCHORE_APPLE_DEVELOPER_ID_CERT_CHAIN }}
QUILL_SIGN_PASSWORD: ${{ secrets.ANCHORE_APPLE_DEVELOPER_ID_CERT_PASS }}
@@ -102,12 +107,30 @@ jobs:
file: go.mod
artifact-name: sbom.spdx.json
- name: Notify Slack of new release
uses: slackapi/slack-github-action@45a88b9581bfab2566dc881e2cd66d334e621e2c #v3.0.3
continue-on-error: true
with:
webhook: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload: |
text: "A new Syft release has been published: https://github.com/anchore/syft/releases/tag/${{ github.event.inputs.version }}"
blocks:
- type: section
text:
type: mrkdwn
text: |
*A new Syft release has been published* :rocket:
• Release: <https://github.com/anchore/syft/releases/tag/${{ github.event.inputs.version }}|${{ github.event.inputs.version }}>
• Repo: `${{ github.repository }}`
• Workflow: `${{ github.workflow }}`
• Event: `${{ github.event_name }}`
if: ${{ success() }}
release-install-script:
needs: [release]
needs: [ release ]
if: ${{ always() && (needs.release.result == 'success' || github.event.inputs.phase == 'install-script-only') }}
permissions:
contents: read # required for the reusable workflow to check out the repo and publish the install script
uses: anchore/workflows/.github/workflows/release-install-script.yaml@b3e328b5ae31ba96297e2ed9a6124e5e6352a4c5 # v0.7.0
uses: "anchore/workflows/.github/workflows/release-install-script.yaml@main"
with:
tag: ${{ github.event.inputs.version }}
secrets:
@@ -25,7 +25,7 @@ jobs:
persist-credentials: false
- name: "Run zizmor"
uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6
uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3
with:
# there is a pass/fail gate as a repo ruleset (if there is no ruleset configured then the action will pass by default)
advanced-security: true
+14 -7
View File
@@ -21,10 +21,9 @@ jobs:
name: "Static analysis"
# runs-on.com: memory & general purpose instances for testing
# spot enabled: ok to interrupt non-production workloads
# s3-cache: faster actions cache
# tmpfs: faster io-intensive workflows
# note: s3-cache intentionally omitted -- PR runs are untrusted and must not write to the
# shared cache backend that the trusted release workflow reads from (cache poisoning).
runs-on: &test-runner "runs-on=${{ github.run_id }}/cpu=4+8/ram=32+128/family=r5+r6+r7+r8+m4+m5+m6+m7+m8/spot=price-capacity-optimized/extras=tmpfs"
runs-on: &test-runner "runs-on=${{ github.run_id }}/cpu=4+8/ram=32+128/family=r5+r6+r7+r8+m4+m5+m6+m7+m8/spot=price-capacity-optimized/extras=s3-cache+tmpfs"
permissions:
contents: read
steps:
@@ -92,13 +91,15 @@ jobs:
# runs-on.com: compute instances for parallel builds
# spot disabled: reliability for build workflows (used for releases too)
# goreleaser uses parallelism of 12, so we need more CPUs
# s3-cache: faster actions cache
# tmpfs: faster io-intensive workflows
# note: s3-cache intentionally omitted -- PR runs are untrusted and must not write to the
# shared cache backend that the trusted release workflow reads from (cache poisoning).
runs-on: "runs-on=${{ github.run_id }}/cpu=16+32/ram=32+128/family=c5+c6+c7+c8/spot=false/extras=tmpfs"
runs-on: "runs-on=${{ github.run_id }}/cpu=16+32/ram=32+128/family=c5+c6+c7+c8/spot=false/extras=s3-cache+tmpfs"
permissions:
contents: read
steps:
# required for magic-cache from runs-on to function with artifact upload/download (see https://runs-on.com/caching/magic-cache/#actionsupload-artifact-compatibility)
- uses: runs-on/action@742bf56072eb4845a0f94b3394673e4903c90ff0 # v2.1.0
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
persist-credentials: false
@@ -129,6 +130,9 @@ jobs:
permissions:
contents: read
steps:
# required for magic-cache from runs-on to function with artifact upload/download (see https://runs-on.com/caching/magic-cache/#actionsupload-artifact-compatibility)
- uses: runs-on/action@742bf56072eb4845a0f94b3394673e4903c90ff0 # v2.1.0
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
persist-credentials: false
@@ -171,7 +175,7 @@ jobs:
contents: read
steps:
- name: Install Cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
@@ -207,6 +211,9 @@ jobs:
permissions:
contents: read
steps:
# required for magic-cache from runs-on to function with artifact upload/download (see https://runs-on.com/caching/magic-cache/#actionsupload-artifact-compatibility)
- uses: runs-on/action@742bf56072eb4845a0f94b3394673e4903c90ff0 # v2.1.0
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
persist-credentials: false
+2 -4
View File
@@ -3,8 +3,6 @@ go.work
go.work.sum
.tool-versions
.python-version
.mise.toml
.env
# app configuration
/.syft.yaml
@@ -22,8 +20,6 @@ bin/
/generate
/specs
mise.toml
.make/.make
.conductor
# changelog generation
CHANGELOG.md
@@ -80,3 +76,5 @@ cosign.pub
__pycache__/
*.py[cod]
*$py.class
-14
View File
@@ -1,14 +0,0 @@
module github.com/anchore/syft/.make
go 1.25.8
require (
github.com/anchore/go-make v0.4.0
github.com/goccy/go-yaml v1.19.2
)
require (
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
golang.org/x/mod v0.35.0 // indirect
golang.org/x/sys v0.44.0 // indirect
)
-10
View File
@@ -1,10 +0,0 @@
github.com/anchore/go-make v0.4.0 h1:poFE4PXcHwvix2E8AhdM7YHZ15bMhZb+W02i3+qrP8M=
github.com/anchore/go-make v0.4.0/go.mod h1:Nc/tkwQHW1d1Vi8+0rtS/vSrH6pxieaUQXLdrctn+8g=
github.com/bmatcuk/doublestar/v4 v4.10.0 h1:zU9WiOla1YA122oLM6i4EXvGW62DvKZVxIe6TYWexEs=
github.com/bmatcuk/doublestar/v4 v4.10.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
-209
View File
@@ -1,209 +0,0 @@
package main
import (
"fmt"
"os"
"path/filepath"
"runtime"
"github.com/goccy/go-yaml"
. "github.com/anchore/go-make"
"github.com/anchore/go-make/file"
"github.com/anchore/go-make/git"
"github.com/anchore/go-make/lang"
"github.com/anchore/go-make/run"
"github.com/anchore/go-make/tasks/golint"
"github.com/anchore/go-make/tasks/goreleaser"
"github.com/anchore/go-make/tasks/gotest"
)
// taskfileDescriptions maps Taskfile.yaml task names to their `desc:` field.
// Loaded at package init so wrap() can use Taskfile.yaml as the single source
// of truth for wrapped-task descriptions.
var taskfileDescriptions = mustReadTaskfileDescriptions()
func main() {
Makefile(
// shared anchore tasks
golint.Tasks(),
goreleaser.Tasks(),
// unit tests: exclude packages under any test/ directory (matches the syft
// Taskfile's prior `grep -v` against test paths). Coverage threshold of 62%
// preserves the prior coverage gate that used to live in scripts/coverage.py.
gotest.Tasks(
gotest.Name("unit"),
gotest.ExcludeGlob("**/test/**"),
gotest.CoverageThreshold(62),
),
// integration tests: native go-make Task. The race-detector smoke against a
// real image stays bundled here (RunsOn integration) so `make integration`
// behaves like the Taskfile version did.
gotest.Tasks(
gotest.Name("integration"),
gotest.IncludeGlob("./cmd/syft/internal/test/integration/..."),
gotest.Verbose(),
gotest.NoCoverage(),
),
Task{
Name: "integration:race-smoke",
Description: "exercise the CLI with the race detector",
RunsOn: lang.List("integration"),
Run: func() {
Run("go run -race cmd/syft/main.go anchore/test_images:grype-quality-dotnet-69f15d2")
},
},
// cli tests: native go-make Task. Requires SYFT_BINARY_LOCATION pointing at
// an *absolute* path to the snapshot binary. Intentionally does NOT depend
// on snapshot: in CI we download a pre-built snapshot artifact and re-running
// goreleaser here would both burn ~10m and clobber the downloaded binary.
// Locally, the failure message tells you to run `make snapshot` first.
Task{
Name: "cli",
Description: "Run CLI tests",
RunsOn: lang.List("test"),
Run: func() {
bin := snapshotBinPath()
if !file.Exists(bin) {
panic(fmt.Sprintf("snapshot binary not found at %s; run `make snapshot` first", bin))
}
Log("testing binary: %s", bin)
Run(
"go test -count=1 -timeout=15m -v ./test/cli",
run.Env("SYFT_BINARY_LOCATION", bin),
)
},
},
// default validation pipeline (replaces Taskfile `default`/`pr-validations`/`validations`).
Task{
Name: "default",
Description: "Run all validation tasks",
Dependencies: Deps("static-analysis", "test", "install-test"),
},
// --- everything below is implemented in Taskfile.yaml and surfaced here
// via wrap(). Descriptions come from Taskfile.yaml (single source of truth).
// static analysis extras
wrap("check-json-schema-drift").RunOn("static-analysis"),
wrap("check-capability-drift"),
wrap("check-binary-fixture-size").RunOn("static-analysis"),
// test extras
wrap("validate-cyclonedx-schema").RunOn("test"),
wrap("test-utils").RunOn("test"),
wrap("check-docker-cache").RunOn("test"),
wrap("snapshot-smoke-test"),
// update commands
wrap("update-format-golden-files"),
// fixture cache plumbing (heavy ORAS logic, lives in Taskfile).
// refresh-fixtures hooks into "unit" so `make unit` triggers the
// stale-cache detection + download just like `task unit` did on main
// (its `deps: [tmpdir, fixtures]` is what kept the fixture cache fresh).
wrap("fingerprints"),
wrap("refresh-fixtures").RunOn("unit"),
wrap("fixtures"),
wrap("build-fixtures"),
wrap("download-test-fixture-cache"),
wrap("upload-test-fixture-cache"),
wrap("show-test-image-cache"),
// install-script tests (delegates to test/install/Makefile)
wrap("install-test"),
wrap("install-test-cache-save"),
wrap("install-test-cache-load"),
wrap("install-test-ci-mac"),
// compare tests
wrap("generate-compare-file"),
wrap("compare-mac"),
wrap("compare-linux"),
wrap("compare-test-deb-package-install"),
wrap("compare-test-rpm-package-install"),
// code/data generation (umbrella + per-target; each lives in Taskfile)
wrap("generate"),
wrap("generate-json-schema"),
wrap("generate-license-list"),
wrap("generate-cpe-dictionary-index"),
wrap("generate-capabilities"),
// cleanup (each hooks into go-make's built-in `clean` label)
wrap("clean-snapshot").RunOn("clean"),
wrap("clean-docker-cache").RunOn("clean"),
wrap("clean-oras-cache").RunOn("clean"),
wrap("clean-cache").RunOn("clean"),
wrap("clean-test-observations").RunOn("clean"),
)
}
// wrap creates a go-make Task that delegates execution to `task <name>`. The
// task's description is pulled from Taskfile.yaml's `desc:` field — descriptions
// for wrapped tasks must always live in Taskfile.yaml, never here.
func wrap(name string) Task {
desc, ok := taskfileDescriptions[name]
if !ok || desc == "" {
// loud-fail at startup so missing descs can't sneak through review.
panic(fmt.Sprintf("Taskfile.yaml task %q is missing a `desc:` field; please add one", name))
}
return Task{
Name: name,
Description: desc,
Run: func() { Run("task " + name) },
}
}
// mustReadTaskfileDescriptions parses Taskfile.yaml at the repo root and returns
// a map of task name -> desc. Runs at package init time so wrap() can use it.
func mustReadTaskfileDescriptions() map[string]string {
root := git.Root()
if root == "" {
return nil
}
path := filepath.Join(root, "Taskfile.yaml")
data, err := os.ReadFile(path) //nolint:gosec // G304: path resolved from git.Root()
if err != nil {
return nil
}
var tf struct {
Tasks map[string]struct {
Desc string `yaml:"desc"`
Aliases []string `yaml:"aliases"`
} `yaml:"tasks"`
}
lang.Throw(yaml.Unmarshal(data, &tf))
out := make(map[string]string, len(tf.Tasks))
for name, t := range tf.Tasks {
out[name] = t.Desc
// aliases inherit the canonical task's description so wrap() can find them.
for _, alias := range t.Aliases {
out[alias] = t.Desc
}
}
return out
}
// snapshotBinPath replicates the SNAPSHOT_BIN computation from the prior Taskfile:
// <repoRoot>/snapshot/<os>-build_<os>_<arch>/syft, where arch maps amd64->amd64_v1
// and arm64->arm64_v8.0 to match goreleaser's per-target output directory naming.
// Returns an absolute path: the cli tests' getSyftBinaryLocation contract requires
// SYFT_BINARY_LOCATION to be absolute because subtests run with cmd.Dir = t.TempDir().
func snapshotBinPath() string {
osName := runtime.GOOS
var arch string
switch runtime.GOARCH {
case "amd64":
arch = "amd64_v1"
case "arm64":
arch = "arm64_v8.0"
default:
arch = runtime.GOARCH
}
return filepath.Join(RootDir(), "snapshot", osName+"-build_"+osName+"_"+arch, "syft")
}
+41 -13
View File
@@ -1,18 +1,46 @@
# `test` and `snapshot` have matching directory names in this repo, so make would
# refuse to run them without an explicit .PHONY (Nothing to be done for ...).
.PHONY: test snapshot
test:
@go run -C .make . test
OWNER = anchore
PROJECT = syft
snapshot:
@go run -C .make . snapshot
TOOL_DIR = .tool
BINNY = $(TOOL_DIR)/binny
TASK = $(TOOL_DIR)/task
.PHONY: *
.DEFAULT_GOAL: make-default
.DEFAULT_GOAL := make-default
make-default:
@go run -C .make .
## Bootstrapping targets #################################
.DEFAULT:
# note: we need to assume that binny and task have not already been installed
$(BINNY):
@mkdir -p $(TOOL_DIR)
@curl -sSfL https://get.anchore.io/binny | sh -s -- -b $(TOOL_DIR)
# note: we need to assume that binny and task have not already been installed
.PHONY: task
$(TASK) task: $(BINNY)
@$(BINNY) install task -q
.PHONY: ci-bootstrap-go
ci-bootstrap-go:
go mod download
# this is a bootstrapping catch-all, where if the target doesn't exist, we'll ensure the tools are installed and then try again
%:
@go run -C .make . $@
@make --silent $(TASK)
@$(TASK) $@
## Shim targets #################################
.PHONY: make-default
make-default: $(TASK)
@# run the default task in the taskfile
@$(TASK)
# for those of us that can't seem to kick the habit of typing `make ...` lets wrap the superior `task` tool
TASKS := $(shell bash -c "test -f $(TASK) && NO_COLOR=1 $(TASK) -l | grep '^\* ' | cut -d' ' -f2 | tr -d ':' | tr '\n' ' '" ) $(shell bash -c "test -f $(TASK) && NO_COLOR=1 $(TASK) -l | grep 'aliases:' | cut -d ':' -f 3 | tr '\n' ' ' | tr -d ','")
.PHONY: $(TASKS)
$(TASKS): $(TASK)
@$(TASK) $@
help: $(TASK)
@$(TASK) -l
+262 -47
View File
@@ -1,10 +1,5 @@
version: "3"
# NOTE: most generic tasks (static-analysis, format, lint, unit, snapshot, release,
# changelog, ci-release, etc.) are now provided natively by anchore/go-make and
# defined in .make/main.go. This file holds the syft-specific tasks that go-make
# wraps via `wrap("<name>")` calls — keep descriptions (`desc:`) populated so they
# show up in `make help`.
version: "3"
includes:
generate:cpe-index: ./task.d/generate/cpe-index.yaml
@@ -30,7 +25,11 @@ vars:
YQ: "{{ .TOOL_DIR }}/yq"
TASK: "{{ .TOOL_DIR }}/task"
# used for snapshot bin discovery in compare/install tasks
# used for changelog generation
CHANGELOG: CHANGELOG.md
NEXT_VERSION: VERSION
# used for snapshot builds
OS:
sh: uname -s | tr '[:upper:]' '[:lower:]'
ARCH:
@@ -43,6 +42,11 @@ vars:
# e.g. when installing snapshot debs from a local path, ./ forces the deb to be installed in the current working directory instead of referencing a package name
SNAPSHOT_DIR: ./snapshot
SNAPSHOT_BIN: "{{ .PROJECT_ROOT }}/{{ .SNAPSHOT_DIR }}/{{ .OS }}-build_{{ .OS }}_{{ .ARCH }}/{{ .PROJECT }}"
SNAPSHOT_CMD: "{{ .TOOL_DIR }}/goreleaser release --config {{ .TMP_DIR }}/goreleaser.yaml --clean --snapshot --skip=publish --skip=sign"
BUILD_CMD: "{{ .TOOL_DIR }}/goreleaser build --config {{ .TMP_DIR }}/goreleaser.yaml --clean --snapshot --single-target"
RELEASE_CMD: "{{ .TOOL_DIR }}/goreleaser release --clean --release-notes {{ .CHANGELOG }}"
VERSION:
sh: git describe --dirty --always --tags
# used for install and acceptance testing
COMPARE_DIR: ./test/compare
@@ -53,10 +57,43 @@ env:
tasks:
## Bootstrap (internal helpers used by other Taskfile tasks) ###############
## High-level tasks #################################
default:
desc: Run all validation tasks
aliases:
- pr-validations
- validations
cmds:
- task: static-analysis
- task: test
- task: install-test
static-analysis:
desc: Run all static analysis tasks
cmds:
- task: check-go-mod-tidy
- task: check-licenses
- task: lint
- task: check-json-schema-drift
- task: check-binary-fixture-size
test:
desc: Run all levels of test
cmds:
- task: unit
- task: integration
- task: validate-cyclonedx-schema
- task: test-utils
- task: snapshot
- task: cli
- task: check-docker-cache
## Bootstrap tasks #################################
binny:
internal: true
# desc: Get the binny tool
generates:
- "{{ .TOOL_DIR }}/binny"
status:
@@ -65,8 +102,10 @@ tasks:
silent: true
tools:
internal: true
desc: Install all tools needed for CI and local development
deps: [binny]
aliases:
- bootstrap
generates:
- ".binny.yaml"
- "{{ .TOOL_DIR }}/*"
@@ -75,14 +114,79 @@ tasks:
cmd: "{{ .TOOL_DIR }}/binny install -v"
silent: true
update-tools:
desc: Update pinned versions of all tools to their latest available versions
deps: [binny]
generates:
- ".binny.yaml"
- "{{ .TOOL_DIR }}/*"
cmd: "{{ .TOOL_DIR }}/binny update -v"
silent: true
list-tools:
desc: List all tools needed for CI and local development
deps: [binny]
cmd: "{{ .TOOL_DIR }}/binny list"
silent: true
list-tool-updates:
desc: List all tools that are not up to date relative to the binny config
deps: [binny]
cmd: "{{ .TOOL_DIR }}/binny list --updates"
silent: true
tmpdir:
internal: true
silent: true
generates:
- "{{ .TMP_DIR }}"
cmd: "mkdir -p {{ .TMP_DIR }}"
## Static analysis extras #################################################
## Static analysis tasks #################################
format:
desc: Auto-format all source code
deps: [tools]
cmds:
- gofmt -w -s .
- "{{ .TOOL_DIR }}/gosimports -local github.com/anchore -w ."
- go mod tidy
lint-fix:
desc: Auto-format all source code + run golangci lint fixers
deps: [tools]
cmds:
- task: format
- "{{ .TOOL_DIR }}/golangci-lint run --tests=false --fix"
lint:
desc: Run gofmt + golangci lint checks
vars:
BAD_FMT_FILES:
sh: gofmt -l -s .
BAD_FILE_NAMES:
sh: "find . | grep -e ':' || true"
deps: [tools]
cmds:
# ensure there are no go fmt differences
- cmd: 'test -z "{{ .BAD_FMT_FILES }}" || (echo "files with gofmt issues: [{{ .BAD_FMT_FILES }}]"; exit 1)'
silent: true
# ensure there are no files with ":" in it (a known back case in the go ecosystem)
- cmd: 'test -z "{{ .BAD_FILE_NAMES }}" || (echo "files with bad names: [{{ .BAD_FILE_NAMES }}]"; exit 1)'
silent: true
# run linting
- "{{ .TOOL_DIR }}/golangci-lint run --tests=false"
check-licenses:
# desc: Ensure transitive dependencies are compliant with the current license policy
deps: [tools]
cmd: "{{ .TOOL_DIR }}/bouncer check ./..."
check-go-mod-tidy:
# desc: Ensure go.mod and go.sum are up to date
cmds:
- cmd: .github/scripts/go-mod-tidy-check.sh && echo "go.mod and go.sum are tidy!"
silent: true
check-json-schema-drift:
desc: Ensure there is no drift between the JSON schema and the code
@@ -99,8 +203,8 @@ tasks:
cmds:
- .github/scripts/check_binary_fixture_size.sh syft/pkg/cataloger/binary/testdata/classifiers/snippets
## Test extras ############################################################
## Testing tasks #################################
update-format-golden-files:
desc: "Update golden (i.e. snapshot) files used by unit tests"
cmds:
@@ -110,32 +214,59 @@ tasks:
- go test ./syft/format/cyclonedxjson -update-cyclonedx-json
- go test ./syft/format/syftjson -update-json
unit:
desc: Run unit tests
deps:
- tmpdir
- fixtures
vars:
TEST_PKGS:
sh: "go list ./... | grep -v {{ .OWNER }}/{{ .PROJECT }}/test | grep -v {{ .OWNER }}/{{ .PROJECT }}/cmd/syft/internal/test | tr '\n' ' '"
# unit test coverage threshold (in % coverage)
COVERAGE_THRESHOLD: 62
cmds:
- task: clean-test-observations
- "go test -coverprofile {{ .TMP_DIR }}/unit-coverage-details.txt {{ .TEST_PKGS }}"
- cmd: ".github/scripts/coverage.py {{ .COVERAGE_THRESHOLD }} {{ .TMP_DIR }}/unit-coverage-details.txt"
silent: true
integration:
desc: Run integration tests
cmds:
- "go test -v ./cmd/syft/internal/test/integration"
# exercise most of the CLI with the data race detector
# we use a larger image to ensure we're using multiple catalogers at a time
- "go run -race cmd/syft/main.go anchore/test_images:grype-quality-dotnet-69f15d2"
validate-cyclonedx-schema:
desc: Validate that Syft produces valid CycloneDX documents
cmds:
- "cd schema/cyclonedx && make"
cli:
desc: Run CLI tests
deps: [tools]
cmds:
- cmd: "echo 'testing binary: {{ .SNAPSHOT_BIN }}'"
silent: true
- cmd: "test -f {{ .SNAPSHOT_BIN }} || (find {{ .SNAPSHOT_DIR }} && echo '\nno snapshot found for {{ .SNAPSHOT_BIN }}' && false)"
silent: true
- "go test -count=1 -timeout=15m -v ./test/cli"
env:
SYFT_BINARY_LOCATION: "{{ .SNAPSHOT_BIN }}"
test-utils:
desc: Run tests for pipeline utils
cmds:
- cmd: .github/scripts/labeler_test.py
snapshot-smoke-test:
desc: Run a smoke test on the snapshot builds + docker images
cmds:
- cmd: "echo 'testing snapshot binary: {{ .SNAPSHOT_BIN }}'"
silent: true
- cmd: "test -f {{ .SNAPSHOT_BIN }} || (find {{ .SNAPSHOT_DIR }} && echo '\nno snapshot found for {{ .SNAPSHOT_BIN }}' && false)"
silent: true
- "{{ .SNAPSHOT_BIN }} version"
- "{{ .SNAPSHOT_BIN }} scan alpine:latest"
- docker run --rm anchore/syft:latest version
- docker run --rm anchore/syft:latest scan alpine:latest
## Test-fixture-related targets ###########################################
## Test-fixture-related targets #################################
fingerprints:
desc: Generate fingerprints for all non-docker test fixtures
desc: Generate fingerprints for all non-docker test fixture
silent: true
# this will look for `testdata/Makefile` and invoke the `fingerprint` target to calculate all cache input fingerprint files
generates:
@@ -150,10 +281,16 @@ tasks:
echo -e "${YELLOW}creating fingerprint files for non-docker fixtures...${RESET}"
for dir in $(find . -type d -name 'testdata'); do
if [ -f "$dir/Makefile" ]; then
# for debugging...
#echo -e "${YELLOW}• calculating fingerprints in $dir... ${RESET}"
(make -C "$dir" fingerprint)
fi
done
# for debugging...
# echo -e "generated all fixture fingerprints"
- .github/scripts/fingerprint_docker_fixtures.py
- |
# if DOWNLOAD_TEST_FIXTURE_CACHE is set to 'false', then we don't need to calculate the fingerprint for the cache
@@ -295,7 +432,6 @@ tasks:
eval $oras_command
show-test-image-cache:
desc: Print the on-disk + docker daemon state of the stereoscope fixture image cache
silent: true
cmds:
- "echo 'Docker daemon cache:'"
@@ -316,36 +452,28 @@ tasks:
exit 1
fi
## install.sh testing targets #############################################
## install.sh testing targets #################################
install-test:
desc: Run install.sh test suite (delegates to test/install/Makefile)
cmds:
- "cd test/install && make"
install-test-cache-save:
desc: Save the install.sh test image cache (delegates to test/install/Makefile)
cmds:
- "cd test/install && make save"
install-test-cache-load:
desc: Load the install.sh test image cache (delegates to test/install/Makefile)
cmds:
- "cd test/install && make load"
install-test-ci-mac:
desc: Run install.sh CI test suite on macOS (delegates to test/install/Makefile)
cmds:
- "cd test/install && make ci-test-mac"
## Compare-test targets ###################################################
generate-compare-file:
desc: Generate the acceptance comparison reference JSON for the current compare image
cmd: "go run ./cmd/syft {{ .COMPARE_TEST_IMAGE }} -o json > {{ .COMPARE_DIR }}/testdata/acceptance-{{ .COMPARE_TEST_IMAGE }}.json"
compare-mac:
desc: Run macOS install + acceptance comparison against the snapshot build
deps: [tmpdir]
cmd: |
{{ .COMPARE_DIR }}/mac.sh \
@@ -355,13 +483,11 @@ tasks:
{{ .TMP_DIR }}
compare-linux:
desc: Run Linux install + acceptance comparison (deb + rpm) against the snapshot build
cmds:
- task: compare-test-deb-package-install
- task: compare-test-rpm-package-install
compare-test-deb-package-install:
desc: Run Linux .deb install + acceptance comparison against the snapshot build
deps: [tmpdir]
cmd: |
{{ .COMPARE_DIR }}/deb.sh \
@@ -371,7 +497,6 @@ tasks:
{{ .TMP_DIR }}
compare-test-rpm-package-install:
desc: Run Linux .rpm install + acceptance comparison against the snapshot build
deps: [tmpdir]
cmd: |
{{ .COMPARE_DIR }}/rpm.sh \
@@ -381,7 +506,7 @@ tasks:
{{ .TMP_DIR }}
## Code and data generation targets ######################################
## Code and data generation targets #################################
generate:
desc: Add data generation tasks
@@ -431,7 +556,104 @@ tasks:
- "SYFT_ENABLE_COMPLETENESS_TESTS=true go test -p 1 ./internal/capabilities/... -count=1"
## Cleanup targets ########################################################
## Build-related targets #################################
build:
desc: Build the project
deps: [tools, tmpdir]
generates:
- "{{ .PROJECT }}"
cmds:
- silent: true
cmd: |
echo "dist: {{ .SNAPSHOT_DIR }}" > {{ .TMP_DIR }}/goreleaser.yaml
cat .goreleaser.yaml >> {{ .TMP_DIR }}/goreleaser.yaml
- "{{ .BUILD_CMD }}"
snapshot:
desc: Create a snapshot release
aliases:
- build
deps: [tools, tmpdir]
sources:
- cmd/**/*.go
- syft/**/*.go
- internal/**/*.go
method: checksum
generates:
- "{{ .SNAPSHOT_BIN }}"
cmds:
- silent: true
cmd: |
echo "dist: {{ .SNAPSHOT_DIR }}" > {{ .TMP_DIR }}/goreleaser.yaml
cat .goreleaser.yaml >> {{ .TMP_DIR }}/goreleaser.yaml
- "{{ .SNAPSHOT_CMD }}"
snapshot-smoke-test:
desc: Run a smoke test on the snapshot builds + docker images
cmds:
- cmd: "echo 'testing snapshot binary: {{ .SNAPSHOT_BIN }}'"
silent: true
- cmd: "test -f {{ .SNAPSHOT_BIN }} || (find {{ .SNAPSHOT_DIR }} && echo '\nno snapshot found for {{ .SNAPSHOT_BIN }}' && false)"
silent: true
- "{{ .SNAPSHOT_BIN }} version"
- "{{ .SNAPSHOT_BIN }} scan alpine:latest"
- docker run --rm anchore/syft:latest version
- docker run --rm anchore/syft:latest scan alpine:latest
changelog:
desc: Generate a changelog
deps: [tools]
generates:
- "{{ .CHANGELOG }}"
- "{{ .NEXT_VERSION }}"
cmds:
- "{{ .TOOL_DIR }}/chronicle -vv -n --version-file {{ .NEXT_VERSION }} > {{ .CHANGELOG }}"
- "{{ .TOOL_DIR }}/glow -w 0 {{ .CHANGELOG }}"
## Release targets #################################
release:
desc: Create a release
interactive: true
deps: [tools]
cmds:
- cmd: .github/scripts/trigger-release.sh
silent: true
## CI-only targets #################################
ci-check:
# desc: "[CI only] Are you in CI?"
cmds:
- cmd: .github/scripts/ci-check.sh
silent: true
ci-release:
# desc: "[CI only] Create a release"
deps: [tools]
cmds:
- task: ci-check
- "{{ .TOOL_DIR }}/chronicle -vvv > CHANGELOG.md"
- cmd: "cat CHANGELOG.md"
silent: true
- "{{ .RELEASE_CMD }}"
## Cleanup targets #################################
clean:
desc: Remove all cache files and old builds
cmds:
- task: clean-snapshot
- task: clean-cache
- task: clean-test-observations
- task: clean-docker-cache
- task: clean-oras-cache
clean-snapshot:
desc: Remove any snapshot builds
@@ -453,7 +675,6 @@ tasks:
desc: Remove all image docker tar cache, images from the docker daemon, and ephemeral test fixtures
cmds:
- task: clean-docker-cache
- task: prune-orphan-fingerprints
- |
BOLD='\033[1m'
YELLOW='\033[0;33m'
@@ -469,12 +690,6 @@ tasks:
echo -e "${BOLD}Deleted all ephemeral test fixtures${RESET}"
- rm -f {{ .LAST_CACHE_PULL_FILE }} {{ .CACHE_PATHS_FILE }}
prune-orphan-fingerprints:
desc: Remove *.fingerprint files left behind by moved/deleted catalogers
silent: true
cmds:
- .github/scripts/prune_orphan_fingerprints.py
clean-test-observations:
desc: Remove all test observations (i.e. testdata/test-observations.json)
cmds:
+23 -21
View File
@@ -1,6 +1,6 @@
module github.com/anchore/syft
go 1.26.3
go 1.25.8
require (
github.com/BurntSushi/toml v1.6.0
@@ -22,7 +22,7 @@ require (
github.com/anchore/go-sync v0.1.0
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b
github.com/anchore/packageurl-go v0.2.0
github.com/anchore/stereoscope v0.2.0
github.com/anchore/stereoscope v0.1.23
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
github.com/aquasecurity/go-pep440-version v0.0.1
github.com/bitnami/go-version v0.0.0-20250131085805-b1f57a8634ef
@@ -42,7 +42,7 @@ require (
github.com/github/go-spdx/v2 v2.4.0
github.com/gkampitakis/go-snaps v0.5.21
github.com/go-git/go-billy/v5 v5.9.0
github.com/go-git/go-git/v5 v5.19.1
github.com/go-git/go-git/v5 v5.19.0
github.com/go-test/deep v1.1.1
github.com/go-viper/mapstructure/v2 v2.5.0
github.com/goccy/go-yaml v1.19.2
@@ -111,14 +111,15 @@ require (
cloud.google.com/go/iam v1.5.3 // indirect
cloud.google.com/go/monitoring v1.24.3 // indirect
cloud.google.com/go/storage v1.61.3 // indirect
cyphar.com/go-pathrs v0.2.1 // indirect
dario.cat/mergo v1.0.2 // indirect
github.com/DataDog/zstd v1.5.5 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29 // indirect
github.com/Microsoft/hcsshim v0.15.0-rc.1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/Microsoft/hcsshim v0.14.0-rc.1 // indirect
github.com/ProtonMail/go-crypto v1.4.0 // indirect
github.com/STARRY-S/zip v0.2.3 // indirect
github.com/agext/levenshtein v1.2.1 // indirect
@@ -164,22 +165,22 @@ require (
github.com/clipperhouse/uax29/v2 v2.6.0 // indirect
github.com/cloudflare/circl v1.6.3 // indirect
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect
github.com/containerd/cgroups/v3 v3.1.3 // indirect
github.com/containerd/containerd/api v1.11.1 // indirect
github.com/containerd/containerd/v2 v2.3.1 // indirect
github.com/containerd/continuity v0.5.0 // indirect
github.com/containerd/cgroups/v3 v3.1.2 // indirect
github.com/containerd/containerd/api v1.10.0 // indirect
github.com/containerd/containerd/v2 v2.2.2 // indirect
github.com/containerd/continuity v0.4.5 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/fifo v1.1.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v1.0.0-rc.4 // indirect
github.com/containerd/plugin v1.1.0 // indirect
github.com/containerd/plugin v1.0.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.18.2 // indirect
github.com/containerd/ttrpc v1.2.8 // indirect
github.com/containerd/ttrpc v1.2.7 // indirect
github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/docker/cli v29.4.3+incompatible // indirect
github.com/docker/cli v29.4.0+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.5 // indirect
github.com/docker/go-connections v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
@@ -253,8 +254,9 @@ require (
github.com/olekukonko/ll v0.1.6 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/opencontainers/runtime-spec v1.3.0 // indirect
github.com/opencontainers/selinux v1.13.1 // indirect
github.com/pborman/indent v1.2.1 // indirect
github.com/pelletier/go-toml/v2 v2.3.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pierrec/lz4/v4 v4.1.22 // indirect
github.com/pjbgf/sha1cd v0.6.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
@@ -296,8 +298,8 @@ require (
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/otel v1.43.0 // indirect
go.opentelemetry.io/otel/metric v1.43.0 // indirect
go.opentelemetry.io/otel/sdk v1.43.0 // indirect
@@ -311,13 +313,13 @@ require (
golang.org/x/term v0.42.0 // indirect
golang.org/x/text v0.36.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
gonum.org/v1/gonum v0.17.0 // indirect
gonum.org/v1/gonum v0.16.0 // indirect
google.golang.org/api v0.271.0 // indirect
google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d // indirect
google.golang.org/grpc v1.80.0 // indirect
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect
google.golang.org/grpc v1.79.3 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
modernc.org/libc v1.70.0 // indirect
modernc.org/mathutil v1.7.1 // indirect
+46 -44
View File
@@ -67,6 +67,8 @@ cloud.google.com/go/storage v1.61.3 h1:VS//ZfBuPGDvakfD9xyPW1RGF1Vy3BWUoVZXgW1KM
cloud.google.com/go/storage v1.61.3/go.mod h1:JtqK8BBB7TWv0HVGHubtUdzYYrakOQIsMLffZ2Z/HWk=
cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U=
cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s=
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=
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
@@ -82,8 +84,8 @@ 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/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ=
github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 h1:DHa2U07rk8syqvCge0QIGMCE1WxGj9njT44GH7zNJLQ=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 h1:sBEjpZlNHzK1voKq9695PJSX2o5NEXl7/OL3coiIY0c=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0=
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.55.0/go.mod h1:IA1C1U7jO/ENqm/vhi7V9YYpBsp+IMyqNrEN94N7tVc=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.55.0 h1:7t/qx5Ost0s0wbA/VDrByOooURhp+ikYwv20i9Y07TQ=
@@ -97,10 +99,10 @@ github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lpr
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29 h1:0kQAzHq8vLs7Pptv+7TxjdETLf/nIqJpIB4oC6Ba4vY=
github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29/go.mod h1:ZWa7ssZJT30CCDGJ7fk/2SBTq9BIQrrVjrcss0UW2s0=
github.com/Microsoft/hcsshim v0.15.0-rc.1 h1:FbbwtQmiD+BVHynGkx5S65JkLyhkEiiTP8nrpmg2SZw=
github.com/Microsoft/hcsshim v0.15.0-rc.1/go.mod h1:HWvvUPIy9HF6LotILj1G4VyS065rcLQ6tqj6tMUdOfI=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.14.0-rc.1 h1:qAPXKwGOkVn8LlqgBN8GS0bxZ83hOJpcjxzmlQKxKsQ=
github.com/Microsoft/hcsshim v0.14.0-rc.1/go.mod h1:hTKFGbnDtQb1wHiOWv4v0eN+7boSWAHyK/tNAaYZL0c=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
@@ -146,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/packageurl-go v0.2.0 h1:CkrM4RMUwrEGAiE1OVlxaZNzWj0TuHRey7o4T/EAErk=
github.com/anchore/packageurl-go v0.2.0/go.mod h1:2JCgOQMIsqZ7TmliXG4PnUthPJAKE3mWQbsW2XHjAOE=
github.com/anchore/stereoscope v0.2.0 h1:8haOu2ugLymmxvyfrZR7OTBFiRFRBh5LlNUtRrSRoxI=
github.com/anchore/stereoscope v0.2.0/go.mod h1:PYx3fD4lvBVsYoQ/fBdauhZ5hmkRrJgw1B73svKx7/U=
github.com/anchore/stereoscope v0.1.23 h1:q9i3CtbicTuSlcCnA+5pfoT9WDCEoSqvXDfHMH1hyWo=
github.com/anchore/stereoscope v0.1.23/go.mod h1:JLnun49fkLkuv3ebU0ROvFl/0JiRmNmUtCzc6y4ollo=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
@@ -292,14 +294,14 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
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-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI=
github.com/containerd/cgroups/v3 v3.1.3 h1:eUNflyMddm18+yrDmZPn3jI7C5hJ9ahABE5q6dyLYXQ=
github.com/containerd/cgroups/v3 v3.1.3/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw=
github.com/containerd/containerd/api v1.11.1 h1:h8nfoDW9+fNsC/9TwiAHj8B1GzXKtR4eFtkhi/X5RLU=
github.com/containerd/containerd/api v1.11.1/go.mod h1:CaQFRu+N1MtbgL6JDOJLUB1hCKESU1lD6MuTJhgtdlw=
github.com/containerd/containerd/v2 v2.3.1 h1:4dVXBdlvotRBlaP2TmNbY/EGc06KJrMDDUqQdxX/HOk=
github.com/containerd/containerd/v2 v2.3.1/go.mod h1:xVoxGPWZBwwph8DF2IbDhriLKdHfjdpO0b3wFP9wQ1I=
github.com/containerd/continuity v0.5.0 h1:7a85HZpCSs+1Zps0Ee3DPSuAWY+0SJM1JNM51nlEVDg=
github.com/containerd/continuity v0.5.0/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
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/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o=
github.com/containerd/containerd/api v1.10.0/go.mod h1:NBm1OAk8ZL+LG8R0ceObGxT5hbUYj7CzTmR3xh0DlMM=
github.com/containerd/containerd/v2 v2.2.2 h1:mjVQdtfryzT7lOqs5EYUFZm8ioPVjOpkSoG1GJPxEMY=
github.com/containerd/containerd/v2 v2.2.2/go.mod h1:5Jhevmv6/2J+Iu/A2xXAdUIdI5Ah/hfyO7okJ4AFIdY=
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
@@ -310,12 +312,12 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/platforms v1.0.0-rc.4 h1:M42JrUT4zfZTqtkUwkr0GzmUWbfyO5VO0Q5b3op97T4=
github.com/containerd/platforms v1.0.0-rc.4/go.mod h1:lKlMXyLybmBedS/JJm11uDofzI8L2v0J2ZbYvNsbq1A=
github.com/containerd/plugin v1.1.0 h1:O+7lczNJVMy8rz0YNx3xGB8tTf5qY4i5abF041Ew19U=
github.com/containerd/plugin v1.1.0/go.mod h1:qBTum+A8lJ6lO44A19Eo7y1OlcLj4OWFH1DA/vnHmcc=
github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y=
github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8=
github.com/containerd/stargz-snapshotter/estargz v0.18.2 h1:yXkZFYIzz3eoLwlTUZKz2iQ4MrckBxJjkmD16ynUTrw=
github.com/containerd/stargz-snapshotter/estargz v0.18.2/go.mod h1:XyVU5tcJ3PRpkA9XS2T5us6Eg35yM0214Y+wvrZTBrY=
github.com/containerd/ttrpc v1.2.8 h1:xbVu6D4qF2jihdh9rDVOKqUMiFBQk6YctTdo1zk087Y=
github.com/containerd/ttrpc v1.2.8/go.mod h1:wyZW2K79t4Hfcxl+GUvkZqRBzJlqFFvgEeeWXa42tyE=
github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ=
github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -341,8 +343,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c=
github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0=
github.com/docker/cli v29.4.3+incompatible h1:u+UliYm2J/rYrIh2FqHQg32neRG8GjbvNuwQRTzGspU=
github.com/docker/cli v29.4.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v29.4.0+incompatible h1:+IjXULMetlvWJiuSI0Nbor36lcJ5BTcVpUmB21KBoVM=
github.com/docker/cli v29.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY=
github.com/docker/docker-credential-helpers v0.9.5/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c=
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
@@ -383,8 +385,6 @@ github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg
github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA=
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/erofs/go-erofs v0.3.0 h1:o/W5ABAA3sHYl97WL93dacKEfeDpJhdFf3c2snAti7I=
github.com/erofs/go-erofs v0.3.0/go.mod h1:XkSeN9MHszGd4+3gcEjadJLYHCQpWzJ7/8yznzMuzJs=
github.com/facebookincubator/flog v0.0.0-20190930132826-d2511d0ce33c/go.mod h1:QGzNH9ujQ2ZUr/CjDGZGWeDAVStrWNjHeEcjJL96Nuk=
github.com/facebookincubator/nvdtools v0.1.5 h1:jbmDT1nd6+k+rlvKhnkgMokrCAzHoASWE5LtHbX2qFQ=
github.com/facebookincubator/nvdtools v0.1.5/go.mod h1:Kh55SAWnjckS96TBSrXI99KrEKH4iB0OJby3N8GRJO4=
@@ -424,8 +424,8 @@ github.com/go-git/go-billy/v5 v5.9.0 h1:jItGXszUDRtR/AlferWPTMN4j38BQ88XnXKbilmm
github.com/go-git/go-billy/v5 v5.9.0/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.19.1 h1:nX27AnaU43/K5bKktKwgBmR9lawoYVe1Ckg0rgzzN00=
github.com/go-git/go-git/v5 v5.19.1/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ=
github.com/go-git/go-git/v5 v5.19.0 h1:+WkVUQZSy/F1Gb13udrMKjIM2PrzsNfDKFSfo5tkMtc=
github.com/go-git/go-git/v5 v5.19.0/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -778,6 +778,8 @@ github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJw
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg=
github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.13.1 h1:A8nNeceYngH9Ow++M+VVEwJVpdFmrlxsN22F+ISDCJE=
github.com/opencontainers/selinux v1.13.1/go.mod h1:S10WXZ/osk2kWOYKy1x2f/eXF5ZHJoUs8UU/2caNRbg=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
@@ -786,8 +788,8 @@ github.com/pborman/indent v1.2.1/go.mod h1:FitS+t35kIYtB5xWTZAPhnmrxcciEEOdbyrrp
github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.3.1 h1:MYEvvGnQjeNkRF1qUuGolNtNExTDwct51yp7olPtrEc=
github.com/pelletier/go-toml/v2 v2.3.1/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU=
github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pjbgf/sha1cd v0.6.0 h1:3WJ8Wz8gvDz29quX1OcEmkAlUg9diU4GxJHqs0/XiwU=
@@ -822,8 +824,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/quasilyte/go-ruleguard/dsl v0.3.23 h1:lxjt5B6ZCiBeeNO8/oQsegE6fLeCzuMRoVWSkXC4uvY=
github.com/quasilyte/go-ruleguard/dsl v0.3.23/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
@@ -998,10 +1000,10 @@ go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ
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.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo=
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/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/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.40.0 h1:ZrPRak/kS4xI3AVXy8F7pipuDXmDsrO8Lg+yQjBLjw0=
@@ -1319,8 +1321,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -1427,10 +1429,10 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6
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-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM=
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA=
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20 h1:7ei4lp52gK1uSejlA8AZl5AJjeLUOHBQscRQZUgAcu0=
google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20/go.mod h1:ZdbssH/1SOVnjnDlXzxDHK2MCidiqXtbYccJNzNYPEE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -1458,8 +1460,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.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.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM=
google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4=
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
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-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@@ -1474,8 +1476,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI=
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+1 -5
View File
@@ -490,15 +490,11 @@ func (e *EnrichmentData) EnrichWithBinaryClassifier(catalogerName string, entry
}
for _, o := range binaryClassifierOverrides[classifier.Class] {
cpeStrings := make([]string, len(o.CPEs))
for i, c := range o.CPEs {
cpeStrings[i] = c.Attributes.BindToFmtString()
}
packages = append(packages, capabilities.DetectorPackageInfo{
Class: o.Class,
Name: o.Package,
PURL: stripPURLVersion(o.PURL),
CPEs: cpeStrings,
CPEs: o.CPEs,
Type: "BinaryPkg",
})
}
+3 -38
View File
@@ -10,7 +10,7 @@ type binaryClassifierOverride struct {
Class string
Package string
PURL string
CPEs []cpe.CPE
CPEs []string
}
var binaryClassifierOverrides = map[string][]binaryClassifierOverride{
@@ -110,47 +110,12 @@ var binaryClassifierOverrides = map[string][]binaryClassifierOverride{
CPEs: singleCPE("cpe:2.3:a:openssl:openssl:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
},
"mysqld-binary": {
{
Class: "mysqld-mysql-cluster-legacy-binary",
Package: "mysql-cluster",
PURL: mustPURL("pkg:generic/mysql-cluster@version"),
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:a:oracle:mysql_cluster:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
},
{
Class: "mysqld-mysql-cluster-binary",
Package: "mysql-cluster",
PURL: mustPURL("pkg:generic/mysql-cluster@version"),
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
cpe.Must("cpe:2.3:a:oracle:mysql_server:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
cpe.Must("cpe:2.3:a:oracle:mysql_cluster:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
},
{
Class: "mysqld-mysql-server-binary",
Package: "mysql-server",
PURL: mustPURL("pkg:generic/mysql-server@version"),
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
cpe.Must("cpe:2.3:a:oracle:mysql_server:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
},
},
}
func mustPURL(purl string) string {
return purl
}
func singleCPE(cpeString string, source ...cpe.Source) []cpe.CPE {
src := cpe.GeneratedSource
if len(source) > 0 {
src = source[0]
}
return []cpe.CPE{
cpe.Must(cpeString, src),
}
func singleCPE(cpeString string, _ ...any) []string {
return []string{cpeString}
}
+5 -9
View File
@@ -15,18 +15,14 @@ fixtures: build verify
# requirement 2: 'fingerprint' goal to determine if the fixture input that indicates any existing cache should be busted
fingerprint: $(FINGERPRINT_FILE)
tools-check:
@sha256sum -c Dockerfile.sha256 || (echo "Tools Dockerfile has changed" && exit 1)
# for selfrando...
# docker buildx build --platform linux/amd64 -t $(TOOL_IMAGE) .
tools:
@if docker image inspect $(TOOL_IMAGE) > /dev/null 2>&1 \
&& test -f Dockerfile.sha256 \
&& sha256sum --quiet -c Dockerfile.sha256 2>/dev/null; then \
: ; \
else \
docker build -t $(TOOL_IMAGE) . \
&& sha256sum Dockerfile > Dockerfile.sha256; \
fi
@(docker image inspect $(TOOL_IMAGE) > /dev/null 2>&1 && make tools-check) || (docker build -t $(TOOL_IMAGE) . && sha256sum Dockerfile > Dockerfile.sha256)
build: tools
mkdir -p $(BIN)
@@ -50,4 +46,4 @@ $(FINGERPRINT_FILE):
clean:
rm -rf $(BIN) Dockerfile.sha256 $(VERIFY_FILE) $(FINGERPRINT_FILE)
.PHONY: tools build verify debug clean
.PHONY: tools tools-check build verify debug clean
@@ -15,15 +15,11 @@ fixtures: build
# requirement 2: 'fingerprint' goal to determine if the fixture input that indicates any existing cache should be busted
fingerprint: $(FINGERPRINT_FILE)
tools-check:
@sha256sum -c Dockerfile.sha256 || (echo "Tools Dockerfile has changed" && exit 1)
tools:
@if docker image inspect $(TOOL_IMAGE) > /dev/null 2>&1 \
&& test -f Dockerfile.sha256 \
&& sha256sum --quiet -c Dockerfile.sha256 2>/dev/null; then \
: ; \
else \
docker build --platform linux/amd64 -t $(TOOL_IMAGE) . \
&& sha256sum Dockerfile > Dockerfile.sha256; \
fi
@(docker image inspect $(TOOL_IMAGE) > /dev/null 2>&1 && make tools-check) || (docker build --platform linux/amd64 -t $(TOOL_IMAGE) . && sha256sum Dockerfile > Dockerfile.sha256)
build: tools
@mkdir -p $(BIN)
@@ -42,4 +38,4 @@ $(FINGERPRINT_FILE):
clean:
rm -rf $(BIN) Dockerfile.sha256 $(VERIFY_FILE) $(FINGERPRINT_FILE)
.PHONY: tools build debug clean
.PHONY: tools tools-check build debug clean
@@ -66,16 +66,6 @@ catalogers:
cpes:
- cpe:2.3:a:julialang:julia:*:*:*:*:*:*:*:*
type: BinaryPkg
- method: glob
criteria:
- '**/julia'
packages:
- class: julia-binary
name: julia
purl: pkg:generic/julia
cpes:
- cpe:2.3:a:julialang:julia:*:*:*:*:*:*:*:*
type: BinaryPkg
- method: glob
criteria:
- '**/helm'
@@ -252,77 +242,6 @@ catalogers:
- cpe:2.3:a:percona:percona_server:*:*:*:*:*:*:*:*
- cpe:2.3:a:percona:xtradb_cluster:*:*:*:*:*:*:*:*
type: BinaryPkg
- method: glob
criteria:
- '**/mysqld'
packages:
- class: mysqld-mysql-cluster-legacy-binary
name: mysql-server
purl: pkg:generic/mysql-server
cpes:
- cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*
- cpe:2.3:a:oracle:mysql_server:*:*:*:*:*:*:*:*
type: BinaryPkg
- method: glob
criteria:
- '**/mysqld'
packages:
- class: mysqld-binary
name: ""
purl: pkg:/
cpes: []
type: BinaryPkg
- class: mysqld-mysql-cluster-legacy-binary
name: mysql-cluster
purl: pkg:generic/mysql-cluster
cpes:
- cpe:2.3:a:oracle:mysql_cluster:*:*:*:*:*:*:*:*
type: BinaryPkg
- class: mysqld-mysql-cluster-binary
name: mysql-cluster
purl: pkg:generic/mysql-cluster
cpes:
- cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*
- cpe:2.3:a:oracle:mysql_server:*:*:*:*:*:*:*:*
- cpe:2.3:a:oracle:mysql_cluster:*:*:*:*:*:*:*:*
type: BinaryPkg
- class: mysqld-mysql-server-binary
name: mysql-server
purl: pkg:generic/mysql-server
cpes:
- cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*
- cpe:2.3:a:oracle:mysql_server:*:*:*:*:*:*:*:*
type: BinaryPkg
- method: glob
criteria:
- '**/ndbd'
packages:
- class: ndbd-binary
name: mysql-cluster
purl: pkg:generic/mysql-cluster
cpes:
- cpe:2.3:a:oracle:mysql_cluster:*:*:*:*:*:*:*:*
type: BinaryPkg
- method: glob
criteria:
- '**/ndbmtd'
packages:
- class: ndbmtd-binary
name: mysql-cluster
purl: pkg:generic/mysql-cluster
cpes:
- cpe:2.3:a:oracle:mysql_cluster:*:*:*:*:*:*:*:*
type: BinaryPkg
- method: glob
criteria:
- '**/ndb_mgmd'
packages:
- class: ndb_mgmd-binary
name: mysql-cluster
purl: pkg:generic/mysql-cluster
cpes:
- cpe:2.3:a:oracle:mysql_cluster:*:*:*:*:*:*:*:*
type: BinaryPkg
- method: glob
criteria:
- '**/xtrabackup'
@@ -36,9 +36,8 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
// or testdata/classifiers/bin directory . Snippets are searched for first, and if not found, then existing binaries are
// used. If no binary or snippet is found the test will fail. If '-must-use-original-binaries' is used the only
// full binaries are tested (no snippets), and if no binary is found the test will be skipped.
logicalFixture string
expected pkg.Package
expectedPackages []pkg.Package
logicalFixture string
expected pkg.Package
}{
{
logicalFixture: "arangodb/3.11.8/linux-amd64",
@@ -207,82 +206,6 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
Metadata: metadata("mariadb-binary"),
},
},
{
logicalFixture: "mysqld/9.7.0/linux-amd64",
expected: pkg.Package{
Name: "mysql-server",
Version: "9.7.0",
Type: "binary",
PURL: "pkg:generic/mysql-server@9.7.0",
Locations: locations("mysqld"),
Metadata: metadata("mysqld-mysql-server-binary"),
},
},
{
logicalFixture: "mysql-cluster/9.7.0/linux-amd64",
expected: pkg.Package{
Name: "mysql-cluster",
Version: "9.7.0",
Type: "binary",
PURL: "pkg:generic/mysql-cluster@9.7.0",
Locations: locations("mysqld"),
Metadata: metadata("mysqld-mysql-cluster-binary"),
},
},
{
logicalFixture: "mysql-cluster/7.6.17/linux-amd64",
expectedPackages: []pkg.Package{
{
Name: "mysql-server",
Version: "5.7.33",
Type: "binary",
PURL: "pkg:generic/mysql-server@5.7.33",
Locations: locations("mysqld"),
Metadata: metadata("mysqld-mysql-cluster-legacy-binary"),
},
{
Name: "mysql-cluster",
Version: "7.6.17",
Type: "binary",
PURL: "pkg:generic/mysql-cluster@7.6.17",
Locations: locations("mysqld"),
Metadata: metadata("mysqld-mysql-cluster-legacy-binary"),
},
},
},
{
logicalFixture: "ndbd/9.7.0/linux-amd64",
expected: pkg.Package{
Name: "mysql-cluster",
Version: "9.7.0",
Type: "binary",
PURL: "pkg:generic/mysql-cluster@9.7.0",
Locations: locations("ndbd"),
Metadata: metadata("ndbd-binary"),
},
},
{
logicalFixture: "ndbmtd/9.7.0/linux-amd64",
expected: pkg.Package{
Name: "mysql-cluster",
Version: "9.7.0",
Type: "binary",
PURL: "pkg:generic/mysql-cluster@9.7.0",
Locations: locations("ndbmtd"),
Metadata: metadata("ndbmtd-binary"),
},
},
{
logicalFixture: "ndb_mgmd/9.7.0/linux-amd64",
expected: pkg.Package{
Name: "mysql-cluster",
Version: "9.7.0",
Type: "binary",
PURL: "pkg:generic/mysql-cluster@9.7.0",
Locations: locations("ndb_mgmd"),
Metadata: metadata("ndb_mgmd-binary"),
},
},
{
logicalFixture: "mongodb/8.0.17/linux-amd64",
expected: pkg.Package{
@@ -509,39 +432,6 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
Metadata: metadata("haproxy-binary"),
},
},
{
logicalFixture: "helm/4.1.4/linux-s390x",
expected: pkg.Package{
Name: "helm",
Version: "4.1.4",
Type: "binary",
PURL: "pkg:golang/helm.sh/helm@4.1.4",
Locations: locations("helm"),
Metadata: metadata("helm"),
},
},
{
logicalFixture: "helm/3.15.2/linux-amd64",
expected: pkg.Package{
Name: "helm",
Version: "3.15.2",
Type: "binary",
PURL: "pkg:golang/helm.sh/helm@3.15.2",
Locations: locations("helm"),
Metadata: metadata("helm"),
},
},
{
logicalFixture: "helm/3.12.0/linux-s390x",
expected: pkg.Package{
Name: "helm",
Version: "3.12.0",
Type: "binary",
PURL: "pkg:golang/helm.sh/helm@3.12.0",
Locations: locations("helm"),
Metadata: metadata("helm"),
},
},
{
logicalFixture: "helm/3.11.1/linux-amd64",
expected: pkg.Package{
@@ -553,39 +443,6 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
Metadata: metadata("helm"),
},
},
{
logicalFixture: "helm/3.0.0-alpha.1/linux-amd64",
expected: pkg.Package{
Name: "helm",
Version: "3.0.0-alpha.1",
Type: "binary",
PURL: "pkg:golang/helm.sh/helm@3.0.0-alpha.1",
Locations: locations("helm"),
Metadata: metadata("helm"),
},
},
{
logicalFixture: "helm/2.17.0-rc.1/linux-amd64",
expected: pkg.Package{
Name: "helm",
Version: "2.17.0-rc.1",
Type: "binary",
PURL: "pkg:golang/helm.sh/helm@2.17.0-rc.1",
Locations: locations("helm"),
Metadata: metadata("helm"),
},
},
{
logicalFixture: "helm/2.0.0-beta.2/linux-amd64",
expected: pkg.Package{
Name: "helm",
Version: "2.0.0-beta.2",
Type: "binary",
PURL: "pkg:golang/helm.sh/helm@2.0.0-beta.2",
Locations: locations("helm"),
Metadata: metadata("helm"),
},
},
{
logicalFixture: "helm/3.10.3/linux-amd64",
expected: pkg.Package{
@@ -1474,50 +1331,6 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
Metadata: metadata("dart-binary"),
},
},
{
logicalFixture: "deno/1.10.3/linux-amd64",
expected: pkg.Package{
Name: "deno",
Version: "1.10.3",
Type: "binary",
PURL: "pkg:generic/deno@1.10.3",
Locations: locations("deno"),
Metadata: metadata("deno-binary"),
},
},
{
logicalFixture: "deno/1.16.4/linux-amd64",
expected: pkg.Package{
Name: "deno",
Version: "1.16.4",
Type: "binary",
PURL: "pkg:generic/deno@1.16.4",
Locations: locations("deno"),
Metadata: metadata("deno-binary"),
},
},
{
logicalFixture: "deno/1.28.3/linux-amd64",
expected: pkg.Package{
Name: "deno",
Version: "1.28.3",
Type: "binary",
PURL: "pkg:generic/deno@1.28.3",
Locations: locations("deno"),
Metadata: metadata("deno-binary"),
},
},
{
logicalFixture: "deno/1.29.4/linux-amd64",
expected: pkg.Package{
Name: "deno",
Version: "1.29.4",
Type: "binary",
PURL: "pkg:generic/deno@1.29.4",
Locations: locations("deno"),
Metadata: metadata("deno-binary"),
},
},
{
logicalFixture: "deno/1.41.0/linux-amd64",
expected: pkg.Package{
@@ -2543,106 +2356,6 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
Metadata: metadata("ingress-nginx-binary"),
},
},
{
logicalFixture: "julia/1.13.0-alpha2/linux-amd64",
expected: pkg.Package{
Name: "julia",
Version: "1.13.0-alpha2",
Type: "binary",
PURL: "pkg:generic/julia@1.13.0-alpha2",
Locations: locations("libjulia-internal.so.1.13.0"),
Metadata: metadata("julia-binary"),
},
},
{
logicalFixture: "julia/1.12.6/linux-amd64",
expected: pkg.Package{
Name: "julia",
Version: "1.12.6",
Type: "binary",
PURL: "pkg:generic/julia@1.12.6",
Locations: locations("libjulia-internal.so.1.12.6"),
Metadata: metadata("julia-binary"),
},
},
{
logicalFixture: "julia/1.11.9/linux-amd64",
expected: pkg.Package{
Name: "julia",
Version: "1.11.9",
Type: "binary",
PURL: "pkg:generic/julia@1.11.9",
Locations: locations("libjulia-internal.so.1.11.9"),
Metadata: metadata("julia-binary"),
},
},
{
logicalFixture: "julia/1.10.11/linux-amd64",
expected: pkg.Package{
Name: "julia",
Version: "1.10.11",
Type: "binary",
PURL: "pkg:generic/julia@1.10.11",
Locations: locations("libjulia-internal.so.1.10.11"),
Metadata: metadata("julia-binary"),
},
},
{
logicalFixture: "julia/1.9.0-alpha1/linux-amd64",
expected: pkg.Package{
Name: "julia",
Version: "1.9.0-alpha1",
Type: "binary",
PURL: "pkg:generic/julia@1.9.0-alpha1",
Locations: locations("libjulia-internal.so.1.9"),
Metadata: metadata("julia-binary"),
},
},
{
logicalFixture: "julia/1.8.5/linux-amd64",
expected: pkg.Package{
Name: "julia",
Version: "1.8.5",
Type: "binary",
PURL: "pkg:generic/julia@1.8.5",
Locations: locations("libjulia-internal.so.1.8"),
Metadata: metadata("julia-binary"),
},
},
{
// note: dynamic (non-snippet) test case
logicalFixture: "julia/1.5.4/linux-amd64",
expected: pkg.Package{
Name: "julia",
Version: "1.5.4",
Type: "binary",
PURL: "pkg:generic/julia@1.5.4",
Locations: locations("julia", "libjulia.so.1.5"),
Metadata: pkg.BinarySignature{
Matches: []pkg.ClassifierMatch{
match("julia-binary", "julia"),
match("julia-binary", "libjulia.so.1.5"),
},
},
},
},
{
// note: dynamic (non-snippet) test case
logicalFixture: "julia/1.3.1/linux-amd64",
expected: pkg.Package{
Name: "julia",
Version: "1.3.1",
Type: "binary",
PURL: "pkg:generic/julia@1.3.1",
Locations: locations("julia", "libjulia.so.1.3"),
Metadata: pkg.BinarySignature{
Matches: []pkg.ClassifierMatch{
match("julia-binary", "julia"),
match("julia-binary", "libjulia.so.1.3"),
},
},
},
},
}
for _, test := range tests {
@@ -2664,16 +2377,9 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
packages, _, err := c.Catalog(context.Background(), resolver)
require.NoError(t, err)
expected := test.expectedPackages
if len(expected) == 0 {
expected = []pkg.Package{test.expected}
}
require.Len(t, packages, 1, "mismatched package count")
require.Len(t, packages, len(expected), "mismatched package count")
for i := range expected {
assertPackagesAreEqual(t, expected[i], packages[i])
}
assertPackagesAreEqual(t, test.expected, packages[0])
})
}
}
+8 -158
View File
@@ -88,43 +88,8 @@ func DefaultClassifiers() []binutils.Classifier {
{
Class: "julia-binary",
FileGlob: "**/libjulia-internal.so",
EvidenceMatcher: binutils.MatchAny(
// �1.13.0-beta3[NUL]branch
// [NUL]GIT_VERSION_INFO[NUL]jl_image_unpack[NUL]1.13.0-alpha2[NUL]branch
// [NUL]GIT_VERSION_INFO[NUL]__init__[NUL]1.12.6[NUL]branch[NUL]commit
// [NUL]GIT_VERSION_INFO[NUL]__init__[NUL]verify_methods[NUL]1.11.9[NUL]branch[NUL]commit
// [NUL][NUL]__init__[NUL]1.10.11[NUL]verify_methods[NUL]
m.FileContentsVersionMatcher(`\x00__init__\x00(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]|-beta[0-9]|-rc[0-9])?)\x00(branch|verify_methods)`),
m.FileContentsVersionMatcher(`(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]|-beta[0-9]|-rc[0-9])?)\x00branch\x00`),
// [NUL]verify_methods[NUL]Task cannot be serialized[NUL]1.9.0-alpha1[NUL]BigInt[NUL]
m.FileContentsVersionMatcher(`\x00verify_methods\x00.{0,30}(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]|-beta[0-9]|-rc[0-9])?)\x00BigInt`),
// unknown option `%s`[NUL]1.8.5[NUL]julia version %s
m.FileContentsVersionMatcher(`\x00(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]|-beta[0-9]|-rc[0-9])?)\x00julia version`),
),
Package: "julia",
PURL: mustPURL("pkg:generic/julia@version"),
CPEs: singleCPE("cpe:2.3:a:julialang:julia:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
{
Class: "julia-binary",
FileGlob: "**/julia",
EvidenceMatcher: binutils.SharedLibraryLookup(
// libjulia.so.1
// libjulia.so.0.6
// libjulia.so
`^libjulia\.so(\.[0-9])?(\.[0-9])?$`,
binutils.MatchAny(
// unknown option `%s`[NUL]1.5.4[NUL]julia version %s
m.FileContentsVersionMatcher(`\x00(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]|-beta[0-9]|-rc[0-9])?)\x00julia version`),
// [NUL]#kw#[NUL]1.3.1[NUL]BigInt
// [NUL]#kw#[NUL]0.7.0-beta2[NUL]_require_dependencies
m.FileContentsVersionMatcher(`\x00#kw#\x00(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]|-beta[0-9]|-rc[0-9])?)\x00(BigInt|_require_dependencies)`),
// [NUL]ObjectIdDict[NUL]0.6.4[NUL]jl_sysimg_cpu_target
m.FileContentsVersionMatcher(`\x00ObjectIdDict\x00(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]|-beta[0-9]|-rc[0-9])?)\x00jl_sysimg_cpu_target`),
// [NUL]require[NUL]0.4.6[NUL]core2
m.FileContentsVersionMatcher(`\x00require\x00(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]|-beta[0-9]|-rc[0-9])?)\x00core2`),
),
),
EvidenceMatcher: m.FileContentsVersionMatcher(
`(?m)__init__\x00(?P<version>[0-9]+\.[0-9]+\.[0-9]+)\x00verify`),
Package: "julia",
PURL: mustPURL("pkg:generic/julia@version"),
CPEs: singleCPE("cpe:2.3:a:julialang:julia:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
@@ -132,17 +97,8 @@ func DefaultClassifiers() []binutils.Classifier {
{
Class: "helm",
FileGlob: "**/helm",
EvidenceMatcher: binutils.MatchAny(
// [NUL]v1.21.2[NUL].......[NUL][NUL]v4.1.4[NUL][NUL][NUL]
// [NUL]v2.0.0-beta.2[NUL][NUL][NUL]
m.FileContentsVersionMatcher(`\x00v(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha\.[0-9]|-beta\.[0-9]|-rc\.[0-9])?)\x00{2,}`),
// [NUK]'[DLE]v3.12.0[NUL][NUL]...go1.20.3[NUL][NUL]
m.FileContentsVersionMatcher(`v(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha\.[0-9]|-beta\.[0-9]|-rc\.[0-9])?)\x00+.{1,500}go[0-9]+\.[0-9]+\.[0-9]+\x00+`),
// [NUL]v3.11.1[NUL]�[NUL]
m.FileContentsVersionMatcher(`\x00v(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha\.[0-9]|-beta\.[0-9]|-rc\.[0-9])?)\x00`),
// [NUL]@�@v3.15.2[NUL][NUL]
m.FileContentsVersionMatcher(`@v(?P<version>[0-9]+\.[0-9]+\.[0-9]+(-alpha\.[0-9]|-beta\.[0-9]|-rc\.[0-9])?)\x00`),
),
EvidenceMatcher: m.FileContentsVersionMatcher(
`(?m)\x00v(?P<version>[0-9]+\.[0-9]+\.[0-9]+)\x00`),
Package: "helm",
PURL: mustPURL("pkg:golang/helm.sh/helm@version"),
CPEs: singleCPE("cpe:2.3:a:helm:helm:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
@@ -338,96 +294,6 @@ func DefaultClassifiers() []binutils.Classifier {
cpe.Must("cpe:2.3:a:percona:xtradb_cluster:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
},
{
// Legacy MySQL Cluster contains both MySQL Server and MySQL Cluster versions (Example: 5.7.33-ndb-7.5.21)
// This classifier identifies the MySQL Server version of the mysqld binary (5.7.33 in the example above).
Class: "mysqld-mysql-cluster-legacy-binary",
FileGlob: "**/mysqld",
EvidenceMatcher: m.FileContentsVersionMatcher(
`cluster-gpl\x00(?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?)\-ndb\-[0-9]+(\.[0-9]+)?(\.[0-9]+)?`),
Package: "mysql-server",
PURL: mustPURL("pkg:generic/mysql-server@version"),
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
cpe.Must("cpe:2.3:a:oracle:mysql_server:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
},
{
Class: "mysqld-binary",
FileGlob: "**/mysqld",
EvidenceMatcher: binutils.BranchingEvidenceMatcher([]binutils.Classifier{
{
// Legacy MySQL Cluster contains both MySQL Server and MySQL Cluster versions (Example: 5.7.33-ndb-7.5.21)
// This classifier identifies the MySQL Cluster version of the mysqld binary (7.5.21 in the example above).
Class: "mysqld-mysql-cluster-legacy-binary",
EvidenceMatcher: m.FileContentsVersionMatcher(
`cluster-gpl\x00[0-9]+(\.[0-9]+)?(\.[0-9]+)?\-ndb\-(?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?)`),
Package: "mysql-cluster",
PURL: mustPURL("pkg:generic/mysql-cluster@version"),
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:a:oracle:mysql_cluster:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
},
{
// mysqld from MySQL Cluster after versioning was aligned with MySQL Server
Class: "mysqld-mysql-cluster-binary",
EvidenceMatcher: m.FileContentsVersionMatcher(
`/mysql-cluster-gpl-(?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)/`),
Package: "mysql-cluster",
PURL: mustPURL("pkg:generic/mysql-cluster@version"),
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
cpe.Must("cpe:2.3:a:oracle:mysql_server:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
cpe.Must("cpe:2.3:a:oracle:mysql_cluster:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
},
{
// mysqld from MySQL Server
Class: "mysqld-mysql-server-binary",
EvidenceMatcher: m.FileContentsVersionMatcher(
`/mysql-(?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)/`),
Package: "mysql-server",
PURL: mustPURL("pkg:generic/mysql-server@version"),
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:a:oracle:mysql:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
cpe.Must("cpe:2.3:a:oracle:mysql_server:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
},
}...),
},
{
Class: "ndbd-binary",
FileGlob: "**/ndbd",
EvidenceMatcher: m.FileContentsVersionMatcher(
`/mysql-cluster-gpl-(?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)/`),
Package: "mysql-cluster",
PURL: mustPURL("pkg:generic/mysql-cluster@version"),
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:a:oracle:mysql_cluster:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
},
{
Class: "ndbmtd-binary",
FileGlob: "**/ndbmtd",
EvidenceMatcher: m.FileContentsVersionMatcher(
`/mysql-cluster-gpl-(?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)/`),
Package: "mysql-cluster",
PURL: mustPURL("pkg:generic/mysql-cluster@version"),
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:a:oracle:mysql_cluster:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
},
{
Class: "ndb_mgmd-binary",
FileGlob: "**/ndb_mgmd",
EvidenceMatcher: m.FileContentsVersionMatcher(
`/mysql-cluster-gpl-(?P<version>[0-9]+(\.[0-9]+)?(\.[0-9]+)?(alpha[0-9]|beta[0-9]|rc[0-9])?)/`),
Package: "mysql-cluster",
PURL: mustPURL("pkg:generic/mysql-cluster@version"),
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:a:oracle:mysql_cluster:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
},
{
Class: "xtrabackup-binary",
FileGlob: "**/xtrabackup",
@@ -567,26 +433,10 @@ func DefaultClassifiers() []binutils.Classifier {
{
Class: "deno-binary",
FileGlob: "**/deno",
EvidenceMatcher: binutils.MatchAny(
m.FileContentsVersionMatcher(
// Deno/2.6.3
// Deno/1.41.0
`Deno/(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`,
),
m.FileContentsVersionMatcher(
// deno::tools::standalonedeno-65db94feba9d4d51a09b74629f566dbc90484fbarelease/v1.29.4windows
// cli/tools/standalone.rsdeno-74064c9d8c222b33b2a552ea0af1054f57002a96release/v1.28.3windows
`deno-[0-9a-z]{40}release/v(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`,
),
m.FileContentsVersionMatcher(
// cli/tools/standalone.rsdeno-ab286750a8c87215a9651efb11fcc620f29140051.16.4release/vdlwindows
`deno-[0-9a-z]{40}(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`,
),
m.FileContentsVersionMatcher(
// 1.10.31567c1013cc8ff12cf039137792da66a1d0015b5DENO_UNSTABLE_COVERAGE_DIRNo current directorycli/main
`(?P<version>[0-9]+\.[0-9]+\.[0-9]+)[0-9a-z]{40}DENO`,
),
),
EvidenceMatcher: m.FileContentsVersionMatcher(
// Deno/2.6.3
// Deno/1.41.0
`Deno/(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
Package: "deno",
PURL: mustPURL("pkg:generic/deno@version"),
CPEs: singleCPE("cpe:2.3:a:deno:deno:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
@@ -275,15 +275,9 @@ func copyBinaryFromContainer(containerName, containerPath, destinationPath, dige
return err
}
// ensure permissions are 600 for destination (if it is not a symlink)
info, err := os.Lstat(destinationPath)
if err != nil {
return fmt.Errorf("unable to stat file %q: %w", destinationPath, err)
}
if info.Mode()&os.ModeSymlink == 0 {
if err := os.Chmod(destinationPath, 0600); err != nil {
return fmt.Errorf("unable to set permissions on file %q: %w", destinationPath, err)
}
// ensure permissions are 600 for destination
if err := os.Chmod(destinationPath, 0600); err != nil {
return fmt.Errorf("unable to set permissions on file %q: %w", destinationPath, err)
}
// capture digest file
@@ -1,9 +0,0 @@
name: deno
offset: 31454975
length: 120
snippetSha256: 30ab01cb89ba17c770cca7d60e12f2c2119fd8db2b389636053bad1146ac83df
fileSha256: 68ec2c702e9c21e47d5557c603080932ffa24627b463b4a5a4e2ed4ff00f7d5d
### byte snippet to follow ###
s already installed
1.10.31567c1013cc8ff12cf039137792da66a1d0015b5DENO_UNSTABLE_COVERAGE_DIRNo current directorycli/main
@@ -1,9 +0,0 @@
name: deno
offset: 4219127
length: 120
snippetSha256: 97e369d4eed74c5b1ff7d578c9de100c71136dfcc54f19455b2938671d1a9640
fileSha256: f3af5cf3838c0cd01de1acaaa716de804ad08c716927af1848aa9664b96a737c
### byte snippet to follow ###
g ctrl+d or close()
Error: cli/tools/standalone.rsdeno-ab286750a8c87215a9651efb11fcc620f29140051.16.4release/vdlwindowsh
@@ -1,9 +0,0 @@
name: deno
offset: 5079501
length: 110
snippetSha256: aa6181b1204d821493756007090ad81677a26f20de0efe9c53bdf401b54849fd
fileSha256: 3373cbed016860095b01f693a58181c4cf1ac9d6ab7bd5dbca5f684788402919
### byte snippet to follow ###
n to exit
cli/tools/standalone.rsdeno-74064c9d8c222b33b2a552ea0af1054f57002a96release/v1.28.3windowshttps://dl
@@ -1,9 +0,0 @@
name: deno
offset: 5116362
length: 220
snippetSha256: 786a6c5d8be76e3c6e628cd2400c6ed5a7a7cfc75b135e8e7f1375f55dc28787
fileSha256: d9c8a385c3704e220b1722c642f22e32f8f267013742f9b44d68c67bb5f9232d
### byte snippet to follow ###
ument. For example:
deno run --allow-read=. main.js./$deno$eval.console.log(cli/tools/standalone.rsCompiledeno::tools::standalonedeno-65db94feba9d4d51a09b74629f566dbc90484fbarelease/v1.29.4windowshttps://dl.deno.land
@@ -1 +0,0 @@
libjulia-internal.so.1.10.11
@@ -1 +0,0 @@
libjulia-internal.so.1.11.9
@@ -1 +0,0 @@
libjulia-internal.so.1.12.6
@@ -1 +0,0 @@
libjulia-internal.so.1.13.0
@@ -1 +0,0 @@
libjulia-internal.so.1.13.0
@@ -1 +0,0 @@
libjulia-internal.so.1.8
@@ -1 +0,0 @@
libjulia-internal.so.1.9
+14 -203
View File
@@ -123,38 +123,6 @@ from-images:
paths:
- /usr/lib/dart/bin/dart
- name: deno
version: 1.10.3
images:
- ref: denoland/deno:1.10.3@sha256:9687db39d68333fce31f371734a1b982092507606508289a5c7a24cfc5fe6ee2
platform: linux/amd64
paths:
- /usr/bin/deno
- name: deno
version: 1.16.4
images:
- ref: denoland/deno:1.16.4@sha256:027868eb6f079ef290957bcda05280a6b08ff86baf549bc6eff5c17467a44d41
platform: linux/amd64
paths:
- /usr/bin/deno
- name: deno
version: 1.28.3
images:
- ref: denoland/deno:1.28.3@sha256:8636e6ac55fbd4687c111eb4b798b1772d43874c53647ca4a2bad6d1962643f0
platform: linux/amd64
paths:
- /usr/bin/deno
- name: deno
version: 1.29.4
images:
- ref: denoland/deno:1.29.4@sha256:f5b5a4678b18884724b277a4eb5490a978eab2da5a47461766df9fb59ebb08b6
platform: linux/amd64
paths:
- /usr/bin/deno
- name: deno
version: 1.41.0
images:
@@ -344,52 +312,20 @@ from-images:
paths:
- /usr/bin/mysql
- version: 9.7.0
images:
- ref: mysql:9.7.0@sha256:6e5e46e6aece0bc8edb5abecc6fd726653f36447860f7f4dbf3481c91b477f69
platform: linux/amd64
paths:
- /usr/sbin/mysqld
- name: mysql-cluster
version: 9.7.0
images:
- ref: container-registry.oracle.com/mysql/community-cluster:9.7.0
platform: linux/amd64
paths:
- /usr/sbin/mysqld
- name: mysql-cluster
version: 7.6.17
images:
- ref: container-registry.oracle.com/mysql/community-cluster:7.6.17
platform: linux/amd64
paths:
- /usr/sbin/mysqld
- name: ndbd
version: 9.7.0
images:
- ref: container-registry.oracle.com/mysql/community-cluster:9.7.0
platform: linux/amd64
paths:
- /usr/sbin/ndbd
- name: ndbmtd
version: 9.7.0
images:
- ref: container-registry.oracle.com/mysql/community-cluster:9.7.0
platform: linux/amd64
paths:
- /usr/sbin/ndbmtd
- name: ndb_mgmd
version: 9.7.0
images:
- ref: container-registry.oracle.com/mysql/community-cluster:9.7.0
platform: linux/amd64
paths:
- /usr/sbin/ndb_mgmd
# TODO: add pattern for mysqld
# - version: 5.6.51
# images:
# - ref: mysql:5.6.51@sha256:897086d07d1efa876224b147397ea8d3147e61dd84dce963aace1d5e9dc2802d
# platform: linux/amd64
# paths:
# - /usr/sbin/mysqld
#
# - version: 8.0.34
# images:
# - ref: mysql:8.0.34@sha256:8b8835a2c32cd7357a5d2ea4b49ad870ff519c8c1d4add362803feddf4a0a973
# platform: linux/amd64
# paths:
# - /usr/sbin/mysqld
- name: mongodb
version: 8.0.17
@@ -868,27 +804,6 @@ from-images:
- /usr/local/lib/libruby.so.2.6.10
- /usr/local/lib/libruby.so.2.6
- version: 4.1.4
images:
- ref: alpine/helm:4.1.4@sha256:d69c97f71f38128c3ed4b8bcd70b4de65efad9e09494c85d158661e7ffd8b719
platform: linux/s390x
paths:
- /usr/bin/helm
- version: 3.15.2
images:
- ref: alpine/helm:3.15.2@sha256:61185768b41810085cb57a9bc8de9003bea78ac0dd417e5b0b16223a6a0aa812
platform: linux/amd64
paths:
- /usr/bin/helm
- version: 3.12.0
images:
- ref: alpine/helm:3.12.0@sha256:6f6e18df0710af82188ab8b27d3890b6d519c501c0982f3a76f3fdbff39ff3c7
platform: linux/s390x
paths:
- /usr/bin/helm
- version: 3.11.1
images:
- ref: alpine/helm:3.11.1@sha256:8628e3695fb743a8b9de89626f1b7a221280c2152c0e288c2504e59b68233e8b
@@ -903,27 +818,6 @@ from-images:
paths:
- /usr/local/bin/helm
- version: 3.0.0-alpha.1
images:
- ref: alpine/helm:3.0.0-alpha.1@sha256:95bd39add326ac58a333815666aace6d4a28606a79eef96d4e44287b11540b69
platform: linux/amd64
paths:
- /usr/bin/helm
- version: 2.17.0-rc.1
images:
- ref: alpine/helm:2.17.0-rc.1@sha256:3938b9f291794fe88489dae2a87e0ad9d634464c686186d4a3ca33beef84278d
platform: linux/amd64
paths:
- /usr/bin/helm
- version: 2.0.0-beta.2
images:
- ref: alpine/helm:2.0.0-beta.2@sha256:97d97b27a723b28c459d6c92e7b0591c553e88e483a248235fbdaa4dacb2e6d5
platform: linux/amd64
paths:
- /usr/bin/helm
- version: 1.15.2
images:
- ref: hashicorp/consul:1.15.2@sha256:c2169f3bb18dd947ae8eb5f6766896695c71fb439f050a3343e0007d895615b8
@@ -1566,86 +1460,3 @@ from-images:
paths:
- /nginx-ingress-controller
- name: julia
version: 1.13.0-beta3
images:
- ref: library/julia:1.13.0-beta3@sha256:3b36013b071d9abc9bdedb66a4230a9445bc692aa2c49f85852b94e81c7f0a74
platform: linux/amd64
paths:
- /usr/local/julia/lib/julia/libjulia-internal.so
- /usr/local/julia/lib/julia/libjulia-internal.so.1.13.0
- name: julia
version: 1.13.0-alpha2
images:
- ref: library/julia:1.13.0-alpha2@sha256:f1b1cd24979025371be317353d0d9071e9b549583d2b13783cbafd40b8d4e319
platform: linux/amd64
paths:
- /usr/local/julia/lib/julia/libjulia-internal.so
- /usr/local/julia/lib/julia/libjulia-internal.so.1.13.0
- name: julia
version: 1.12.6
images:
- ref: library/julia:1.12.6@sha256:54d6a3f40bbd76021e6ca8fab2dd2af08cc5388b078223d3040eaf3567b4ccd3
platform: linux/amd64
paths:
- /usr/local/julia/lib/julia/libjulia-internal.so
- /usr/local/julia/lib/julia/libjulia-internal.so.1.12.6
- name: julia
version: 1.11.9
images:
- ref: library/julia:1.11.9@sha256:18e83baa9277c2ac94bef267d585634760b5adf9bc7343480161c7b09034b452
platform: linux/amd64
paths:
- /usr/local/julia/lib/julia/libjulia-internal.so
- /usr/local/julia/lib/julia/libjulia-internal.so.1.11.9
- name: julia
version: 1.10.11
images:
- ref: library/julia:1.10.11@sha256:2f27b44f3ecda0f941c1b475b8967fa933fbf52b5f877f69bfe4df959c56df66
platform: linux/amd64
paths:
- /usr/local/julia/lib/julia/libjulia-internal.so
- /usr/local/julia/lib/julia/libjulia-internal.so.1.10.11
- name: julia
version: 1.9.0-alpha1
images:
- ref: library/julia:1.9.0-alpha1@sha256:fb932603485d7cea435e85c073c04bdf4d0b90232c03013585aa0f65c8216111
platform: linux/amd64
paths:
- /usr/local/julia/lib/julia/libjulia-internal.so
- /usr/local/julia/lib/julia/libjulia-internal.so.1.9
- name: julia
version: 1.8.5
images:
- ref: library/julia:1.8.5@sha256:5edccd0ca0b5f00d78beca0bd8217d65b2c24ef051ad07e2b08ed67224ff905a
platform: linux/amd64
paths:
- /usr/local/julia/lib/julia/libjulia-internal.so
- /usr/local/julia/lib/julia/libjulia-internal.so.1.8
- name: julia
version: 1.5.4
images:
- ref: library/julia:1.5.4@sha256:39c3f721aa5ede195965e7f20575b1ee5949bdd2b42204e227d98114bcc94b83
platform: linux/amd64
paths:
- /usr/local/julia/bin/julia
- /usr/local/julia/lib/libjulia.so.1
- /usr/local/julia/lib/libjulia.so.1.5
- name: julia
version: 1.3.1
images:
- ref: library/julia:1.3.1@sha256:a14f56f9f2ed44559d9f435cc346ede09a7d61afcbac61ba037acd2b39b56171
platform: linux/amd64
paths:
- /usr/local/julia/bin/julia
- /usr/local/julia/lib/libjulia.so.1
- /usr/local/julia/lib/libjulia.so.1.3
@@ -2335,9 +2335,6 @@
"@backstage/techdocs-common": [
"cpe:2.3:a:linuxfoundation:\\@backstage\\/techdocs-common:*:*:*:*:*:node.js:*:*"
],
"@better-auth/oauth-provider": [
"cpe:2.3:a:better-auth:better-auth\\/oauth-provider:*:*:*:*:*:node.js:*:*"
],
"@braintree/sanitize-url": [
"cpe:2.3:a:paypal:braintree\\/sanitize-url:*:*:*:*:*:node.js:*:*"
],
@@ -2377,9 +2374,6 @@
"@coding-solo/godot-mcp": [
"cpe:2.3:a:coding-solo:godot_mcp:*:*:*:*:*:*:*:*"
],
"@contentauth/c2pa-web": [
"cpe:2.3:a:adobe:c2pa-web:*:*:*:*:*:node.js:*:*"
],
"@cookiex/deep": [
"cpe:2.3:a:cookiex-deep_project:cookiex-deep:*:*:*:*:*:node.js:*:*"
],
@@ -2399,7 +2393,7 @@
"cpe:2.3:a:evershop:evershop:*:*:*:*:*:node.js:*:*"
],
"@fastify/middie": [
"cpe:2.3:a:fastify:fastify\\/middie:*:*:*:*:*:node.js:*:*"
"cpe:2.3:a:openjsf:\\@fastify\\/middie:*:*:*:*:*:fastify:*:*"
],
"@fastly/js-compute": [
"cpe:2.3:a:fastly:js-compute:*:*:*:*:*:node.js:*:*"
@@ -3439,9 +3433,6 @@
"fast-string-search": [
"cpe:2.3:a:fast_string_search_project:fast_string_search:*:*:*:*:*:node.js:*:*"
],
"fast-uri": [
"cpe:2.3:a:openjsf:fast-uri:*:*:*:*:*:node.js:*:*"
],
"fast-xml-parser": [
"cpe:2.3:a:naturalintelligence:fast-xml-parser:*:*:*:*:*:*:*:*"
],
@@ -3906,9 +3897,6 @@
"iniparserjs": [
"cpe:2.3:a:iniparserjs_project:iniparserjs:*:*:*:*:*:node.js:*:*"
],
"inngest": [
"cpe:2.3:a:inngest:inngest:*:*:*:*:*:node.js:*:*"
],
"install-g-test": [
"cpe:2.3:a:install-g-test_project:install-g-test:*:*:*:*:*:node.js:*:*"
],
@@ -5358,8 +5346,7 @@
"cpe:2.3:a:serc.js_project:serc.js:*:*:*:*:*:node.js:*:*"
],
"serialize-javascript": [
"cpe:2.3:a:verizon:serialize-javascript:*:*:*:*:*:node.js:*:*",
"cpe:2.3:a:yahoo:serialize_javascript:*:*:*:*:*:node.js:*:*"
"cpe:2.3:a:verizon:serialize-javascript:*:*:*:*:*:node.js:*:*"
],
"serialize-to-js": [
"cpe:2.3:a:serialize-to-js_project:serialize-to-js:*:*:*:*:*:node.js:*:*"
@@ -5627,9 +5614,6 @@
"svelte": [
"cpe:2.3:a:svelte:svelte:*:*:*:*:*:node.js:*:*"
],
"svgo": [
"cpe:2.3:a:svgo:svgo:*:*:*:*:*:node.js:*:*"
],
"swagger-ui-dist": [
"cpe:2.3:a:smartbear:swagger-ui-dist:*:*:*:*:*:node.js:*:*"
],
@@ -6160,9 +6144,6 @@
"XML2Dict": [
"cpe:2.3:a:xml2dict_project:xml2dict:*:*:*:*:*:python:*:*"
],
"agixt": [
"cpe:2.3:a:agixt:agixt:*:*:*:*:*:*:*:*"
],
"aiohttp-session": [
"cpe:2.3:a:aio-libs:aiohttp_session:*:*:*:*:*:*:*:*"
],
@@ -6190,9 +6171,6 @@
"b2sdk": [
"cpe:2.3:a:backblaze:b2-sdk-python:*:*:*:*:*:*:*:*"
],
"bedrock-agentcore-starter-toolkit": [
"cpe:2.3:a:amazon:bedrock_agentcore_starter_toolkit:*:*:*:*:*:python:*:*"
],
"black": [
"cpe:2.3:a:python:black:*:*:*:*:*:python:*:*"
],
@@ -6402,9 +6380,6 @@
"langchain-experimental": [
"cpe:2.3:a:langchain:langchain_experimental:*:*:*:*:*:python:*:*"
],
"langflow-base": [
"cpe:2.3:a:langflow:langflow-base:*:*:*:*:*:python:*:*"
],
"lerobot": [
"cpe:2.3:a:huggingface:lerobot:*:*:*:*:*:python:*:*"
],
@@ -6708,9 +6683,6 @@
"telnyx": [
"cpe:2.3:a:telnyx:telnyx:*:*:*:*:*:python:*:*"
],
"tinytag": [
"cpe:2.3:a:tinytag:tinytag:*:*:*:*:*:python:*:*"
],
"tkvideoplayer": [
"cpe:2.3:a:python:tkvideoplayer:*:*:*:*:*:*:*:*"
],
@@ -7130,9 +7102,6 @@
"rbovirt": [
"cpe:2.3:a:amos_benari:rbovirt:*:*:*:*:*:ruby:*:*"
],
"rdiscount": [
"cpe:2.3:a:dafoster:rdiscount:*:*:*:*:*:ruby:*:*"
],
"rdoc": [
"cpe:2.3:a:ruby-lang:rdoc:*:*:*:*:*:ruby:*:*"
],
@@ -7816,9 +7785,6 @@
"try-mutex": [
"cpe:2.3:a:try-mutex_project:try-mutex:*:*:*:*:*:rust:*:*"
],
"tuftool": [
"cpe:2.3:a:amazon:tuftool:*:*:*:*:*:rust:*:*"
],
"tungstenite": [
"cpe:2.3:a:snapview:tungstenite:*:*:*:*:*:rust:*:*"
],
+1 -1
View File
@@ -108,7 +108,7 @@ func (a archiveFilename) extension() string {
func (a archiveFilename) pkgType() pkg.Type {
switch strings.ToLower(a.extension()) {
case "jar", "war", "ear", "lpkg", "par", "sar", "nar", "kar", "rar", "zap":
case "jar", "war", "ear", "lpkg", "par", "sar", "nar", "kar", "rar":
return pkg.JavaPkg
case "jpi", "hpi":
return pkg.JenkinsPluginPkg
@@ -48,7 +48,6 @@ var archiveFormatGlobs = []string{
// out of date, and they charge for their IDE. If you find an example
// project that we can build in CI feel free to include it
"**/*.rar", // Java Resource Adapter Archive
"**/*.zap", // ZAP add-ons https://github.com/zaproxy/zaproxy/wiki/ZapAddOns
}
// javaArchiveHashes are all the current hash algorithms used to calculate archive digests
@@ -351,85 +351,6 @@ func TestParseJar(t *testing.T) {
},
},
},
{
// Dupicate the example-java-app-gradle test and the Makefile is adjusted to copy its jar to example-zap-addon-0.1.0.zap
name: "example-zap-addon",
fixture: "testdata/java-builds/packages/example-zap-addon-0.1.0.zap",
wantErr: require.NoError, // no nested jars
expected: map[string]pkg.Package{
"example-zap-addon": {
Name: "example-zap-addon",
Version: "0.1.0",
PURL: "pkg:maven/example-zap-addon/example-zap-addon@0.1.0",
Language: pkg.Java,
Type: pkg.JavaPkg,
Licenses: pkg.NewLicenseSet(
pkg.License{
Value: "Apache-2.0",
SPDXExpression: "Apache-2.0",
Type: license.Concluded,
Locations: file.NewLocationSet(file.NewLocation("testdata/java-builds/packages/example-zap-addon-0.1.0.zap")),
},
),
Metadata: pkg.JavaArchive{
VirtualPath: "testdata/java-builds/packages/example-zap-addon-0.1.0.zap",
Manifest: &pkg.JavaManifest{
Main: []pkg.KeyValue{
{
Key: "Manifest-Version",
Value: "1.0",
},
{
Key: "Main-Class",
Value: "hello.HelloWorld",
},
},
},
// PomProject: &pkg.JavaPomProject{
// Path: "META-INF/maven/io.jenkins.plugins/example-jenkins-plugin/pom.xml",
// Parent: &pkg.JavaPomParent{GroupID: "org.jenkins-ci.plugins", ArtifactID: "plugin", Version: "4.46"},
// GroupID: "io.jenkins.plugins",
// ArtifactID: "example-jenkins-plugin",
// Version: "1.0-SNAPSHOT",
// Name: "Example Jenkins Plugin",
// },
},
},
"joda-time": {
Name: "joda-time",
Version: "2.2",
PURL: "pkg:maven/joda-time/joda-time@2.2",
Language: pkg.Java,
Type: pkg.JavaPkg,
Licenses: pkg.NewLicenseSet(
pkg.NewLicenseFromFieldsWithContext(ctx, "Apache 2", "http://www.apache.org/licenses/LICENSE-2.0.txt", func() *file.Location {
l := file.NewLocation("testdata/java-builds/packages/example-zap-addon-0.1.0.zap")
return &l
}()),
),
Metadata: pkg.JavaArchive{
// ensure that nested packages with different names than that of the parent are appended as
// a suffix on the virtual path with a colon separator between group name and artifact name
VirtualPath: "testdata/java-builds/packages/example-zap-addon-0.1.0.zap:joda-time:joda-time",
PomProperties: &pkg.JavaPomProperties{
Path: "META-INF/maven/joda-time/joda-time/pom.properties",
GroupID: "joda-time",
ArtifactID: "joda-time",
Version: "2.2",
},
PomProject: &pkg.JavaPomProject{
Path: "META-INF/maven/joda-time/joda-time/pom.xml",
GroupID: "joda-time",
ArtifactID: "joda-time",
Version: "2.2",
Name: "Joda time",
Description: "Date and time library to replace JDK date handling",
URL: "http://joda-time.sourceforge.net",
},
},
},
},
},
}
for _, test := range tests {
@@ -32,7 +32,6 @@ func Test_ArchiveCataloger_Globs(t *testing.T) {
"java-archives/example.far",
"java-archives/example.lpkg",
"java-archives/example.rar",
"java-archives/example.zap",
"archives/example.zip",
"archives/example.tar",
"archives/example.tar.gz",
@@ -1 +0,0 @@
example archive
+1 -4
View File
@@ -14,7 +14,7 @@ fixtures: jars archives native-image
# requirement 2: 'fingerprint' goal to determine if the fixture input that indicates any existing cache should be busted
fingerprint: $(FINGERPRINT_FILE)
jars: $(PKGSDIR)/example-java-app-maven-0.1.0.jar $(PKGSDIR)/example-java-app-gradle-0.1.0.jar $(PKGSDIR)/example-jenkins-plugin.hpi $(PKGSDIR)/spring-boot-0.0.1-SNAPSHOT.jar $(PKGSDIR)/example-zap-addon-0.1.0.zap
jars: $(PKGSDIR)/example-java-app-maven-0.1.0.jar $(PKGSDIR)/example-java-app-gradle-0.1.0.jar $(PKGSDIR)/example-jenkins-plugin.hpi $(PKGSDIR)/spring-boot-0.0.1-SNAPSHOT.jar
archives: $(PKGSDIR)/example-java-app-maven-0.1.0.zip $(PKGSDIR)/example-java-app-maven-0.1.0.tar $(PKGSDIR)/example-java-app-maven-0.1.0.tar.gz $(PKGSDIR)/example-java-app-maven-0.1.0.tgz
@@ -55,9 +55,6 @@ clean-maven:
$(PKGSDIR)/example-java-app-gradle-0.1.0.jar:
./build-example-java-app-gradle.sh $(PKGSDIR)
$(PKGSDIR)/example-zap-addon-0.1.0.zap: $(PKGSDIR)/example-java-app-gradle-0.1.0.jar
cp $(PKGSDIR)/example-java-app-gradle-0.1.0.jar $(PKGSDIR)/example-zap-addon-0.1.0.zap
clean-gradle:
rm -rf example-java-app/.gradle \
example-java-app/build
+3 -4
View File
@@ -11,11 +11,10 @@ import (
"github.com/anchore/syft/syft/pkg"
)
// https://packaging.python.org/en/latest/specifications/name-normalization/
var nameNormalizationPattern = regexp.MustCompile(`[-_.]+`)
func normalize(name string) string {
normalized := nameNormalizationPattern.ReplaceAllString(name, "-")
// https://packaging.python.org/en/latest/specifications/name-normalization/
re := regexp.MustCompile(`[-_.]+`)
normalized := re.ReplaceAllString(name, "-")
return strings.ToLower(normalized)
}
@@ -118,32 +118,32 @@ func TestParseRpmFiles(t *testing.T) {
skipFiles: true,
expected: []pkg.Package{
{
Name: "basesystem",
Version: "0:11-13.el9.0.1",
PURL: "pkg:rpm/basesystem@11-13.el9.0.1?arch=noarch&epoch=0&upstream=basesystem-11-13.el9.0.1.src.rpm",
Locations: file.NewLocationSet(file.NewLocation("/basesystem-11-13.el9.0.1.noarch.rpm")),
Name: "postgresql14-server",
Version: "0:14.10-1PGDG.rhel9",
PURL: "pkg:rpm/postgresql14-server@14.10-1PGDG.rhel9?arch=x86_64&epoch=0&upstream=postgresql14-14.10-1PGDG.rhel9.src.rpm",
Locations: file.NewLocationSet(file.NewLocation("/postgresql14-server-14.10-1PGDG.rhel9.x86_64.rpm")),
FoundBy: "rpm-archive-cataloger",
Type: pkg.RpmPkg,
Licenses: pkg.NewLicenseSet(pkg.NewLicenseFromLocations("Public Domain", file.NewLocation("/basesystem-11-13.el9.0.1.noarch.rpm"))),
Licenses: pkg.NewLicenseSet(pkg.NewLicenseFromLocations("PostgreSQL", file.NewLocation("/postgresql14-server-14.10-1PGDG.rhel9.x86_64.rpm"))),
Language: "",
CPEs: nil,
Metadata: pkg.RpmArchive{
Name: "basesystem",
Version: "11",
Name: "postgresql14-server",
Version: "14.10",
Epoch: ref(0),
Arch: "noarch",
Release: "13.el9.0.1",
SourceRpm: "basesystem-11-13.el9.0.1.src.rpm",
Size: 0,
Arch: "x86_64",
Release: "1PGDG.rhel9",
SourceRpm: "postgresql14-14.10-1PGDG.rhel9.src.rpm",
Size: 24521699,
Signatures: []pkg.RpmSignature{
{
PublicKeyAlgorithm: "RSA",
HashAlgorithm: "SHA256",
Created: "Thu Feb 29 17:37:22 2024",
IssuerKeyID: "702d426d350d275d",
Created: "Tue Jan 2 16:45:56 2024",
IssuerKeyID: "40bca2b408b40d20",
},
},
Vendor: "Rocky Enterprise Software Foundation",
Vendor: "PostgreSQL Global Development Group",
// note: files are not asserted in this test
},
},
@@ -1,24 +1,26 @@
FROM --platform=linux/amd64 rockylinux:9 AS rpm-downloader
# download a signed RPM from the Rocky Linux 9.3 vault. Rocky Linux freezes
# minor-version contents in the vault indefinitely, which gives us a stable
# upstream that won't rotate the way distro "current" repos do (the previous
# fixture used a PostgreSQL repo and broke when PG removed older 14.x RPMs).
# download a signed RPM (PostgreSQL in this example, known to be signed)
# using PostgreSQL official RPM which is signed with their GPG key
# $ rpm -Kv postgresql14-server-14.10-1PGDG.rhel9.x86_64.rpm
# postgresql14-server-14.10-1PGDG.rhel9.x86_64.rpm:
# Header V4 RSA/SHA256 Signature, key ID 08b40d20: NOKEY
# Header SHA256 digest: OK
# Header SHA1 digest: OK
# Payload SHA256 digest: OK
# MD5 digest: OK
#
# $ rpm -Kv basesystem-11-13.el9.0.1.noarch.rpm
# basesystem-11-13.el9.0.1.noarch.rpm:
# Header V4 RSA/SHA256 Signature, key ID 350d275d: NOKEY
# Header SHA256 digest: OK
# Header SHA1 digest: OK
# Payload SHA256 digest: OK
# MD5 digest: OK
# $ rpm -ivh --nodeps --force postgresql14-server-14.10-1PGDG.rhel9.x86_64.rpm
# warning: postgresql14-server-14.10-1PGDG.rhel9.x86_64.rpm: Header V4 RSA/SHA256 Signature, key ID 08b40d20: NOKEY
# Verifying... ################################# [100%]
# Preparing... ################################# [100%]
#
# $ rpm -qp --qf '%{NAME}-%{VERSION}-%{RELEASE} %{RSAHEADER:pgpsig}\n' basesystem-11-13.el9.0.1.noarch.rpm
# basesystem-11-13.el9.0.1 RSA/SHA256, Thu Feb 29 17:37:22 2024, Key ID 702d426d350d275d
# $ rpm -q --qf '%{NAME}-%{VERSION}-%{RELEASE} %{RSAHEADER:pgpsig}\n' postgresql14-server-14.10-1PGDG.rhel9.x86_64
# postgresql14-server-14.10-1PGDG.rhel9 RSA/SHA256, Tue Jan 2 16:45:56 2024, Key ID 40bca2b408b40d20
RUN curl -O https://dl.rockylinux.org/vault/rocky/9.3/BaseOS/x86_64/os/Packages/b/basesystem-11-13.el9.0.1.noarch.rpm
RUN curl -O https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-9-x86_64/postgresql14-server-14.10-1PGDG.rhel9.x86_64.rpm
FROM scratch
COPY --from=rpm-downloader /basesystem-11-13.el9.0.1.noarch.rpm /basesystem-11-13.el9.0.1.noarch.rpm
COPY --from=rpm-downloader /postgresql14-server-14.10-1PGDG.rhel9.x86_64.rpm /postgresql14-server-14.10-1PGDG.rhel9.x86_64.rpm