Compare commits

...
23 Commits
Author SHA1 Message Date
Keith Zantow 16223e6dd7 fix: consider vendored golang packages in module attribution (#5093)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
2026-07-27 15:20:49 -04:00
Eljees 1286689419 Fix missing nested packages in package-lock.json v1 (#5108)
* fix(javascript): catalog nested package-lock v1 dependencies

Signed-off-by: Eljees <57435526+Eljees@users.noreply.github.com>

* test(javascript): cover nested package-lock v1 dependencies

Signed-off-by: Eljees <57435526+Eljees@users.noreply.github.com>

---------

Signed-off-by: Eljees <57435526+Eljees@users.noreply.github.com>
2026-07-27 15:18:48 -04:00
Eljees 295454945c fix: strip publisher URL from RPM CPE vendor (#5081)
Signed-off-by: Eljees <yurytumanov.r@yandex.ru>
2026-07-27 15:18:27 -04:00
Enes Deniz 86baeeb481 fix(rust): omit Cargo PURLs for local packages (#5105)
Signed-off-by: Enes Deniz <142517728+3nesdeniz@users.noreply.github.com>
2026-07-27 14:50:13 +00:00
Rayan Salhabandcyphercodes 2dcf5163b8 fix(apk): allow large installed db fields (#5100)
Signed-off-by: cyphercodes <cyphercodes@users.noreply.github.com>
Co-authored-by: cyphercodes <cyphercodes@users.noreply.github.com>
2026-07-27 14:36:56 +00:00
Arpit Jain 12b8ba47fb Fix inverted bounds check dropping every Erlang string with a backslash (#5110)
parseErlangString advances past a backslash escape and then checks
len(data) >= *i before reading the escaped byte. That condition is
almost always true (it only turns false once *i runs off the end),
so the intended out-of-range guard fires on the very first escape
character it sees instead of only at EOF. Any rebar.lock or OTP
resource file containing a backslash in a quoted string (a Windows
git path, an escaped quote, anything) fails to parse and the whole
file, and every package in it, gets dropped.

Flip the comparison to *i >= len(data) so the guard only trips when
the escape is genuinely truncated, and add a regression test for a
string with an escaped quote.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
2026-07-27 14:22:41 +00:00
Rez Moss 138d9ce2a0 added bun binary classifier (#5103)
* added bun binary classifier

Signed-off-by: Rez Moss <hi@rezmoss.com>

* added bun binary classifier

Signed-off-by: Rez Moss <hi@rezmoss.com>

---------

Signed-off-by: Rez Moss <hi@rezmoss.com>
2026-07-27 10:18:50 -04:00
anchore-oss-update-botandanchore-oss-update-bot 8a229b16c4 chore(deps): update CPE dictionary index (#5109)
Signed-off-by: anchore-oss-update-bot <anchore-oss-update-bot@users.noreply.github.com>
Co-authored-by: anchore-oss-update-bot <anchore-oss-update-bot@users.noreply.github.com>
2026-07-27 10:04:27 -04:00
dependabot[bot] 9af0098a68 chore(deps): bump google.golang.org/grpc from 1.80.0 to 1.82.1 (#5099)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.80.0 to 1.82.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.80.0...v1.82.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.82.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 13:48:24 +00:00
dependabot[bot] 2840ea6653 chore(deps): bump modernc.org/sqlite from 1.53.0 to 1.54.0 (#5098)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.53.0 to 1.54.0.
- [Changelog](https://gitlab.com/cznic/sqlite/blob/master/CHANGELOG.md)
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.53.0...v1.54.0)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-version: 1.54.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 13:29:49 +00:00
dependabot[bot] b38e40e3e6 chore(deps): bump zizmorcore/zizmor-action from 0.5.7 to 0.6.0 (#5096)
Bumps [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) from 0.5.7 to 0.6.0.
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](https://github.com/zizmorcore/zizmor-action/compare/192e21d79ab29983730a13d1382995c2307fbcaa...6599ee8b7a49aef6a770f63d261d214911a7ce02)

---
updated-dependencies:
- dependency-name: zizmorcore/zizmor-action
  dependency-version: 0.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 13:29:21 +00:00
dependabot[bot] a6eedecd31 chore(deps): bump github.com/gpustack/gguf-parser-go (#5097)
Bumps [github.com/gpustack/gguf-parser-go](https://github.com/gpustack/gguf-parser-go) from 0.24.1 to 0.25.0.
- [Release notes](https://github.com/gpustack/gguf-parser-go/releases)
- [Commits](https://github.com/gpustack/gguf-parser-go/compare/v0.24.1...v0.25.0)

---
updated-dependencies:
- dependency-name: github.com/gpustack/gguf-parser-go
  dependency-version: 0.25.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 13:29:04 +00:00
dependabot[bot] 691b1357b2 chore(deps): bump actions/checkout from 7.0.0 to 7.0.1 (#5095)
Bumps [actions/checkout](https://github.com/actions/checkout) from 7.0.0 to 7.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0...3d3c42e5aac5ba805825da76410c181273ba90b1)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-24 13:27:48 +00:00
Alex Goodman c890e7f17f decode golang symbols (#5089)
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-07-23 15:03:36 -04:00
anchore-oss-update-botandanchore-oss-update-bot 29fd7d0dec chore(deps): update anchore dependencies (#5022)
Signed-off-by: anchore-oss-update-bot <anchore-oss-update-bot@users.noreply.github.com>
Co-authored-by: anchore-oss-update-bot <anchore-oss-update-bot@users.noreply.github.com>
2026-07-20 18:04:57 +00:00
Yashas Gunderiaandychampion 289137ff3c Avoid duplicate packages for replaced Go modules (#5069)
* Prevent duplicate Go packages after source replacement resolution

Source analysis already applies module replacements through go/packages. Avoid synthesizing the same replacement again from go.mod while retaining fallback synthesis for modules that source analysis did not resolve.

Constraint: Preserve unimported and local-path replacement cataloging.

Rejected: Deduplicate only during final assembly | That retains redundant license lookup and ambiguous metadata ownership.

Confidence: high

Scope-risk: narrow

Directive: Keep go.mod fallback packages limited to modules absent from source analysis.

Tested: Focused replacement regression, related Go module parser tests, go vet, gofmt, and diff checks.

Not-tested: Docker-backed full cataloger fixtures; local root storage was exhausted by image generation.
Signed-off-by: ychampion <ychampion@users.noreply.github.com>

* Keep replacement fixtures with the Go module test data

Constraint: The maintainer reserves internal/gotestdata for fixtures that need special Go tooling discovery.
Rejected: Leave this fixture in gotestdata | The regression opens its module explicitly and does not need the special location.
Confidence: high
Scope-risk: narrow
Directive: Use internal/gotestdata only when a fixture must avoid Go testdata discovery rules.
Tested: replacement regression repeated 10 times; Go module parser table; go vet for the Go cataloger; gofmt; diff checks.
Not-tested: Full cataloger package; three unrelated parser fixtures fail identically on exact prior head in this environment.
Signed-off-by: ychampion <ychampion@users.noreply.github.com>

---------

Signed-off-by: ychampion <ychampion@users.noreply.github.com>
Co-authored-by: ychampion <ychampion@users.noreply.github.com>
2026-07-20 12:30:56 -04:00
dependabot[bot] 22ffd5209d chore(deps): bump github.com/gkampitakis/go-snaps from 0.5.22 to 0.5.23 (#5079)
Bumps [github.com/gkampitakis/go-snaps](https://github.com/gkampitakis/go-snaps) from 0.5.22 to 0.5.23.
- [Release notes](https://github.com/gkampitakis/go-snaps/releases)
- [Commits](https://github.com/gkampitakis/go-snaps/compare/v0.5.22...v0.5.23)

---
updated-dependencies:
- dependency-name: github.com/gkampitakis/go-snaps
  dependency-version: 0.5.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-20 15:28:53 +00:00
Jason PaulosandAlex Goodman a0852ebf98 Add multi-platform OCI image support (#5074)
* Add multi-platform OCI image support

Signed-off-by: Jason Paulos <jasonpaulos@users.noreply.github.com>

* Reduce calls to PrepareMultiplatformFixtureImage in TestMultiPlatformOCIImageSelection

Signed-off-by: Jason Paulos <jasonpaulos@users.noreply.github.com>

* Use smaller image for testing & update stereoscope fork

Signed-off-by: Jason Paulos <jasonpaulos@users.noreply.github.com>

* bump to stereoscope@main after 548 merge

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Jason Paulos <jasonpaulos@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-07-20 15:28:29 +00:00
anchore-oss-update-botandanchore-oss-update-bot d380ad08b5 chore(deps): update CPE dictionary index (#5082)
Signed-off-by: anchore-oss-update-bot <anchore-oss-update-bot@users.noreply.github.com>
Co-authored-by: anchore-oss-update-bot <anchore-oss-update-bot@users.noreply.github.com>
2026-07-20 15:21:24 +00:00
dependabot[bot] ae9534203d chore(deps): bump golang.org/x/mod from 0.37.0 to 0.38.0 (#5078)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.37.0 to 0.38.0.
- [Commits](https://github.com/golang/mod/compare/v0.37.0...v0.38.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-version: 0.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-17 13:52:25 +00:00
dependabot[bot] dc1ef98237 chore(deps): bump golang.org/x/tools from 0.47.0 to 0.48.0 (#5077)
Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.47.0 to 0.48.0.
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.47.0...v0.48.0)

---
updated-dependencies:
- dependency-name: golang.org/x/tools
  dependency-version: 0.48.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-17 13:52:22 +00:00
dependabot[bot] 36a3af41d9 chore(deps): bump golang.org/x/net from 0.56.0 to 0.57.0 (#5076)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.56.0 to 0.57.0.
- [Commits](https://github.com/golang/net/compare/v0.56.0...v0.57.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.57.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-17 13:32:07 +00:00
Christopher Angelo Phillips 3e2bc6ed09 ci: add docker-container driver (#5071)
* ci: add docker-container driver

Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>

* fix: update to v4.2.0

Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>

---------

Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
2026-07-16 10:21:22 -04:00
35 changed files with 1228 additions and 146 deletions
+6 -1
View File
@@ -75,7 +75,7 @@ jobs:
packages: write # required for publishing release artifacts to GitHub packages
id-token: write # required for keyless signing (cosign/sigstore OIDC)
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 #v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7.0.1
with:
fetch-depth: 0
persist-credentials: true
@@ -83,6 +83,11 @@ jobs:
- name: Bootstrap environment
uses: ./.github/actions/bootstrap
# dockers_v2 builds multi-platform manifests in a single buildx invocation, which requires a
# docker-container driver builder (the default builder on the runner cannot build multi-platform).
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Login to Docker Hub
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 #v4.4.0
with:
@@ -20,12 +20,12 @@ jobs:
contents: read
security-events: write # for uploading SARIF results
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: "Run zizmor"
uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7
uses: zizmorcore/zizmor-action@6599ee8b7a49aef6a770f63d261d214911a7ce02 # v0.6.0
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
+7 -7
View File
@@ -28,7 +28,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 #v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7.0.1
with:
persist-credentials: false
@@ -50,7 +50,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 #v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7.0.1
with:
persist-credentials: false
@@ -72,7 +72,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 #v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7.0.1
with:
persist-credentials: false
@@ -105,7 +105,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 #v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7.0.1
with:
persist-credentials: false
@@ -135,7 +135,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 #v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7.0.1
with:
persist-credentials: false
@@ -179,7 +179,7 @@ jobs:
- name: Install Cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 #v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7.0.1
with:
persist-credentials: false
@@ -213,7 +213,7 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 #v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7.0.1
with:
persist-credentials: false
@@ -0,0 +1,145 @@
package integration
import (
"context"
"encoding/json"
"fmt"
"runtime"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/anchore/stereoscope/pkg/image"
"github.com/anchore/stereoscope/pkg/imagetest"
"github.com/anchore/syft/syft"
"github.com/anchore/syft/syft/source"
)
// TestMultiPlatformOCIImageSelection verifies that syft can load a single platform out of a
// multi-platform OCI image on disk (both --from oci-dir and --from oci-archive) by selecting the
// image that matches the requested platform.
func TestMultiPlatformOCIImageSelection(t *testing.T) {
remoteImage := "docker.io/library/busybox:1.38.0"
// Per-platform image config digests within the multi-platform index, obtained from the OCI layout
// (see anchore/stereoscope integration tests: TestPlatformSelectionWithOciLocalSources).
expectedDigest := map[string]string{
"arm64": "sha256:e0e8b3cbfed68a90084781e2962f9c0deead51c5a3f11a488eef0283a4284bc2",
"s390x": "sha256:0cf160e720a8e4f20883b72276a6eaded83b79539f3f1d39e35a3336154b9960",
"amd64": "sha256:c6348fa86ba0fb2108c9334f5fe913ddc6d853313e655891f133a0127c30099f",
"ppc64le": "sha256:b144fc0e06537d07956cde340b878a81a717e394edb736d3110858a12a6635cb",
}
// syft --from source tag -> stereoscope OCI source used to prepare the local fixture
sources := map[string]image.Source{
"oci-dir": image.OciDirectorySource,
"oci-archive": image.OciTarballSource,
}
for from, imageSource := range sources {
t.Run(from, func(t *testing.T) {
localPath := imagetest.PrepareMultiplatformFixtureImage(t, imageSource, remoteImage)
for _, arch := range []string{"amd64", "arm64", "s390x", "ppc64le"} {
t.Run(fmt.Sprintf("linux/%s", arch), func(t *testing.T) {
platform, err := image.NewPlatform("linux/" + arch)
require.NoError(t, err)
src, err := syft.GetSource(
context.Background(),
localPath,
syft.DefaultGetSourceConfig().WithSources(from).WithPlatform(platform),
)
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, src.Close())
})
meta, ok := src.Describe().Metadata.(source.ImageMetadata)
require.True(t, ok, "expected image metadata, got %T", src.Describe().Metadata)
// The raw config of the selected image must match the requested platform...
assertConfigPlatform(t, meta.RawConfig, "linux", arch)
// ...and it must be the exact per-platform image from the multi-platform index.
assert.Equal(t, expectedDigest[arch], meta.ID)
})
}
})
}
}
// TestMultiPlatformOCIImageSelection_UnavailablePlatform verifies that requesting a platform not present
// in the multi-platform OCI image results in an error rather than silently selecting the wrong image.
func TestMultiPlatformOCIImageSelection_UnavailablePlatform(t *testing.T) {
remoteImage := "docker.io/library/busybox:1.38.0"
// windows/amd64 is not present in this linux-only multi-platform image
platform, err := image.NewPlatform("windows/amd64")
require.NoError(t, err)
sources := map[string]image.Source{
"oci-dir": image.OciDirectorySource,
"oci-archive": image.OciTarballSource,
}
for from, imageSource := range sources {
t.Run(from, func(t *testing.T) {
localPath := imagetest.PrepareMultiplatformFixtureImage(t, imageSource, remoteImage)
_, err := syft.GetSource(
context.Background(),
localPath,
syft.DefaultGetSourceConfig().WithSources(from).WithPlatform(platform),
)
require.ErrorContains(t, err, "windows/amd64")
})
}
}
// TestMultiPlatformOCIImageSelection_DefaultPlatform verifies that not specifying a platform results
// in the current platform being selected.
func TestMultiPlatformOCIImageSelection_DefaultPlatform(t *testing.T) {
remoteImage := "docker.io/library/busybox:1.38.0"
sources := map[string]image.Source{
"oci-dir": image.OciDirectorySource,
"oci-archive": image.OciTarballSource,
}
for from, imageSource := range sources {
t.Run(from, func(t *testing.T) {
localPath := imagetest.PrepareMultiplatformFixtureImage(t, imageSource, remoteImage)
src, err := syft.GetSource(
context.Background(),
localPath,
syft.DefaultGetSourceConfig().WithSources(from),
)
require.NoError(t, err)
t.Cleanup(func() {
require.NoError(t, src.Close())
})
meta, ok := src.Describe().Metadata.(source.ImageMetadata)
require.True(t, ok, "expected image metadata, got %T", src.Describe().Metadata)
// The raw config of the selected image must match the current platform
assertConfigPlatform(t, meta.RawConfig, "linux", runtime.GOARCH)
})
}
}
// assertConfigPlatform asserts the os/architecture recorded in a raw OCI image config document.
func assertConfigPlatform(t *testing.T, rawConfig []byte, os, architecture string) {
t.Helper()
require.NotEmpty(t, rawConfig)
var cfg struct {
OS string `json:"os"`
Architecture string `json:"architecture"`
}
require.NoError(t, json.Unmarshal(rawConfig, &cfg))
assert.Equal(t, os, cfg.OS)
assert.Equal(t, architecture, cfg.Architecture)
}
@@ -7,4 +7,6 @@
!image-pkg-coverage/pkgs/java/*.hpi
**/go.sum
!image-go-bin-arch-coverage/go.sum
!image-go-bin-arch-coverage/go.sum
cache/
+27 -27
View File
@@ -18,11 +18,11 @@ require (
github.com/anchore/go-homedir v0.1.1
github.com/anchore/go-logger v0.1.1
github.com/anchore/go-macholibre v0.1.1
github.com/anchore/go-rpmdb v0.1.0
github.com/anchore/go-rpmdb v0.2.0
github.com/anchore/go-sync v0.1.1
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.2
github.com/anchore/stereoscope v0.3.0
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
@@ -40,7 +40,7 @@ require (
github.com/elliotchance/phpserialize v1.4.0
github.com/facebookincubator/nvdtools v0.1.5
github.com/github/go-spdx/v2 v2.7.0
github.com/gkampitakis/go-snaps v0.5.22
github.com/gkampitakis/go-snaps v0.5.23
github.com/go-git/go-billy/v5 v5.9.0
github.com/go-git/go-git/v5 v5.19.1
github.com/go-test/deep v1.1.1
@@ -52,7 +52,7 @@ require (
github.com/google/licensecheck v0.3.1
github.com/google/uuid v1.6.0
github.com/gookit/color v1.6.1
github.com/gpustack/gguf-parser-go v0.24.1
github.com/gpustack/gguf-parser-go v0.25.0
github.com/hashicorp/go-cleanhttp v0.5.2
github.com/hashicorp/go-getter v1.8.6
github.com/hashicorp/go-multierror v1.1.1
@@ -93,12 +93,12 @@ require (
go.uber.org/goleak v1.3.0
go.yaml.in/yaml/v3 v3.0.4
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f
golang.org/x/mod v0.37.0
golang.org/x/net v0.56.0
golang.org/x/mod v0.38.0
golang.org/x/net v0.57.0
golang.org/x/time v0.15.0
golang.org/x/tools v0.47.0
golang.org/x/tools v0.48.0
gopkg.in/yaml.v3 v3.0.1
modernc.org/sqlite v1.53.0
modernc.org/sqlite v1.54.0
)
require (
@@ -118,7 +118,7 @@ require (
cloud.google.com/go/storage v1.61.3 // 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.32.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
@@ -168,10 +168,10 @@ require (
github.com/clipperhouse/displaywidth v0.11.0 // indirect
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
github.com/cloudflare/circl v1.6.3 // indirect
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 // 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.2 // indirect
github.com/containerd/containerd/v2 v2.3.3 // indirect
github.com/containerd/continuity v0.5.0 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
@@ -183,14 +183,14 @@ require (
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.5.3+incompatible // indirect
github.com/docker/cli v29.6.1+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.5 // indirect
github.com/docker/go-connections v0.7.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect
github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect
github.com/envoyproxy/go-control-plane/envoy v1.37.0 // indirect
github.com/envoyproxy/protoc-gen-validate v1.3.3 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/felixge/fgprof v0.9.5 // indirect
@@ -238,8 +238,8 @@ require (
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/locker v1.0.1 // indirect
github.com/moby/moby/api v1.54.2 // indirect
github.com/moby/moby/client v0.4.1 // indirect
github.com/moby/moby/api v1.55.0 // indirect
github.com/moby/moby/client v0.5.0 // indirect
github.com/moby/sys/sequential v0.6.0 // indirect
github.com/moby/sys/signal v0.7.1 // indirect
github.com/moby/sys/user v0.4.0 // indirect
@@ -257,7 +257,7 @@ require (
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/opencontainers/runtime-spec v1.3.0 // 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.4.3 // indirect
github.com/pierrec/lz4/v4 v4.1.26 // indirect
github.com/piprate/json-gold v0.7.0 // indirect
github.com/pjbgf/sha1cd v0.6.0 // indirect
@@ -299,7 +299,7 @@ require (
github.com/zclconf/go-cty v1.16.3 // indirect
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/detectors/gcp v1.43.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/otel v1.43.0 // indirect
@@ -309,22 +309,22 @@ require (
go.opentelemetry.io/otel/trace v1.43.0 // indirect
go.yaml.in/yaml/v4 v4.0.0-rc.2 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
golang.org/x/crypto v0.53.0 // indirect
golang.org/x/crypto v0.54.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect
golang.org/x/sync v0.21.0 // indirect
golang.org/x/sys v0.46.0 // indirect
golang.org/x/term v0.44.0 // indirect
golang.org/x/text v0.38.0 // indirect
golang.org/x/sync v0.22.0 // indirect
golang.org/x/sys v0.47.0 // indirect
golang.org/x/term v0.45.0 // indirect
golang.org/x/text v0.40.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
gonum.org/v1/gonum v0.17.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/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect
google.golang.org/grpc v1.82.1 // indirect
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
modernc.org/libc v1.73.4 // indirect
modernc.org/libc v1.74.1 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/memory v1.11.0 // indirect
)
+60 -60
View File
@@ -82,8 +82,8 @@ github.com/CycloneDX/cyclonedx-go v0.11.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.32.0 h1:rIkQfkCOVKc1OiRCNcSDD8ml5RJlZbH/Xsq7lbpynwc=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.32.0/go.mod h1:RD2SsorTmYhF6HkTmDw7KmPYQk8OBYwTkuasChwv7R4=
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=
@@ -136,8 +136,8 @@ github.com/anchore/go-lzo v0.1.1 h1:IwL/fvkdtlIrYIXck6WxZ3nb8WjjHziYYmGxlooyOnM=
github.com/anchore/go-lzo v0.1.1/go.mod h1:3kLx0bve2oN1iDwgM1U5zGku1Tfbdb0No5qp1eL1fIk=
github.com/anchore/go-macholibre v0.1.1 h1:sTBHi3S1WVIOCamc6NyT8Sn9mBmD30DCTfjfVm4k6/M=
github.com/anchore/go-macholibre v0.1.1/go.mod h1:YNq2610RlvGCK0Za+Klz/OCMtUaEnwwAGA/VfUAQaro=
github.com/anchore/go-rpmdb v0.1.0 h1:Q8dc208/HYzCqhx0L1zurfm1UPil24hlo9NjkdFmLdE=
github.com/anchore/go-rpmdb v0.1.0/go.mod h1:eQVa6QFGzKy0qMcnW2pez0XBczvgwSjw9vA23qifEyU=
github.com/anchore/go-rpmdb v0.2.0 h1:ixcyMg/guhBL9XjBVwhTv9CG48xO07Qkg2uDX2+zx/c=
github.com/anchore/go-rpmdb v0.2.0/go.mod h1:ATsRlpCXstnoYfzqBfhwGw0U2dolx1BBQ9rAU8jWBAw=
github.com/anchore/go-struct-converter v0.2.0-rc2 h1:q+859fW2/jbHJHB2etbNfRlFwYpknyvbqqk1hUdamQ4=
github.com/anchore/go-struct-converter v0.2.0-rc2/go.mod h1:cDBA5vhcR62nXWo8QH9/Kk2807o65ISaHPNPX66L+Uw=
github.com/anchore/go-sync v0.1.1 h1:91SZ+YqUIIHmf2jPAYZPuHqM/ZqnK1pVJDWtET6+AJE=
@@ -146,8 +146,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.2 h1:SGTLGoF6GHmKEn9Bb6LYpzzgz9nhvMZgN/c4fTSQjYY=
github.com/anchore/stereoscope v0.2.2/go.mod h1:ylJXJKebLctP7u9ewguB1d0zUETJxvAA7r2DiuljDTM=
github.com/anchore/stereoscope v0.3.0 h1:6mGGRxm4zRKj/jNiSM7g6XGwWihrnkQRJj11hcULDqY=
github.com/anchore/stereoscope v0.3.0/go.mod h1:QIBWxa5WCrjtBqXH0+RIuECATrffcbaNdMWquZ83+OI=
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=
@@ -290,14 +290,14 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-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/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik=
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2/go.mod h1:qwXFYgsP6T7XnJtbKlf1HP8AjxZZyzxMmc+Lq5GjlU4=
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.2 h1:eLven1YxRMkeiKu7IcMrPKE+gn8sGR1DqHbbshMEvWM=
github.com/containerd/containerd/v2 v2.3.2/go.mod h1:rHKGm3VW6wNrINb3x8mNT+w7qYXFVElTt/8HTuxVhD4=
github.com/containerd/containerd/v2 v2.3.3 h1:MUNBVVBTBpPll7KPh5GTvkC3cfG03PQLAHVdsUoue9k=
github.com/containerd/containerd/v2 v2.3.3/go.mod h1:rHKGm3VW6wNrINb3x8mNT+w7qYXFVElTt/8HTuxVhD4=
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/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
@@ -339,8 +339,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.5.3+incompatible h1:nbEFfz774vBwQ5KRYv7c/AghjReqnGISvrRhzjV0evs=
github.com/docker/cli v29.5.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v29.6.1+incompatible h1:oO7F4nn3Ovr/5TlfTUWFbMwBSS/B7Xs6Epv26gBrUP8=
github.com/docker/cli v29.6.1+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.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c=
@@ -371,14 +371,14 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.
github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ=
github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA=
github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU=
github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g=
github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98=
github.com/envoyproxy/go-control-plane/envoy v1.37.0 h1:u3riX6BoYRfF4Dr7dwSOroNfdSbEPe9Yyl09/B6wBrQ=
github.com/envoyproxy/go-control-plane/envoy v1.37.0/go.mod h1:DReE9MMrmecPy+YvQOAOHNYMALuowAnbjjEMkkWOi6A=
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI=
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4=
github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA=
github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMDjpqGAGacLe2T0ds=
github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0=
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=
@@ -410,8 +410,8 @@ github.com/github/go-spdx/v2 v2.7.0 h1:GzfXx4wFdlilARxmFRXW/mgUy3A4vSqZocCMFV6XF
github.com/github/go-spdx/v2 v2.7.0/go.mod h1:Ftc45YYG1WzpzwEPKRVm9Jv8vDqOrN4gWoCkK+bHer0=
github.com/gkampitakis/ciinfo v0.3.4 h1:5eBSibVuSMbb/H6Elc0IIEFbkzCJi3lm94n0+U7Z0KY=
github.com/gkampitakis/ciinfo v0.3.4/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo=
github.com/gkampitakis/go-snaps v0.5.22 h1:xg9omphRnbDnimMCl1KqznC4krlxOGpkB0vDSfX2P7M=
github.com/gkampitakis/go-snaps v0.5.22/go.mod h1:uy3lVzCCRRsAwYqSocyw5fY8xRLCYEfqoOJNxr8HonM=
github.com/gkampitakis/go-snaps v0.5.23 h1:okh5QR48zpUjpWtu65AtqxdCY8huJq+dEDuUzd1PuKg=
github.com/gkampitakis/go-snaps v0.5.23/go.mod h1:uy3lVzCCRRsAwYqSocyw5fY8xRLCYEfqoOJNxr8HonM=
github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4=
github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3q+ihjqxC9u0=
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
@@ -558,8 +558,8 @@ github.com/gookit/assert v0.1.1/go.mod h1:jS5bmIVQZTIwk42uXl4lyj4iaaxx32tqH16CFj
github.com/gookit/color v1.2.5/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg=
github.com/gookit/color v1.6.1 h1:KoTnDxJPRgrL0SoX0f8rCFg2zI0t4E3GZZBMo2nN8LU=
github.com/gookit/color v1.6.1/go.mod h1:9ACFc7/1IpHGBW8RwuDm/0YEnhg3dwwXpoMsmtyHfjs=
github.com/gpustack/gguf-parser-go v0.24.1 h1:nTYtL8HFK6ZhB90RKBu4oX2b3ZHpJLrMmKRfL9w9Cyc=
github.com/gpustack/gguf-parser-go v0.24.1/go.mod h1:y4TwTtDqFWTK+xvprOjRUh+dowgU2TKCX37vRKvGiZ0=
github.com/gpustack/gguf-parser-go v0.25.0 h1:1AMBhMKtI24nTtn588Bq53FqNiOvEw1x9Nb4HbRrThs=
github.com/gpustack/gguf-parser-go v0.25.0/go.mod h1:y4TwTtDqFWTK+xvprOjRUh+dowgU2TKCX37vRKvGiZ0=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 h1:vTCWu1wbdYo7PEZFem/rlr01+Un+wwVmI7wiegFdRLk=
github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72/go.mod h1:Vn+BBgKQHVQYdVQ4NZDICE1Brb+JfaONyDHr3q07oQc=
@@ -723,10 +723,10 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/moby/api v1.54.2 h1:wiat9QAhnDQjA7wk1kh/TqHz2I1uUA7M7t9SAl/JNXg=
github.com/moby/moby/api v1.54.2/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs=
github.com/moby/moby/client v0.4.1 h1:DMQgisVoMkmMs7fp3ROSdiBnoAu8+vo3GggFl06M/wY=
github.com/moby/moby/client v0.4.1/go.mod h1:z52C9O2POPOsnxZAy//WtKcQ32P+jT/NGeXu/7nfjGQ=
github.com/moby/moby/api v1.55.0 h1:2/sexvQyqIWS8pRSCFddBfpW2qE7vR7FCL+vN8pxwMc=
github.com/moby/moby/api v1.55.0/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs=
github.com/moby/moby/client v0.5.0 h1:5XhyPk2fuOWf6RlSFa3MkIIgDZkF25xToXW8Q/BH7cc=
github.com/moby/moby/client v0.5.0/go.mod h1:rcVpF8ncl9vo5gaIBdol6CnbEtSj1uxMvEV/UrykF/s=
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
@@ -786,8 +786,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.4.3 h1:GTRvJQutkOSftxIFD5xw9aepkYNuPWmVJpffdDPYVpY=
github.com/pelletier/go-toml/v2 v2.4.3/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pierrec/lz4/v4 v4.1.26 h1:GrpZw1gZttORinvzBdXPUXATeqlJjqUG/D87TKMnhjY=
github.com/pierrec/lz4/v4 v4.1.26/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4=
github.com/piprate/json-gold v0.7.0 h1:bEMirgA5y8Z2loTQfxyIFfY+EflxH1CTP6r/KIlcJNw=
@@ -998,8 +998,8 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/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/detectors/gcp v1.43.0 h1:62yY3dT7/ShwOxzA0RsKRgshBmfElKI4d/Myu2OxDFU=
go.opentelemetry.io/contrib/detectors/gcp v1.43.0/go.mod h1:RyaZMFY7yi1kAs45S6mbFGz8O8rqB0dTY14uzvG4LCs=
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=
@@ -1040,8 +1040,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto=
golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio=
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -1081,8 +1081,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1127,8 +1127,8 @@ golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1160,8 +1160,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1236,13 +1236,13 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.44.0 h1:0rLvDRCtNj0gZkyIXhCyOb2OAzEhLVqc4B+hrsBhrmc=
golang.org/x/term v0.44.0/go.mod h1:7ze4MdzUzLXpSAoFP1H0bOI9aXDqveSvatT5vKcFh2Y=
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1253,8 +1253,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE=
golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4=
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1315,8 +1315,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1431,10 +1431,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-20260414002931-afd174a4e478 h1:yQugLulqltosq0B/f8l4w9VryjV+N/5gcW0jQ3N8Qec=
google.golang.org/genproto/googleapis/api v0.0.0-20260414002931-afd174a4e478/go.mod h1:C6ADNqOxbgdUUeRTU+LCHDPB9ttAMCTff6auwCVa4uc=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/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=
@@ -1462,8 +1462,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.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE=
google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA=
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=
@@ -1513,20 +1513,20 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=
howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
modernc.org/cc/v4 v4.28.4 h1:Hd/4Es+MBj+/7hSdZaisNyu6bv3V0Dp2MdllyfqaH+c=
modernc.org/cc/v4 v4.28.4/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
modernc.org/ccgo/v4 v4.34.4 h1:OVnSOWQjVKOYkFxoHYB+qQmSHK5gqMqARM+K9DpR/Ws=
modernc.org/ccgo/v4 v4.34.4/go.mod h1:qdKqE8FNIYyysougB1RX9MxCzp5oJOcQXSobANJ4TuE=
modernc.org/cc/v4 v4.29.0 h1:CXgwL8cvxmyzBQZzbSl/6xFtMCryb6u8IOqDci39cgc=
modernc.org/cc/v4 v4.29.0/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI=
modernc.org/ccgo/v4 v4.34.6 h1:sBgfIwyN0TQ9C5hwIeuqyeAKyMWnbvj2fvpF4L11uzU=
modernc.org/ccgo/v4 v4.34.6/go.mod h1:SZ8YcN9NG7XVsQYdm6jYBvi8PQP1qi+kqB6OhjqI3Fk=
modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM=
modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/gc/v3 v3.1.3 h1:6QAplYyVO+KdPW3pGnqmJDUxtkec8ooEWvks/hhU3lc=
modernc.org/gc/v3 v3.1.3/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
modernc.org/gc/v3 v3.1.4 h1:2g65LGVSmFQrXeITAw97x7hCRvZFcyE1uDP+7Vng7JI=
modernc.org/gc/v3 v3.1.4/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.73.4 h1:+ra4Ui8ngyt8HDcO1FTDPWlkAh6yOdaO2yAoh8MddQA=
modernc.org/libc v1.73.4/go.mod h1:DXZ3eO8qMCNn2SnmTNCiC71nJ9Rcq3PsnpU6Vc4rWK8=
modernc.org/libc v1.74.1 h1:bdR4VTKFMC4966QSNZ05XLGI/VwzVa2kTUX51Dm0riQ=
modernc.org/libc v1.74.1/go.mod h1:uH4t5bOx3G3g9Xcmj10YKlTcVISlRDwv8VoQJG9n8Os=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
@@ -1535,8 +1535,8 @@ modernc.org/opt v0.2.0 h1:tGyef5ApycA7FSEOMraay9SaTk5zmbx7Tu+cJs4QKZg=
modernc.org/opt v0.2.0/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.53.0 h1:20WG8N9q4ji/dEqGk4uiI0c6OPjSeLTNYGFCc3+7c1M=
modernc.org/sqlite v1.53.0/go.mod h1:xoEpOIpGrgT48H5iiyt/YXPCZPEzlfmfFwtk8Lklw8s=
modernc.org/sqlite v1.54.0 h1:JCxR4qwkJvOaqAoYcgDoO25Nc+ROg6EJ2LfBVzdrgog=
modernc.org/sqlite v1.54.0/go.mod h1:4ntCLuNmnH8+GNqjka1wNg7KJd5/Hi5FYp8K+XQ7GZw=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
@@ -32,12 +32,15 @@ type parsedData struct {
pkg.ApkDBEntry
}
const maxApkDBFieldSize = 10 * 1024 * 1024
// parseApkDB parses packages from a given APK "installed" flat-file DB. For more
// information on specific fields, see https://wiki.alpinelinux.org/wiki/Apk_spec.
//
//nolint:funlen
func parseApkDB(ctx context.Context, resolver file.Resolver, env *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
scanner := bufio.NewScanner(reader)
scanner.Buffer(nil, maxApkDBFieldSize)
var errs error
var apks []parsedData
@@ -719,6 +719,25 @@ func Test_processChecksum(t *testing.T) {
}
}
func TestParseApkDBAllowsLargeFieldValues(t *testing.T) {
contents := strings.Join([]string{
"P:large-description",
"V:1.0-r0",
"A:x86_64",
"S:1",
"I:1",
"T:" + strings.Repeat("a", 70*1024),
"",
}, "\n")
reader := file.NewLocationReadCloser(file.NewLocation("large-installed-db"), io.NopCloser(strings.NewReader(contents)))
pkgs, _, err := parseApkDB(context.Background(), nil, new(generic.Environment), reader)
require.NoError(t, err)
require.Len(t, pkgs, 1)
assert.Equal(t, "large-description", pkgs[0].Name)
}
func Test_parseApkDB_expectedPkgNames(t *testing.T) {
tests := []struct {
fixture string
@@ -433,6 +433,16 @@ catalogers:
cpes:
- cpe:2.3:a:deno:deno:*:*:*:*:*:*:*:*
type: BinaryPkg
- method: glob
criteria:
- '**/bun'
packages:
- class: bun-binary
name: bun
purl: pkg:generic/bun
cpes:
- cpe:2.3:a:oven-sh:bun:*:*:*:*:*:*:*:*
type: BinaryPkg
- method: glob
criteria:
- '**/ghc*'
@@ -1565,6 +1565,50 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
Metadata: metadata("deno-binary"),
},
},
{
logicalFixture: "bun/0.5.9/linux-amd64",
expected: pkg.Package{
Name: "bun",
Version: "0.5.9",
Type: "binary",
PURL: "pkg:generic/bun@0.5.9",
Locations: locations("bun"),
Metadata: metadata("bun-binary"),
},
},
{
logicalFixture: "bun/1.0.0/linux-amd64",
expected: pkg.Package{
Name: "bun",
Version: "1.0.0",
Type: "binary",
PURL: "pkg:generic/bun@1.0.0",
Locations: locations("bun"),
Metadata: metadata("bun-binary"),
},
},
{
logicalFixture: "bun/1.1.0/linux-amd64",
expected: pkg.Package{
Name: "bun",
Version: "1.1.0",
Type: "binary",
PURL: "pkg:generic/bun@1.1.0",
Locations: locations("bun"),
Metadata: metadata("bun-binary"),
},
},
{
logicalFixture: "bun/1.3.5/linux-amd64",
expected: pkg.Package{
Name: "bun",
Version: "1.3.5",
Type: "binary",
PURL: "pkg:generic/bun@1.3.5",
Locations: locations("bun"),
Metadata: metadata("bun-binary"),
},
},
{
logicalFixture: "haskell-ghc/7.10.3/linux-amd64",
expected: pkg.Package{
+14
View File
@@ -611,6 +611,20 @@ func DefaultClassifiers() []binutils.Classifier {
PURL: mustPURL("pkg:generic/deno@version"),
CPEs: singleCPE("cpe:2.3:a:deno:deno:*:*:*:*:*:*:*:*", cpe.NVDDictionaryLookupSource),
},
{
Class: "bun-binary",
FileGlob: "**/bun",
EvidenceMatcher: binutils.MatchAny(
// bun 1.1.0
// Bun v1.0.0
m.FileContentsVersionMatcher(`(?m)[Bb]un v?(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
// bun-1.1.0
m.FileContentsVersionMatcher(`(?m)bun-(?P<version>[0-9]+\.[0-9]+\.[0-9]+)`),
),
Package: "bun",
PURL: mustPURL("pkg:generic/bun@version"),
CPEs: singleCPE("cpe:2.3:a:oven-sh:bun:*:*:*:*:*:*:*:*"),
},
{
Class: "haskell-ghc-binary",
FileGlob: "**/ghc*",
@@ -0,0 +1,12 @@
name: bun
offset: 1000000
length: 100
snippetSha256: 0000000000000000000000000000000000000000000000000000000000000001
fileSha256: 0000000000000000000000000000000000000000000000000000000000000001
### byte snippet to follow ###
]
Bun v0.5.9
bun-0.5.9
JavaScript runtime for developing, testing, and bundling
@@ -0,0 +1,12 @@
name: bun
offset: 1000000
length: 100
snippetSha256: 0000000000000000000000000000000000000000000000000000000000000002
fileSha256: 0000000000000000000000000000000000000000000000000000000000000002
### byte snippet to follow ###
]
Bun v1.0.0
bun-1.0.0
JavaScript runtime for developing, testing, and bundling
@@ -0,0 +1,12 @@
name: bun
offset: 1000000
length: 100
snippetSha256: 0000000000000000000000000000000000000000000000000000000000000003
fileSha256: 0000000000000000000000000000000000000000000000000000000000000003
### byte snippet to follow ###
]
Bun v1.1.0
bun-1.1.0
JavaScript runtime for developing, testing, and bundling
@@ -0,0 +1,12 @@
name: bun
offset: 1000000
length: 100
snippetSha256: 0000000000000000000000000000000000000000000000000000000000000004
fileSha256: 0000000000000000000000000000000000000000000000000000000000000004
### byte snippet to follow ###
]
Bun v1.3.5
bun-1.3.5
JavaScript runtime for developing, testing, and bundling
+1 -1
View File
@@ -156,7 +156,7 @@ func parseErlangString(data []byte, i *int) (erlangNode, error) {
}
if c == '\\' {
*i++
if len(data) >= *i {
if *i >= len(data) {
return node(nil), fmt.Errorf("invalid escape without closed string at %d", *i)
}
c = data[*i]
@@ -96,6 +96,11 @@ func Test_parseErlang(t *testing.T) {
{ foo, bar }
]}`,
},
{
name: "string with an escaped quote",
content: `
{escaped, ["a\"b"]}`,
},
}
for _, test := range tests {
@@ -112,3 +117,14 @@ func Test_parseErlang(t *testing.T) {
})
}
}
func Test_parseErlangString_escapedByte(t *testing.T) {
// a backslash escape mid-string used to always error out, since the bounds
// check at the escape site was inverted (len(data) >= *i is true for
// almost every position, not just an out-of-range one).
data := []byte(`"a\"b"`)
i := 0
got, err := parseErlangString(data, &i)
require.NoError(t, err)
assert.Equal(t, `a"b`, got.String())
}
+5 -2
View File
@@ -72,7 +72,7 @@ func (c *goModCataloger) parseGoModFile(ctx context.Context, resolver file.Resol
// only use go.mod packages NOT found in source analysis
goModPackages := c.createGoModPackages(ctx, resolver, modFile, sourceModules, reader, digests)
c.applyReplaceDirectives(ctx, resolver, modFile, goModPackages, reader, digests)
c.applyReplaceDirectives(ctx, resolver, modFile, sourceModules, goModPackages, reader, digests)
c.applyExcludeDirectives(modFile, goModPackages)
pkgs = c.assembleResults(catalogedModules, goModPackages)
@@ -365,8 +365,11 @@ func (c *goModCataloger) createGoModPackages(ctx context.Context, resolver file.
}
// applyReplaceDirectives processes replace directives from go.mod
func (c *goModCataloger) applyReplaceDirectives(ctx context.Context, resolver file.Resolver, modFile *modfile.File, goModPackages map[string]pkg.Package, reader file.LocationReadCloser, digests map[string]string) {
func (c *goModCataloger) applyReplaceDirectives(ctx context.Context, resolver file.Resolver, modFile *modfile.File, sourceModules map[string]*packages.Module, goModPackages map[string]pkg.Package, reader file.LocationReadCloser, digests map[string]string) {
for _, m := range modFile.Replace {
if sourceModules != nil && sourceModules[m.Old.Path] != nil {
continue
}
lics := c.licenseResolver.getLicenses(ctx, resolver, m.New.Path, m.New.Version)
var finalPath string
if !strings.HasPrefix(m.New.Path, ".") && !strings.HasPrefix(m.New.Path, "/") {
@@ -0,0 +1,44 @@
package golang
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
stereofile "github.com/anchore/stereoscope/pkg/file"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
"github.com/anchore/syft/syft/source"
"github.com/anchore/syft/syft/source/directorysource"
)
func Test_parseGoSource_replacedModulesAreNotDuplicated(t *testing.T) {
fixture := filepath.Join("testdata", "go-source-replacements")
s, err := directorysource.NewFromPath(fixture)
require.NoError(t, err)
resolver, err := s.FileResolver(source.AllLayersScope)
require.NoError(t, err)
modPath, err := filepath.Abs(filepath.Join(fixture, "go.mod"))
require.NoError(t, err)
contents, err := os.Open(modPath)
require.NoError(t, err)
t.Cleanup(func() { require.NoError(t, contents.Close()) })
reader := file.LocationReadCloser{
Location: file.NewVirtualLocationFromDirectory("go.mod", "go.mod", *stereofile.NewFileReference(stereofile.Path(modPath))),
ReadCloser: contents,
}
config := DefaultCatalogerConfig().WithUsePackagesLib(true).WithSearchRemoteLicenses(false)
pkgs, _, err := newGoModCataloger(config).parseGoModFile(pkgtest.Context(t), resolver, nil, reader)
require.NoError(t, err)
versions := make(map[string][]string)
for _, p := range pkgs {
versions[p.Name] = append(versions[p.Name], p.Version)
}
require.Equal(t, []string{"v1.5.2"}, versions["rsc.io/quote"])
require.Equal(t, []string{"v1.3.1"}, versions["rsc.io/sampler"])
}
+95 -14
View File
@@ -16,6 +16,10 @@ import (
// mainPackage is the import path the linker assigns to the binary's main package.
const mainPackage = "main"
// vendorPrefix is the import-path prefix carried by vendored packages (e.g. from `go mod vendor`, or the
// standard library's own vendored dependencies such as "vendor/golang.org/x/net/http2").
const vendorPrefix = "vendor/"
// binarySymbol represents a single function symbol extracted from a go binary's pclntab.
type binarySymbol struct {
// packagePath is the import path of the package that owns the symbol (e.g. "github.com/foo/bar/internal/baz")
@@ -52,10 +56,7 @@ func getSymbols(r io.ReaderAt) (syms []binarySymbol, err error) {
continue
}
seen[fn.Name] = struct{}{}
syms = append(syms, binarySymbol{
packagePath: fn.PackageName(),
name: fn.Name,
})
syms = append(syms, makeBinarySymbol(fn.Name, fn.PackageName()))
}
// debug/gosym only exposes top-level functions; functions that the compiler inlined into their
@@ -71,7 +72,7 @@ func getSymbols(r io.ReaderAt) (syms []binarySymbol, err error) {
continue
}
seen[name] = struct{}{}
syms = append(syms, binarySymbol{packagePath: pkgPath, name: name})
syms = append(syms, makeBinarySymbol(name, pkgPath))
}
return syms, nil
@@ -94,6 +95,55 @@ func packagePathFromSymbolName(name string) string {
return name[:slash+1+dot]
}
// makeBinarySymbol builds a binarySymbol, unescaping the %xx sequences the go linker introduces in the
// import-path portion of a symbol name (see unescapePackagePath). The local-symbol suffix (method and
// function names) is left untouched, so only the path prefix shared by packagePath and name is rewritten.
func makeBinarySymbol(name, pkgPath string) binarySymbol {
unescaped := unescapePackagePath(pkgPath)
if unescaped != pkgPath && strings.HasPrefix(name, pkgPath) {
name = unescaped + name[len(pkgPath):]
}
return binarySymbol{packagePath: unescaped, name: name}
}
// unescapePackagePath reverses the escaping cmd/internal/objabi.PathToPrefix applies to import paths in
// symbol names: bytes like '.' (at or after the final '/'), '%', '"', control bytes, and high bytes are
// written as lowercase "%xx". For example "gopkg.in/yaml.v2" is stored as "gopkg.in/yaml%2ev2", so this
// restores it before matching against the (unescaped) module paths from build info. A lone or malformed
// '%' sequence is left as-is.
func unescapePackagePath(path string) string {
if !strings.Contains(path, "%") {
return path
}
var b strings.Builder
b.Grow(len(path))
for i := 0; i < len(path); i++ {
if path[i] == '%' && i+2 < len(path) {
if hi, ok1 := unhex(path[i+1]); ok1 {
if lo, ok2 := unhex(path[i+2]); ok2 {
b.WriteByte(hi<<4 | lo)
i += 2
continue
}
}
}
b.WriteByte(path[i])
}
return b.String()
}
func unhex(c byte) (byte, bool) {
switch {
case c >= '0' && c <= '9':
return c - '0', true
case c >= 'a' && c <= 'f':
return c - 'a' + 10, true
case c >= 'A' && c <= 'F':
return c - 'A' + 10, true
}
return 0, false
}
// nameWithoutTypeArgs strips the type-argument portion from an instantiated generic symbol name, e.g.
// "foo/bar.Do[net/url.Values]" -> "foo/bar.Do". The slashes and dots inside the brackets would otherwise
// corrupt package-path derivation (yielding "foo/bar.Do[net" for the example above). Mirrors
@@ -273,8 +323,13 @@ func readPclntab(r io.ReaderAt) (pclntab []byte, textStart uint64, err error) {
// "(*T).M"). Symbols from the "main" package are attributed to the main module and keyed by the "main"
// import path the linker assigns. Standard-library symbols (which belong to no module) are collected
// separately and returned as the second value, grouped by import path, so they can be attached to the
// synthetic "stdlib" package. Compiler/runtime-internal symbols that are neither module-owned nor a
// recognizable stdlib import path are dropped.
// synthetic "stdlib" package. Vendored packages carry a "vendor/" import-path prefix: such symbols match
// both modules whose own path carries the prefix and modules without it (matched with the prefix trimmed),
// and the prefix is retained in the group key only when the owning module itself is named "vendor/...".
// Module-less vendored packages (the stdlib's own vendored dependencies, e.g.
// "vendor/golang.org/x/net/http2") are dropped: stdlib vulnerabilities seem to be reported against the public
// packages (e.g. "crypto/x509"), not the vendored internal copies. Compiler/runtime-internal symbols that
// are neither module-owned nor a recognizable stdlib import path are likewise dropped.
func moduleSymbols(symbols []binarySymbol, main *debug.Module, deps []*debug.Module) (byModule map[string]map[string][]string, stdlib map[string][]string) {
if len(symbols) == 0 {
return nil, nil
@@ -302,16 +357,17 @@ func moduleSymbols(symbols []binarySymbol, main *debug.Module, deps []*debug.Mod
attrPath = main.Path
}
var best string
for _, modPath := range modulePaths {
if len(modPath) > len(best) && (attrPath == modPath || strings.HasPrefix(attrPath, modPath+"/")) {
best = modPath
}
best := findBestMatch(modulePaths, attrPath)
// the vendor/ prefix is only retained when the owning module itself is named "vendor/...";
// in all other cases (non-vendored modules and vendored stdlib) the recorded import path is trimmed
if !strings.HasPrefix(best, vendorPrefix) {
importPath = strings.TrimPrefix(importPath, vendorPrefix)
}
local := localSymbolName(sym.name, importPath)
if best == "" {
if importPath != mainPackage && isStandardImportPath(importPath) {
if importPath != mainPackage && isStandardImportPath(importPath) { // drop stdlib vendored packages
stdlib[importPath] = append(stdlib[importPath], local)
}
continue
@@ -333,11 +389,36 @@ func moduleSymbols(symbols []binarySymbol, main *debug.Module, deps []*debug.Mod
return results, stdlib
}
// findBestMatch returns the module path that owns the given package path taking into account vendor/ prefixes: a vendor/ import path
// will take precedence and continue to match, non-vendored imports will match against their vendored equivalent
func findBestMatch(modulePaths []string, importPath string) string {
trimmedPath, trimmed := strings.CutPrefix(importPath, vendorPrefix)
candidatePaths := []string{importPath, trimmedPath}
if !trimmed {
candidatePaths = candidatePaths[:1]
}
var best string
for _, candidate := range candidatePaths {
for _, modPath := range modulePaths {
// the prefix must end at a path-segment boundary in candidate, so that e.g. the module
// "github.com/foo/bar" matches the package "github.com/foo/bar/baz" but not "github.com/foo/barbaz"
if len(modPath) > len(best) && strings.HasPrefix(candidate, modPath) && (candidate == modPath || candidate[len(modPath)] == '/') {
best = modPath
}
}
}
return best
}
// localSymbolName strips the owning package's import path prefix from a fully qualified symbol name, e.g.
// "github.com/foo/bar.(*T).M" with import path "github.com/foo/bar" becomes "(*T).M". The name is returned
// unchanged when it does not carry the expected prefix.
func localSymbolName(name, importPath string) string {
if importPath != "" && strings.HasPrefix(name, importPath+".") {
if !strings.HasPrefix(importPath, vendorPrefix) {
name = strings.TrimPrefix(name, vendorPrefix)
}
if len(importPath) < len(name) && strings.HasPrefix(name, importPath) && name[len(importPath)] == '.' {
return name[len(importPath)+1:]
}
return name
+114
View File
@@ -16,6 +16,8 @@ func Test_moduleSymbols(t *testing.T) {
deps := []*debug.Module{
{Path: "github.com/foo/bar"},
{Path: "github.com/foo/bar/v2"},
{Path: "vendor/github.com/vendored/mod"},
{Path: "github.com/vendored/mod"},
nil,
}
@@ -74,6 +76,63 @@ func Test_moduleSymbols(t *testing.T) {
"runtime": {"main"},
},
},
{
name: "vendored packages match non-vendored modules and are recorded under the canonical import path",
symbols: []binarySymbol{
{packagePath: "vendor/github.com/foo/bar", name: "vendor/github.com/foo/bar.Parse"},
{packagePath: "vendor/github.com/foo/bar/internal/util", name: "vendor/github.com/foo/bar/internal/util.(*Helper).Do"},
},
expected: map[string]map[string][]string{
"github.com/foo/bar": {
"github.com/foo/bar": {"Parse"},
"github.com/foo/bar/internal/util": {"(*Helper).Do"},
},
},
},
{
name: "stdlib-vendored packages are dropped",
symbols: []binarySymbol{
{packagePath: "vendor/golang.org/x/net/http2", name: "vendor/golang.org/x/net/http2.(*Framer).ReadFrame"},
},
expected: map[string]map[string][]string{},
},
{
name: "modules whose own path carries the vendor/ prefix match exactly and win over the trimmed match",
symbols: []binarySymbol{
{packagePath: "vendor/github.com/vendored/mod", name: "vendor/github.com/vendored/mod.Run"},
{packagePath: "github.com/vendored/mod", name: "github.com/vendored/mod.Run"},
},
expected: map[string]map[string][]string{
"vendor/github.com/vendored/mod": {
"vendor/github.com/vendored/mod": {"Run"},
},
"github.com/vendored/mod": {
"github.com/vendored/mod": {"Run"},
},
},
},
{
name: "vendored and unvendored symbols for the same package are merged and deduplicated under the canonical import path",
symbols: []binarySymbol{
{packagePath: "github.com/foo/bar", name: "github.com/foo/bar.Parse"},
{packagePath: "vendor/github.com/foo/bar", name: "vendor/github.com/foo/bar.Parse"},
},
expected: map[string]map[string][]string{
"github.com/foo/bar": {
"github.com/foo/bar": {"Parse"},
},
},
},
{
// "github.com/foo/barbaz" shares a string prefix with the "github.com/foo/bar" module but not a
// path-segment boundary, so it must not be attributed to it (and, having a dotted first element,
// it is not a stdlib path either — it is dropped)
name: "module paths only match the package path at a path-segment boundary",
symbols: []binarySymbol{
{packagePath: "github.com/foo/barbaz", name: "github.com/foo/barbaz.Parse"},
},
expected: map[string]map[string][]string{},
},
{
name: "duplicate symbols are deduplicated",
symbols: []binarySymbol{
@@ -97,6 +156,58 @@ func Test_moduleSymbols(t *testing.T) {
}
}
func Test_escapedImportPathAttribution(t *testing.T) {
// the go linker escapes the '.' in the last path element, so "gopkg.in/yaml.v2" appears in the symbol
// table as "gopkg.in/yaml%2ev2". attribution must still land these under the unescaped module path.
mainModule := &debug.Module{Path: "github.com/someorg/somecli"}
deps := []*debug.Module{{Path: "gopkg.in/yaml.v2"}}
symbols := []binarySymbol{
makeBinarySymbol("gopkg.in/yaml%2ev2.(*decoder).alias", "gopkg.in/yaml%2ev2"),
makeBinarySymbol("gopkg.in/yaml%2ev2.(*TypeError).Error", "gopkg.in/yaml%2ev2"),
}
gotByModule, gotStdlib := moduleSymbols(symbols, mainModule, deps)
assert.Nil(t, gotStdlib)
assert.Equal(t, map[string]map[string][]string{
"gopkg.in/yaml.v2": {
"gopkg.in/yaml.v2": {"(*TypeError).Error", "(*decoder).alias"},
},
}, gotByModule)
}
func Test_unescapePackagePath(t *testing.T) {
tests := []struct {
input string
expected string
}{
{"gopkg.in/yaml%2ev2", "gopkg.in/yaml.v2"},
{"foo%25bar", "foo%bar"},
{"foo%22bar", "foo\"bar"},
// no escapes: unchanged
{"github.com/foo/bar", "github.com/foo/bar"},
{"", ""},
// malformed sequences are left as-is
{"foo%2", "foo%2"},
{"foo%zz", "foo%zz"},
{"foo%", "foo%"},
// uppercase hex is accepted too
{"foo%2Ebar", "foo.bar"},
}
for _, tt := range tests {
t.Run(tt.input, func(t *testing.T) {
assert.Equal(t, tt.expected, unescapePackagePath(tt.input))
})
}
}
func Test_makeBinarySymbol(t *testing.T) {
// only the import-path prefix is unescaped; the local-symbol suffix is preserved verbatim
sym := makeBinarySymbol("gopkg.in/yaml%2ev2.(*decoder).alias", "gopkg.in/yaml%2ev2")
assert.Equal(t, "gopkg.in/yaml.v2", sym.packagePath)
assert.Equal(t, "gopkg.in/yaml.v2.(*decoder).alias", sym.name)
}
func Test_localSymbolName(t *testing.T) {
tests := []struct {
name string
@@ -239,6 +350,9 @@ func Test_packagePathFromSymbolName(t *testing.T) {
// module paths that begin with "go." are not compiler-generated
{"go.uber.org/zap.(*Logger).Info", "go.uber.org/zap"},
{"go.opentelemetry.io/otel.Tracer", "go.opentelemetry.io/otel"},
// vendored packages retain their "vendor/" import-path prefix in symbol names
{"vendor/golang.org/x/net/http2.(*Framer).ReadFrame", "vendor/golang.org/x/net/http2"},
{"vendor/github.com/foo/bar.Parse", "vendor/github.com/foo/bar"},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
@@ -0,0 +1,15 @@
module example.com/repro
go 1.23
require rsc.io/quote v1.5.1
require (
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
rsc.io/sampler v1.3.0 // indirect
)
replace (
rsc.io/quote => rsc.io/quote v1.5.2
rsc.io/sampler => rsc.io/sampler v1.3.1
)
@@ -0,0 +1,6 @@
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
rsc.io/sampler v1.3.1 h1:F0c3J2nQCdk9ODsNhU3sElnvPIxM/xV1c/qZuAeZmac=
rsc.io/sampler v1.3.1/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
@@ -0,0 +1,11 @@
package main
import (
"fmt"
"rsc.io/quote"
)
func main() {
fmt.Println(quote.Hello())
}
@@ -7,6 +7,9 @@
"chainguard.dev/apko": [
"cpe:2.3:a:chainguard:apko:*:*:*:*:*:go:*:*"
],
"github.com/Azure/go-ntlmssp": [
"cpe:2.3:a:microsoft:go-ntlmssp:*:*:*:*:*:go:*:*"
],
"github.com/ClickHouse/ch-go": [
"cpe:2.3:a:clickhouse:ch:*:*:*:*:*:go:*:*"
],
@@ -223,6 +226,9 @@
"github.com/xddxdd/bird-lg-go": [
"cpe:2.3:a:xddxdd:bird-lg-go:*:*:*:*:*:go:*:*"
],
"github.com/xuri/excelize/v2": [
"cpe:2.3:a:excelize:excelize:*:*:*:*:*:go:*:*"
],
"github.com/yuin/goldmark": [
"cpe:2.3:a:yuin:goldmark:*:*:*:*:*:go:*:*"
],
@@ -2349,6 +2355,9 @@
"@apollosproject/data-connector-rock": [
"cpe:2.3:a:apollosapp:data-connector-rock:*:*:*:*:*:node.js:*:*"
],
"@appium/base-driver": [
"cpe:2.3:a:appium:appium\\/base-driver:*:*:*:*:*:node.js:*:*"
],
"@appium/support": [
"cpe:2.3:a:appium:appium\\/support:*:*:*:*:*:node.js:*:*"
],
@@ -2403,6 +2412,9 @@
"@better-auth/oauth-provider": [
"cpe:2.3:a:better-auth:better-auth\\/oauth-provider:*:*:*:*:*:node.js:*:*"
],
"@better-auth/sso": [
"cpe:2.3:a:better-auth:better-auth\\/sso:*:*:*:*:*:node.js:*:*"
],
"@braintree/sanitize-url": [
"cpe:2.3:a:paypal:braintree\\/sanitize-url:*:*:*:*:*:node.js:*:*"
],
@@ -2616,6 +2628,9 @@
"@octokit/webhooks": [
"cpe:2.3:a:octokit:webhooks:*:*:*:*:*:node.js:*:*"
],
"@openclaw/feishu": [
"cpe:2.3:a:openclaw:openclaw\\/feishu:*:*:*:*:*:node.js:*:*"
],
"@openclaw/voice-call": [
"cpe:2.3:a:openclaw:openclaw\\/voice-call:*:*:*:*:*:node.js:*:*"
],
@@ -3086,6 +3101,9 @@
"cli": [
"cpe:2.3:a:cli_project:cli:*:*:*:*:*:node.js:*:*"
],
"client-certificate-auth": [
"cpe:2.3:a:tgies:client-certificate-auth:*:*:*:*:*:node.js:*:*"
],
"closure-compiler-stream": [
"cpe:2.3:a:closure-compiler-stream_project:closure-compiler-stream:*:*:*:*:*:node.js:*:*"
],
@@ -5752,6 +5770,9 @@
"ssrf-agent": [
"cpe:2.3:a:ssrf-agent_project:ssrf-agent:*:*:*:*:*:node.js:*:*"
],
"ssrfcheck": [
"cpe:2.3:a:felippe-regazio:ssrf_check:*:*:*:*:*:node.js:*:*"
],
"ssri": [
"cpe:2.3:a:ssri_project:ssri:*:*:*:*:*:node.js:*:*"
],
@@ -6819,6 +6840,9 @@
"pyanyapi": [
"cpe:2.3:a:pyanyapi_project:pyanyapi:*:*:*:*:*:*:*:*"
],
"pyasn1": [
"cpe:2.3:a:pyasn1:pyasn1:*:*:*:*:*:python:*:*"
],
"pybluemonday": [
"cpe:2.3:a:python:pybluemonday:*:*:*:*:*:*:*:*"
],
@@ -6978,6 +7002,9 @@
"sqlparse": [
"cpe:2.3:a:sqlparse_project:sqlparse:*:*:*:*:*:python:*:*"
],
"stanza": [
"cpe:2.3:a:stanford:stanza:*:*:*:*:*:python:*:*"
],
"starlette": [
"cpe:2.3:a:encode:starlette:*:*:*:*:*:python:*:*"
],
@@ -7690,6 +7717,12 @@
"bzip2": [
"cpe:2.3:a:bzip2_project:bzip2:*:*:*:*:*:rust:*:*"
],
"c2pa": [
"cpe:2.3:a:adobe:c2pa:*:*:*:*:*:rust:*:*"
],
"c2patool": [
"cpe:2.3:a:adobe:c2patool:*:*:*:*:*:*:*:*"
],
"cache": [
"cpe:2.3:a:cache_project:cache:*:*:*:*:*:rust:*:*"
],
@@ -8530,6 +8563,9 @@
"add-subtitle": [
"cpe:2.3:a:viitorcloud:add_subtitle:*:*:*:*:*:wordpress:*:*"
],
"add-svg-support-for-media-uploader-inventivo": [
"cpe:2.3:a:inventivo:inventivo:*:*:*:*:*:wordpress:*:*"
],
"add-to-any": [
"cpe:2.3:a:addtoany:addtoany_share_buttons:*:*:*:*:*:wordpress:*:*"
],
@@ -8720,6 +8756,9 @@
"advanced-recent-posts": [
"cpe:2.3:a:advanced_recent_posts_project:advanced_recent_posts:*:*:*:*:*:wordpress:*:*"
],
"advanced-schedule-posts": [
"cpe:2.3:a:hijiriworld:advanced_schedule_posts:*:*:*:*:*:wordpress:*:*"
],
"advanced-sermons": [
"cpe:2.3:a:wpcodeus:advanced_sermons:*:*:*:*:*:wordpress:*:*"
],
@@ -8784,6 +8823,7 @@
"cpe:2.3:a:ai_contact_us_form_project:ai_contact_us_form:*:*:*:*:*:wordpress:*:*"
],
"ai-engine": [
"cpe:2.3:a:jordymeow:ai_engine:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:meowapps:ai_engine:*:*:*:*:*:wordpress:*:*"
],
"ai-image-alt-text-generator-for-wp": [
@@ -9175,7 +9215,8 @@
"cpe:2.3:a:article_directory_project:article_directory:*:*:*:*:*:wordpress:*:*"
],
"article-directory-redux": [
"cpe:2.3:a:icontrolwp:article_directory_redux:*:*:*:*:*:wordpress:*:*"
"cpe:2.3:a:icontrolwp:article_directory_redux:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:icontrolwp:icontrolwp:*:*:*:*:*:wordpress:*:*"
],
"article2pdf": [
"cpe:2.3:a:article2pdf_project:article2pdf:*:*:*:*:*:wordpress:*:*"
@@ -10993,6 +11034,9 @@
"cost-calculator-builder": [
"cpe:2.3:a:stylemixthemes:cost_calculator_builder:*:*:*:*:free:wordpress:*:*"
],
"coub": [
"cpe:2.3:a:chartscss:coub:*:*:*:*:*:wordpress:*:*"
],
"countdown-block": [
"cpe:2.3:a:wpdeveloper:countdown_block:*:*:*:*:*:wordpress:*:*"
],
@@ -12122,9 +12166,12 @@
"cpe:2.3:a:mandsconsulting:email_before_download:*:*:*:*:*:wordpress:*:*"
],
"email-encoder-bundle": [
"cpe:2.3:a:jannisthuemmig:email_encoder:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:onlineoptimisation:email_encoder:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:wp-webhooks:email_encoder:*:*:*:*:*:wordpress:*:*"
],
"email-keep": [
"cpe:2.3:a:intricateweb:email_keep:*:*:*:*:*:wordpress:*:*"
],
"email-log": [
"cpe:2.3:a:email_log_project:email_log:*:*:*:*:*:wordpress:*:*"
],
@@ -13104,6 +13151,9 @@
"game-server-status": [
"cpe:2.3:a:game-server-status_project:game-server-status:*:*:*:*:*:wordpress:*:*"
],
"game-users-share-buttons": [
"cpe:2.3:a:gameusers:game_users_share_button:*:*:*:*:*:wordpress:*:*"
],
"gamepress": [
"cpe:2.3:a:gamepress_project:gamepress:*:*:*:*:*:wordpress:*:*"
],
@@ -13113,6 +13163,9 @@
"gamipress-link": [
"cpe:2.3:a:gamipress:gamipress_-_link:*:*:*:*:*:wordpress:*:*"
],
"gamipress-reset-user": [
"cpe:2.3:a:gamipress:gamipress_-_reset_user:*:*:*:*:*:wordpress:*:*"
],
"garden-gnome-package": [
"cpe:2.3:a:ggnome:garden_gnome_package:*:*:*:*:*:wordpress:*:*"
],
@@ -13197,6 +13250,9 @@
"gestpay-for-woocommerce": [
"cpe:2.3:a:fabrick:gestpay_for_woocommerce:*:*:*:*:*:wordpress:*:*"
],
"get-bookings-wp": [
"cpe:2.3:a:istmoplugins:get_bookings_wp:*:*:*:*:*:wordpress:*:*"
],
"get-custom-field-values": [
"cpe:2.3:a:get_custom_field_values_project:get_custom_field_values:*:*:*:*:*:wordpress:*:*"
],
@@ -13227,6 +13283,15 @@
"gf-custom-style": [
"cpe:2.3:a:alefypimentel:gf_custom_style:*:*:*:*:*:wordpress:*:*"
],
"gf-hubspot": [
"cpe:2.3:a:crmperks:wp_gravity_forms_hubspot:*:*:*:*:*:wordpress:*:*"
],
"gf-insightly": [
"cpe:2.3:a:crmperks:wp_gravity_forms_insightly:*:*:*:*:*:wordpress:*:*"
],
"gf-salesforce-crmperks": [
"cpe:2.3:a:crmperks:wp_gravity_forms_salesforce:*:*:*:*:*:wordpress:*:*"
],
"gf-zoho": [
"cpe:2.3:a:crmperks:wp_gravity_forms_zoho_crm_and_bigin:*:*:*:*:*:wordpress:*:*"
],
@@ -13659,6 +13724,9 @@
"heureka": [
"cpe:2.3:a:heureka:heureka:*:*:*:*:*:wordpress:*:*"
],
"hide-links": [
"cpe:2.3:a:avovkdesign:hide_links:*:*:*:*:*:wordpress:*:*"
],
"hide-my-wp": [
"cpe:2.3:a:wpplugins:hide_my_wp_ghost:*:*:*:*:*:wordpress:*:*"
],
@@ -13683,6 +13751,9 @@
"hkdev-maintenance-mode": [
"cpe:2.3:a:helderk:maintenance_mode:*:*:*:*:*:wordpress:*:*"
],
"hmapsprem": [
"cpe:2.3:a:heroplugins:hero_maps_premium:*:*:*:*:*:wordpress:*:*"
],
"hms-testimonials": [
"cpe:2.3:a:hitmyserver:hms_testimonials:*:*:*:*:*:wordpress:*:*"
],
@@ -13831,6 +13902,9 @@
"ibtana-visual-editor": [
"cpe:2.3:a:vowelweb:ibtana:*:*:*:*:*:wordpress:*:*"
],
"ibuildapp": [
"cpe:2.3:a:ibuildapp:ibuildapp:*:*:*:*:*:wordpress:*:*"
],
"icegram": [
"cpe:2.3:a:icegram:icegram_engage:*:*:*:*:*:wordpress:*:*"
],
@@ -14054,6 +14128,9 @@
"cpe:2.3:a:infusionsoft_project:infusionsoft:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:katz:infusionsoft_gravity_forms:*:*:*:*:*:wordpress:*:*"
],
"infusionsoft-official-opt-in-forms": [
"cpe:2.3:a:keap:keap_official_opt_in_forms:*:*:*:*:*:wordpress:*:*"
],
"inline-google-spreadsheet-viewer": [
"cpe:2.3:a:inline_google_spreadsheet_viewer_project:inline_google_spreadsheet_viewer:*:*:*:*:*:wordpress:*:*"
],
@@ -14154,6 +14231,9 @@
"intelly-related-posts": [
"cpe:2.3:a:data443:inline_related_posts:*:*:*:*:*:wordpress:*:*"
],
"interact-quiz-embed": [
"cpe:2.3:a:tryinteract:embed_a_quiz_on_your_site:*:*:*:*:*:wordpress:*:*"
],
"interactive-3d-flipbook-powered-physics-engine": [
"cpe:2.3:a:3dflipbook:3d_flipbook:*:*:*:*:*:wordpress:*:*"
],
@@ -14390,6 +14470,9 @@
"jvm-rich-text-icons": [
"cpe:2.3:a:jorisvm:jvm_gutenberg_rich_text_icons:*:*:*:*:*:wordpress:*:*"
],
"jwp-a11y": [
"cpe:2.3:a:jidaikobo:jwp-a11y:*:*:*:*:*:wordpress:*:*"
],
"kadence-blocks": [
"cpe:2.3:a:kadencewp:gutenberg_blocks_with_ai:*:*:*:*:*:wordpress:*:*"
],
@@ -14879,6 +14962,9 @@
"logo-slider-wp": [
"cpe:2.3:a:logichunt:logo_slider:*:*:*:*:*:wordpress:*:*"
],
"logs-de-connexion": [
"cpe:2.3:a:floriansimunek:connexion_logs:*:*:*:*:*:wordpress:*:*"
],
"logwpmail": [
"cpe:2.3:a:premierethemes:log_wp_mail:*:*:*:*:*:wordpress:*:*"
],
@@ -14951,6 +15037,9 @@
"cpe:2.3:a:custom_popup_builder_project:custom_popup_builder:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:popup_\\|_custom_popup_builder_project:popup_\\|_custom_popup_builder:*:*:*:*:*:wordpress:*:*"
],
"magayo-lottery-results": [
"cpe:2.3:a:magayo:magayo_lottery_results:*:*:*:*:*:wordpress:*:*"
],
"magazine-blocks": [
"cpe:2.3:a:themegrill:magazine_blocks:*:*:*:*:*:wordpress:*:*"
],
@@ -15147,7 +15236,8 @@
"cpe:2.3:a:master-addons:master_addons:*:*:*:*:*:wordpress:*:*"
],
"master-slider": [
"cpe:2.3:a:averta:master_slider:*:*:*:*:*:wordpress:*:*"
"cpe:2.3:a:averta:master_slider:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:averta:master_slider:*:*:*:*:free:wordpress:*:*"
],
"masterstudy-lms-learning-management-system": [
"cpe:2.3:a:stylemixthemes:masterstudy_lms:*:*:*:*:*:wordpress:*:*"
@@ -15167,6 +15257,9 @@
"materialis-companion": [
"cpe:2.3:a:extendthemes:materialis_companion:*:*:*:*:*:wordpress:*:*"
],
"matomo": [
"cpe:2.3:a:matomo:matomo:*:*:*:*:*:wordpress:*:*"
],
"matrix-pre-loader": [
"cpe:2.3:a:nkb-bd:preloader_matrix:*:*:*:*:*:wordpress:*:*"
],
@@ -15185,6 +15278,9 @@
"mdc-youtube-downloader": [
"cpe:2.3:a:mdc_youtube_downloader_project:mdc_youtube_downloader:*:*:*:*:*:wordpress:*:*"
],
"media-alt-renamer": [
"cpe:2.3:a:jordymeow:media_alt_renamer:*:*:*:*:*:wordpress:*:*"
],
"media-downloader": [
"cpe:2.3:a:media_downloader_project:media_downloader:*:*:*:*:*:wordpress:*:*"
],
@@ -15508,7 +15604,7 @@
"cpe:2.3:a:motor_racing_league_project:motor_racing_league:*:*:*:*:*:wordpress:*:*"
],
"motors-car-dealership-classified-listings": [
"cpe:2.3:a:stylemixthemes:motors_-_car_dealer\\,_classifieds_\\\u0026_listing:*:*:*:*:*:wordpress:*:*"
"cpe:2.3:a:stylemixthemes:motors_-_car_dealer\\,_classifieds_\\\u0026_listing:*:*:*:*:starter:wordpress:*:*"
],
"mousewheel-smooth-scroll": [
"cpe:2.3:a:mousewheel_smooth_scroll_project:mousewheel_smooth_scroll:*:*:*:*:*:wordpress:*:*"
@@ -15516,6 +15612,9 @@
"move-addons": [
"cpe:2.3:a:moveaddons:move_addons_for_elementor:*:*:*:*:*:wordpress:*:*"
],
"movie-database": [
"cpe:2.3:a:heimkino-praxis:movie_database:*:*:*:*:*:wordpress:*:*"
],
"movies": [
"cpe:2.3:a:movies_project:movies:*:*:*:*:*:wordpress:*:*"
],
@@ -16208,6 +16307,7 @@
"cpe:2.3:a:benhuson:page_parts:*:*:*:*:*:wordpress:*:*"
],
"page-scroll-to-id": [
"cpe:2.3:a:malihu:page_scroll_to_id:*:*:*:*:*:wordpress:*:*",
"cpe:2.3:a:page_scroll_to_id_project:page_scroll_to_id:*:*:*:*:*:wordpress:*:*"
],
"page-views-count": [
@@ -16641,6 +16741,9 @@
"popup-zyrex": [
"cpe:2.3:a:zyrex:popup:*:*:*:*:*:wordpress:*:*"
],
"popup4phone": [
"cpe:2.3:a:ivanweb:popup4phone:*:*:*:*:*:wordpress:*:*"
],
"popupally": [
"cpe:2.3:a:accessally:popupally:*:*:*:*:*:wordpress:*:*"
],
@@ -16654,6 +16757,9 @@
"portfolio": [
"cpe:2.3:a:bestwebsoft:portfolio:*:*:*:*:*:wordpress:*:*"
],
"portfolio-and-projects": [
"cpe:2.3:a:essentialplugin:portfolio_and_projects:*:*:*:*:*:wordpress:*:*"
],
"portfolio-by-lisa-westlund": [
"cpe:2.3:a:portfolio_project:portfolio:*:*:*:*:*:wordpress:*:*"
],
@@ -17441,6 +17547,9 @@
"responsive-css-editor": [
"cpe:2.3:a:wpwox:responsive_css_editor:*:*:*:*:*:wordpress:*:*"
],
"responsive-filterable-portfolio": [
"cpe:2.3:a:i13websolution:responsive_filterable_portfolio:*:*:*:*:*:wordpress:*:*"
],
"responsive-food-and-drink-menu": [
"cpe:2.3:a:corporatezen:responsive_food_and_drink_menu:*:*:*:*:*:wordpress:*:*"
],
@@ -17470,6 +17579,12 @@
"responsive-vector-maps": [
"cpe:2.3:a:thinkupthemes:responsive_vector_maps:*:*:*:*:*:wordpress:*:*"
],
"responsive-video-embed": [
"cpe:2.3:a:lepileppanen:responsive_video_embed:*:*:*:*:*:wordpress:*:*"
],
"rest-api-to-miniprogram": [
"cpe:2.3:a:jianbo:rest_api_to_miniprogram:*:*:*:*:*:wordpress:*:*"
],
"restaurant-cafe-addon-for-elementor": [
"cpe:2.3:a:nicheaddons:restaurant_\\\u0026_cafe_addon_for_elementor:*:*:*:*:*:wordpress:*:*"
],
@@ -17655,6 +17770,9 @@
"safe-svg": [
"cpe:2.3:a:10up:safe_svg:*:*:*:*:*:wordpress:*:*"
],
"safetymails-forms": [
"cpe:2.3:a:henriquerodrigues:safetyforms:*:*:*:*:*:wordpress:*:*"
],
"sagepay-server-gateway-for-woocommerce": [
"cpe:2.3:a:patsatech:sagepay_server_gateway_for_woocommerce:*:*:*:*:*:wordpress:*:*"
],
@@ -18545,6 +18663,9 @@
"slideshow-se": [
"cpe:2.3:a:slideshow_se_project:slideshow_se:*:*:*:*:*:wordpress:*:*"
],
"slingblocks": [
"cpe:2.3:a:funnelkit:slingblocks:*:*:*:*:*:wordpress:*:*"
],
"small-package-quotes-fedex-edition": [
"cpe:2.3:a:eniture:small_package_quotes:*:*:*:*:fedex:wordpress:*:*"
],
@@ -18837,6 +18958,9 @@
"sportspress": [
"cpe:2.3:a:themeboy:sportspress:*:*:*:*:*:wordpress:*:*"
],
"spotbot": [
"cpe:2.3:a:jakehelbig:spotbot:*:*:*:*:*:wordpress:*:*"
],
"spotify-play-button-for-wordpress": [
"cpe:2.3:a:followmedarling:spotify-play-button-for-wordpress:*:*:*:*:*:wordpress:*:*"
],
@@ -19939,6 +20063,9 @@
"user-login-log": [
"cpe:2.3:a:intechnosoftware:user_login_log:*:*:*:*:*:wordpress:*:*"
],
"user-messages": [
"cpe:2.3:a:marvinlabs:user_messages:*:*:*:*:*:wordpress:*:*"
],
"user-meta": [
"cpe:2.3:a:user-meta:user_meta_user_profile_builder_and_user_management:*:*:*:*:*:wordpress:*:*"
],
@@ -19962,6 +20089,9 @@
"user-role": [
"cpe:2.3:a:bestwebsoft:user_role:*:*:*:*:*:wordpress:*:*"
],
"user-shortcodes-plus": [
"cpe:2.3:a:kylebjohnson:user_shortcodes_plus:*:*:*:*:*:wordpress:*:*"
],
"user-spam-remover": [
"cpe:2.3:a:joelhardi:user_spam_remover:*:*:*:*:*:wordpress:*:*"
],
@@ -20574,6 +20704,9 @@
"woo-gutenberg-products-block": [
"cpe:2.3:a:automattic:woocommerce_blocks:*:*:*:*:*:wordpress:*:*"
],
"woo-mailerlite": [
"cpe:2.3:a:mailerlite:mailerlite:*:*:*:*:*:wordpress:*:*"
],
"woo-moneybird": [
"cpe:2.3:a:techastha:integration_of_moneybird_for_woocommerce:*:*:*:*:*:wordpress:*:*"
],
@@ -20923,6 +21056,9 @@
"wordpress-users": [
"cpe:2.3:a:jonathonkemp:wordpress_users:*:*:*:*:*:wordpress:*:*"
],
"work-the-flow-file-upload": [
"cpe:2.3:a:lyntonreed:work_the_flow_file_upload:*:*:*:*:*:wordpress:*:*"
],
"workreap": [
"cpe:2.3:a:amentotech:workreap:*:*:*:*:*:wordpress:*:*"
],
@@ -21154,6 +21290,9 @@
"wp-consultant": [
"cpe:2.3:a:wp_consultant_project:wp_consultant:*:*:-:*:-:wordpress:*:*"
],
"wp-contact-form": [
"cpe:2.3:a:ftwr:wp_contact_form:*:*:*:*:*:wordpress:*:*"
],
"wp-contact-slider": [
"cpe:2.3:a:wpexperts:wp_contact_slider:*:*:*:*:*:wordpress:*:*"
],
@@ -21452,6 +21591,9 @@
"wp-fountain": [
"cpe:2.3:a:wp_fountain_project:wp_fountain:*:*:*:*:*:wordpress:*:*"
],
"wp-front-end-login-and-register": [
"cpe:2.3:a:hellomohsinkhan:wp_front-end_login_and_register:*:*:*:*:*:wordpress:*:*"
],
"wp-front-end-profile": [
"cpe:2.3:a:wp_front_end_profile_project:wp_front_end_profile:*:*:*:*:*:wordpress:*:*"
],
@@ -21904,6 +22046,9 @@
"wp-product-gallery-lite": [
"cpe:2.3:a:accesspressthemes:wp_product_gallery_lite:*:*:*:*:*:wordpress:*:*"
],
"wp-programmmanager": [
"cpe:2.3:a:mantus667:wp-pmanager:*:*:*:*:*:wordpress:*:*"
],
"wp-propagator": [
"cpe:2.3:a:widgilabs:plugin_propagator:*:*:*:*:*:wordpress:*:*"
],
@@ -23112,6 +23257,9 @@
"empowerwp": [
"cpe:2.3:a:extendthemes:empowerwp:*:*:*:*:*:wordpress:*:*"
],
"enfold": [
"cpe:2.3:a:kriesi:enfold:*:*:*:*:*:wordpress:*:*"
],
"enlighten": [
"cpe:2.3:a:accesspressthemes:enlighten:*:*:*:*:*:wordpress:*:*"
],
+36 -13
View File
@@ -1,26 +1,49 @@
package cpegenerate
import "github.com/anchore/syft/syft/pkg"
import (
"net/url"
"strings"
"github.com/anchore/syft/syft/pkg"
)
func candidateVendorsForRPM(p pkg.Package) fieldCandidateSet {
vendors := newFieldCandidateSet()
var vendor string
switch m := p.Metadata.(type) {
case pkg.RpmDBEntry:
if m.Vendor != "" {
vendors.add(fieldCandidate{
value: normalizeName(m.Vendor),
disallowSubSelections: true,
})
}
vendor = m.Vendor
case pkg.RpmArchive:
if m.Vendor != "" {
vendors.add(fieldCandidate{
value: normalizeName(m.Vendor),
disallowSubSelections: true,
})
}
vendor = m.Vendor
}
vendor = stripTrailingURL(vendor)
if vendor != "" {
vendors.add(fieldCandidate{
value: normalizeName(vendor),
disallowSubSelections: true,
})
}
return vendors
}
func stripTrailingURL(value string) string {
trimmed := strings.TrimSpace(value)
if !strings.HasSuffix(trimmed, ">") {
return value
}
open := strings.LastIndex(trimmed, "<")
if open == -1 {
return value
}
parsed, err := url.Parse(trimmed[open+1 : len(trimmed)-1])
if err != nil || parsed.Host == "" || (parsed.Scheme != "http" && parsed.Scheme != "https") {
return value
}
return strings.TrimSpace(trimmed[:open])
}
@@ -0,0 +1,60 @@
package cpegenerate
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/anchore/syft/syft/pkg"
)
func TestCandidateVendorsForRPM(t *testing.T) {
tests := []struct {
name string
metadata any
expected []string
}{
{
name: "database vendor with publisher URL",
metadata: pkg.RpmDBEntry{
Vendor: "SUSE LLC <https://www.suse.com/>",
},
expected: []string{"susellc"},
},
{
name: "archive vendor with publisher URL",
metadata: pkg.RpmArchive{
Vendor: "SUSE LLC <https://www.suse.com/>",
},
expected: []string{"susellc"},
},
{
name: "plain vendor",
metadata: pkg.RpmDBEntry{
Vendor: "Red Hat, Inc.",
},
expected: []string{"redhat"},
},
{
name: "non-URL angle-bracket suffix",
metadata: pkg.RpmDBEntry{
Vendor: "Example <support@example.com>",
},
expected: []string{"example<support@example.com>"},
},
{
name: "non-HTTP URL",
metadata: pkg.RpmDBEntry{
Vendor: "Example <ftp://example.com>",
},
expected: []string{"example<ftp://example.com>"},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
p := pkg.Package{Metadata: test.metadata}
assert.ElementsMatch(t, test.expected, candidateVendorsForRPM(p).uniqueValues())
})
}
}
@@ -27,10 +27,11 @@ type packageLock struct {
// lockDependency represents a single package dependency listed in the package.lock json file
type lockDependency struct {
Version string `json:"version"`
Resolved string `json:"resolved"`
Integrity string `json:"integrity"`
Dev bool `json:"dev"`
Version string `json:"version"`
Resolved string `json:"resolved"`
Integrity string `json:"integrity"`
Dev bool `json:"dev"`
Dependencies map[string]lockDependency `json:"dependencies"`
}
type lockPackage struct {
@@ -77,14 +78,7 @@ func (a genericPackageLockAdapter) parsePackageLock(ctx context.Context, resolve
}
if lock.LockfileVersion == 1 {
for name, pkgMeta := range lock.Dependencies {
// skip packages that are only present as a dev dependency
if !a.cfg.IncludeDevDependencies && pkgMeta.Dev {
continue
}
pkgs = append(pkgs, newPackageLockV1Package(ctx, a.cfg, resolver, reader.Location, name, pkgMeta))
}
pkgs = append(pkgs, a.packageLockV1Packages(ctx, resolver, reader.Location, lock.Dependencies)...)
}
if lock.LockfileVersion == 2 || lock.LockfileVersion == 3 {
@@ -116,6 +110,32 @@ func (a genericPackageLockAdapter) parsePackageLock(ctx context.Context, resolve
return pkgs, dependency.Resolve(packageLockDependencySpecifier, pkgs), unknown.IfEmptyf(pkgs, "unable to determine packages")
}
func (a genericPackageLockAdapter) packageLockV1Packages(ctx context.Context, resolver file.Resolver, location file.Location, dependencies map[string]lockDependency) []pkg.Package {
var pkgs []pkg.Package
seen := make(map[string]struct{})
var walk func(map[string]lockDependency)
walk = func(dependencies map[string]lockDependency) {
for name, pkgMeta := range dependencies {
// Skipping a dev-only dependency also skips its dev-only subtree.
if !a.cfg.IncludeDevDependencies && pkgMeta.Dev {
continue
}
p := newPackageLockV1Package(ctx, a.cfg, resolver, location, name, pkgMeta)
if _, exists := seen[p.PURL]; !exists {
pkgs = append(pkgs, p)
seen[p.PURL] = struct{}{}
}
walk(pkgMeta.Dependencies)
}
}
walk(dependencies)
return pkgs
}
func (licenses *packageLockLicense) UnmarshalJSON(data []byte) (err error) {
// The license field could be either a string or an array.
@@ -111,6 +111,66 @@ func TestParsePackageLock(t *testing.T) {
pkgtest.TestFileParser(t, fixture, adapter.parsePackageLock, expectedPkgs, expectedRelationships)
}
func TestParsePackageLockV1NestedDependencies(t *testing.T) {
fixture := "testdata/pkg-lock/nested-package-lock-1.json"
expectedPkgs := []pkg.Package{
{
Name: "duplicate",
Version: "1.0.0",
PURL: "pkg:npm/duplicate@1.0.0",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/duplicate/-/duplicate-1.0.0.tgz", Integrity: "sha512-duplicate"},
},
{
Name: "middle",
Version: "1.0.0",
PURL: "pkg:npm/middle@1.0.0",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/middle/-/middle-1.0.0.tgz", Integrity: "sha512-middle"},
},
{
Name: "parent",
Version: "1.0.0",
PURL: "pkg:npm/parent@1.0.0",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/parent/-/parent-1.0.0.tgz", Integrity: "sha512-parent"},
},
{
Name: "shared",
Version: "0.5.0",
PURL: "pkg:npm/shared@0.5.0",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/shared/-/shared-0.5.0.tgz", Integrity: "sha512-shared-0.5"},
},
{
Name: "shared",
Version: "1.0.0",
PURL: "pkg:npm/shared@1.0.0",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/shared/-/shared-1.0.0.tgz", Integrity: "sha512-shared-1"},
},
{
Name: "shared",
Version: "2.0.0",
PURL: "pkg:npm/shared@2.0.0",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/shared/-/shared-2.0.0.tgz", Integrity: "sha512-shared-2"},
},
}
for i := range expectedPkgs {
expectedPkgs[i].Locations.Add(file.NewLocation(fixture))
}
adapter := newGenericPackageLockAdapter(CatalogerConfig{})
pkgtest.TestFileParser(t, fixture, adapter.parsePackageLock, expectedPkgs, nil)
}
func TestParsePackageLockV2(t *testing.T) {
ctx := context.TODO()
fixture := "testdata/pkg-lock/package-lock-2.json"
@@ -0,0 +1,54 @@
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"parent": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/parent/-/parent-1.0.0.tgz",
"integrity": "sha512-parent",
"dependencies": {
"shared": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/shared/-/shared-1.0.0.tgz",
"integrity": "sha512-shared-1"
},
"middle": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/middle/-/middle-1.0.0.tgz",
"integrity": "sha512-middle",
"dependencies": {
"shared": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/shared/-/shared-0.5.0.tgz",
"integrity": "sha512-shared-0.5"
}
}
},
"duplicate": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/duplicate/-/duplicate-1.0.0.tgz",
"integrity": "sha512-duplicate"
}
}
},
"shared": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shared/-/shared-2.0.0.tgz",
"integrity": "sha512-shared-2"
},
"duplicate": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/duplicate/-/duplicate-1.0.0.tgz",
"integrity": "sha512-duplicate"
},
"dev-parent": {
"version": "1.0.0",
"dev": true,
"dependencies": {
"dev-nested": {
"version": "1.0.0"
}
}
}
}
}
+13 -1
View File
@@ -14,7 +14,7 @@ func newPackageFromCargoMetadata(m pkg.RustCargoLockEntry, locations ...file.Loc
Name: m.Name,
Version: m.Version,
Locations: file.NewLocationSet(locations...),
PURL: packageURL(m.Name, m.Version),
PURL: cargoLockPackageURL(m),
Language: pkg.Rust,
Type: pkg.RustPkg,
Metadata: m,
@@ -25,6 +25,18 @@ func newPackageFromCargoMetadata(m pkg.RustCargoLockEntry, locations ...file.Loc
return p
}
func cargoLockPackageURL(m pkg.RustCargoLockEntry) string {
// Cargo omits source for packages resolved from the local workspace or a
// path dependency. A cargo PURL without a repository qualifier identifies
// a package on crates.io, so emitting one for a local package can cause
// downstream scanners to match unrelated registry vulnerabilities.
if m.Source == "" {
return ""
}
return packageURL(m.Name, m.Version)
}
func newPackageFromAudit(dep *rustaudit.Package, locations ...file.Location) pkg.Package {
p := pkg.Package{
Name: dep.Name,
+33
View File
@@ -4,6 +4,8 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/anchore/syft/syft/pkg"
)
func Test_packageURL(t *testing.T) {
@@ -31,3 +33,34 @@ func Test_packageURL(t *testing.T) {
})
}
}
func TestNewPackageFromCargoMetadataPURL(t *testing.T) {
tests := []struct {
name string
source string
want string
}{
{
name: "crates.io package",
source: "registry+https://github.com/rust-lang/crates.io-index",
want: "pkg:cargo/telemetry@0.1.0",
},
{
name: "local path package",
source: "",
want: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := newPackageFromCargoMetadata(pkg.RustCargoLockEntry{
Name: "telemetry",
Version: "0.1.0",
Source: tt.source,
})
assert.Equal(t, tt.want, got.PURL)
})
}
}
@@ -351,7 +351,7 @@ func TestCargoLockWithGitDependencies(t *testing.T) {
helloWorld := pkg.Package{
Name: "hello_world",
Version: "0.1.0",
PURL: "pkg:cargo/hello_world@0.1.0",
PURL: "",
Locations: locations,
Language: pkg.Rust,
Type: pkg.RustPkg,
@@ -673,6 +673,77 @@ func TestCargoLockWithGitDependencies(t *testing.T) {
pkgtest.TestFileParser(t, fixture, parseCargoLock, expectedPkgs, expectedRelationships)
}
func TestCargoLockWithPathDependencies(t *testing.T) {
fixture := "testdata/path-deps/Cargo.lock"
locations := file.NewLocationSet(file.NewLocation(fixture))
app := pkg.Package{
Name: "app",
Version: "1.0.0",
Locations: locations,
Language: pkg.Rust,
Type: pkg.RustPkg,
Licenses: pkg.NewLicenseSet(),
Metadata: pkg.RustCargoLockEntry{
Name: "app",
Version: "1.0.0",
Dependencies: []string{
"memchr",
"telemetry",
},
},
}
memchr := pkg.Package{
Name: "memchr",
Version: "2.7.4",
PURL: "pkg:cargo/memchr@2.7.4",
Locations: locations,
Language: pkg.Rust,
Type: pkg.RustPkg,
Licenses: pkg.NewLicenseSet(),
Metadata: pkg.RustCargoLockEntry{
Name: "memchr",
Version: "2.7.4",
Source: "registry+https://github.com/rust-lang/crates.io-index",
Checksum: "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3",
Dependencies: []string{},
},
}
telemetry := pkg.Package{
Name: "telemetry",
Version: "0.1.0",
Locations: locations,
Language: pkg.Rust,
Type: pkg.RustPkg,
Licenses: pkg.NewLicenseSet(),
Metadata: pkg.RustCargoLockEntry{
Name: "telemetry",
Version: "0.1.0",
Dependencies: []string{},
},
}
expectedPkgs := []pkg.Package{
app,
memchr,
telemetry,
}
expectedRelationships := []artifact.Relationship{
{
From: memchr,
To: app,
Type: artifact.DependencyOfRelationship,
},
{
From: telemetry,
To: app,
Type: artifact.DependencyOfRelationship,
},
}
pkgtest.TestFileParser(t, fixture, parseCargoLock, expectedPkgs, expectedRelationships)
}
func TestCargoLockDependencySpecification(t *testing.T) {
tests := []struct {
name string
+21
View File
@@ -0,0 +1,21 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "app"
version = "1.0.0"
dependencies = [
"memchr",
"telemetry",
]
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "telemetry"
version = "0.1.0"