mirror of
https://github.com/anchore/syft.git
synced 2026-10-26 12:02:23 +01:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16223e6dd7 | ||
|
|
1286689419 | ||
|
|
295454945c | ||
|
|
86baeeb481 | ||
|
|
2dcf5163b8 | ||
|
|
12b8ba47fb | ||
|
|
138d9ce2a0 | ||
|
|
8a229b16c4 | ||
|
|
9af0098a68 | ||
|
|
2840ea6653 | ||
|
|
b38e40e3e6 | ||
|
|
a6eedecd31 | ||
|
|
691b1357b2 | ||
|
|
c890e7f17f |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -98,7 +98,7 @@ require (
|
||||
golang.org/x/time v0.15.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,7 +168,7 @@ 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.3 // indirect
|
||||
@@ -189,8 +189,8 @@ require (
|
||||
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
|
||||
@@ -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
|
||||
@@ -319,12 +319,12 @@ require (
|
||||
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
|
||||
)
|
||||
|
||||
@@ -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=
|
||||
@@ -290,8 +290,8 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH
|
||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-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=
|
||||
@@ -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=
|
||||
@@ -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=
|
||||
@@ -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=
|
||||
@@ -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{
|
||||
|
||||
@@ -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*",
|
||||
|
||||
+12
@@ -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
|
||||
+12
@@ -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
|
||||
+12
@@ -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
|
||||
+12
@@ -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
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -2412,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:*:*"
|
||||
],
|
||||
@@ -6837,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:*:*:*:*:*:*:*:*"
|
||||
],
|
||||
@@ -8557,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:*:*"
|
||||
],
|
||||
@@ -8747,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:*:*"
|
||||
],
|
||||
@@ -8811,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": [
|
||||
@@ -11021,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:*:*"
|
||||
],
|
||||
@@ -12150,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:*:*"
|
||||
],
|
||||
@@ -13132,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:*:*"
|
||||
],
|
||||
@@ -13141,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:*:*"
|
||||
],
|
||||
@@ -13225,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:*:*"
|
||||
],
|
||||
@@ -13255,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:*:*"
|
||||
],
|
||||
@@ -13687,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:*:*"
|
||||
],
|
||||
@@ -13711,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:*:*"
|
||||
],
|
||||
@@ -14085,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:*:*"
|
||||
],
|
||||
@@ -14185,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:*:*"
|
||||
],
|
||||
@@ -14421,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:*:*"
|
||||
],
|
||||
@@ -14910,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:*:*"
|
||||
],
|
||||
@@ -14982,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:*:*"
|
||||
],
|
||||
@@ -15178,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:*:*"
|
||||
@@ -15198,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:*:*"
|
||||
],
|
||||
@@ -15216,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:*:*"
|
||||
],
|
||||
@@ -15547,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:*:*"
|
||||
],
|
||||
@@ -16239,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": [
|
||||
@@ -16672,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:*:*"
|
||||
],
|
||||
@@ -16685,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:*:*"
|
||||
],
|
||||
@@ -17472,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:*:*"
|
||||
],
|
||||
@@ -17501,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:*:*"
|
||||
],
|
||||
@@ -17686,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:*:*"
|
||||
],
|
||||
@@ -18576,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:*:*"
|
||||
],
|
||||
@@ -18868,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:*:*"
|
||||
],
|
||||
@@ -19970,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:*:*"
|
||||
],
|
||||
@@ -19993,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:*:*"
|
||||
],
|
||||
@@ -20605,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:*:*"
|
||||
],
|
||||
@@ -20954,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:*:*"
|
||||
],
|
||||
@@ -21185,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:*:*"
|
||||
],
|
||||
@@ -21483,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:*:*"
|
||||
],
|
||||
@@ -21935,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:*:*"
|
||||
],
|
||||
@@ -23143,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:*:*"
|
||||
],
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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"
|
||||
Reference in New Issue
Block a user