Skip to content

fix(binary): detect multi-arch ingress-nginx - #5179

Merged
wagoodman merged 3 commits into
anchore:mainfrom
CAOShurong:codex/5062-ingress-multiarch
Aug 19, 2026
Merged

wagoodman merged 3 commits into
anchore:mainfrom
CAOShurong:codex/5062-ingress-multiarch

Conversation

@CAOShurong

Copy link
Copy Markdown
Contributor

Summary

Detect nginx-ingress-controller v1.9.6 binaries from the published ARM64, ARMv7, and s390x controller image variants. These architectures place the controller version farther from the Go build version than the existing classifiers allow.

This addresses the currently reproduced architectures in #5062 without claiming coverage for every historical release in that issue.

Validation

  • go test ./syft/pkg/cataloger/binary -run Test_Cataloger_PositiveCases/nginx-ingress-controller/1.9.6 -count=1 -v
  • the same focused test with -must-use-original-binaries against all four published v1.9.6 binaries (amd64, arm64, arm/v7, s390x)
  • all existing ingress-nginx positive fixtures
  • TestClassifierCataloger_DefaultClassifiers_NegativeCases
  • built the syft CLI and scanned each original binary; every architecture returned exactly one nginx-ingress-controller package at version 1.9.6

The fixtures were generated from registry.k8s.io/ingress-nginx/controller:v1.9.6@sha256:1405cc613bd95b2c6edd8b2a152510ae91c7e62aea4698500d23b2145960ab9c.

Disclosure

This change was developed with OpenAI Codex assistance. I independently reproduced the missing detections, inspected the binary evidence, and ran the tests and real CLI scans listed above.

CAOShurong and others added 3 commits August 13, 2026 22:51
Add v1.9.6 ARM64, ARMv7, and s390x fixtures from the published controller image and match their version marker against the nearby Go build version.

Assisted-by: OpenAI Codex
Signed-off-by: Shurong Cao <[email protected]>
The release is injected with `-ldflags -X`, so it lands in its own aligned,
NUL-padded data symbol. Only that padding is portable -- the surrounding bytes
are an arch-specific float constant pool, which is why the existing matchers all
anchor on incidental junk like `$a` and `S=v<y5` and only ever worked on amd64.

Matching `v<version>` followed by two NULs finds exactly one hit in every v1.9.6
binary (amd64, arm, arm64, s390x) and in all nine amd64 releases already under
test. Two NULs matter -- with one, s390x matches a vendored `v1.19.0` earlier in
the file and reports the wrong version.

This also drops the ~8KB wildcard window the marker previously needed, so the new
fixtures are ordinary 369 byte snippets instead of 8.4KB ones.

Two things in the fixture tooling had to move for that to work:

- `config.yaml` pinned the multi-arch *index* digest for all four platforms, but
  extraction runs `docker create <ref>` with no `--platform`, so every entry
  resolved to whichever image was pulled last. `make download` failed outright on
  `linux/arm/v7`, since the registry labels that platform `armv7` and docker
  normalizes it to `arm`. Now pinned per-platform, matching the redis entry.

- `write-snippet` only recognized EM_X86_64 and EM_AARCH64, so anything else
  landed in a `linux-unknown-<hex>` directory and had to be placed by hand.

Verified against the real binaries with `-must-use-original-binaries`.

Signed-off-by: Alex Goodman <[email protected]>
`write-snippet` used to fall back to `unknown-<hex>` for any ELF machine it
didn't recognize, so three snippets were sitting in directories nothing reads:

    helm/3.12.0/linux-unknown-454d5f53333930      (hex of "EM_S390")
    helm/4.1.4/linux-unknown-454d5f53333930
    redis-server/7.2.5/linux-unknown-454d5f333836 (hex of "EM_386")

The test table asks for `linux-s390x` and `linux-386`, so those three cases were
quietly falling through to downloading the full binaries instead. Renamed to
match, and taught the tool about EM_386 and EM_RISCV so it stops producing dead
directories (there is an existing `linux-riscv64` snippet it also couldn't have
written).

Signed-off-by: Alex Goodman <[email protected]>

@wagoodman wagoodman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a couple of alterations:

  • updated the fixtures to be captured by the helper tool
  • updated the helper tool to cover additional architecture cases (and updated existing non-compliant fixtures themselves)

@wagoodman
wagoodman enabled auto-merge (squash) August 19, 2026 17:52
@wagoodman
wagoodman merged commit 5c6cf08 into anchore:main Aug 19, 2026
15 checks passed
@spiffcs spiffcs added the bug Something isn't working label Aug 27, 2026
social4hyq pushed a commit to social4hyq/homebrew-core that referenced this pull request Sep 20, 2026
syft 1.51.1

Created-by: HarmonybrewBot
Commit-by: HarmonybrewBot
Merged-by: HarmonybrewBot
Description: Created by `brew bump`

---

Created with `brew bump-formula-pr`.<details>
  <summary>release notes</summary>
  <pre>### Bug Fixes

- detect multi-arch ingress-nginx [PR [#5179](anchore/syft#5179) @CAOShurong]
- keep the epoch when parsing RPM manifest packages [PR [#5201](anchore/syft#5201) @sueun-dev]
- correct Apache Derby group ID in purl generation [PR [#5090](anchore/syft#5090) @Ankush-Pathak]
- move image hardlink handling upstream during image indexing [PR [#5196](anchore/syft#5196) @wagoodman]
- keep epoch-pinned requirements in the SBOM [PR [#5161](anchore/syft#5161) @sueun-dev]
- Prevent unnecessary allocations when parsing compressed ELF sections [PR [#5187](anchore/syft#5187) @wagoodman]
- honor the io.ReaderAt contract in readerAtAdapter [PR [#5186](anchore/syft#5186) @wagoodman]
- Support grafana binary various version [Issue [#5059](anchore/syft#5059)] [PR [#5213](anchore/syft#5213) @pujitha24]
- Excluded paths are still scanned and cause syft to crash [Issue [#3258](anchore/syft#3258)]
- Dotnet: Incorrect relationship graph in case of using package locks [Issue [#5125](anchore/syft#5125)] [PR [#5143](anchore/syft#5143) @pujitha24]
- Survive indexing not accessible files [Issue [#3286](anchore/syft#3286)] [PR [#5170](anchore/syft#5170) @addielaruee]
- CPE target_sw not being set consistency for Rust crates [Issue [#3956](anchore/syft#3956)] [PR [#5167](anchore/syft#5167) @Xenira]
- panic: nil pointer dereference in squashfs.(*File).Read when scanning snap (regression from 1.44.0) [Issue [#4989](anchore/syft#4989)] [PR [#5119](anchore/syft#5119) @kzantow]
- golang remote license search attempts to resolve stdlib modules [Issue [#3149](anchore/syft#3149)] [PR [#5192](anchore/syft#5192) @luantaraschi]

### Additional Changes

- gzip binary classifier reports false-positive GNU gzip from BusyBox multicall binary via applet symlink [Issue [#5171](anchore/syft#5171)] [PR [#5202](anchore/syft#5202) @spiffcs]
- pnpm v5 lockfile: underscore peer-dep suffixes are not stripped from package versions [Issue [#5174](anchore/syft#5174)] [PR [#5175](anchore/syft#5175) @codeAnqiang-ma]
- pnpm cataloger reads only the first YAML document: SBOM contains pnpm's own binaries and no project dependencies [Issue [#5168](anchore/syft#5168)] [PR [#5188](anchore/syft#5188) @hamodywe]

### Dependencies

72 dependency changes (70 updated, 1 added, 1 removed). 3 vulnerabilities remediated.

**🟢 Remediated (3)**

- [GO-2026-5158](GHSA-5wrp-cwcj-q835) (Medium) — go.opentelemetry.io/otel
- [GO-2026-6179](https://go.dev/issue/80744) (High) — golang.org/x/mod
- [GO-2026-6180](https://go.dev/issue/80745) (High) — golang.org/x/mod

<details>
<summary>Updated (70 packages)</summary>

- cel.dev/expr `v0.25.1` → `v0.25.2`
- cloud.google.com/go/auth `v0.18.2` → `v0.22.0`
- cloud.google.com/go/iam `v1.5.3` → `v1.11.0`
- cloud.google.com/go/logging `v1.13.1` → `v1.18.0`
- cloud.google.com/go/longrunning `v0.8.0` → `v1.2.0`
- cloud.google.com/go/monitoring `v1.24.3` → `v1.29.0`
- cloud.google.com/go/storage `v1.61.3` → `v1.64.0`
- cloud.google.com/go/trace `v1.11.7` → `v1.16.0`
- github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp `v1.32.0` → `v1.33.0`
- github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric `v0.55.0` → `v0.57.0`
- github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock `v0.55.0` → `v0.57.0`
- github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping `v0.55.0` → `v0.57.0`
- github.com/anchore/stereoscope `v0.3.0` → `v0.3.1`
- github.com/aws/aws-sdk-go-v2 `v1.41.5` → `v1.43.4`
- github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream `v1.7.8` → `v1.7.16`
- github.com/aws/aws-sdk-go-v2/config `v1.32.12` → `v1.32.35`
- github.com/aws/aws-sdk-go-v2/credentials `v1.19.12` → `v1.19.34`
- github.com/aws/aws-sdk-go-v2/feature/ec2/imds `v1.18.20` → `v1.18.35`
- github.com/aws/aws-sdk-go-v2/internal/configsources `v1.4.21` → `v1.4.35`
- github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 `v2.7.21` → `v2.7.35`
- github.com/aws/aws-sdk-go-v2/internal/v4a `v1.4.22` → `v1.4.36`
- github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding `v1.13.7` → `v1.13.15`
- github.com/aws/aws-sdk-go-v2/service/internal/checksum `v1.9.13` → `v1.9.28`
- github.com/aws/aws-sdk-go-v2/service/internal/presigned-url `v1.13.21` → `v1.13.35`
- github.com/aws/aws-sdk-go-v2/service/internal/s3shared `v1.19.21` → `v1.19.36`
- github.com/aws/aws-sdk-go-v2/service/s3 `v1.97.3` → `v1.106.5`
- github.com/aws/aws-sdk-go-v2/service/signin `v1.0.8` → `v1.5.4`
- github.com/aws/aws-sdk-go-v2/service/sso `v1.30.13` → `v1.33.4`
- github.com/aws/aws-sdk-go-v2/service/ssooidc `v1.35.17` → `v1.38.4`
- github.com/aws/aws-sdk-go-v2/service/sts `v1.41.9` → `v1.45.4`
- github.com/aws/smithy-go `v1.24.2` → `v1.27.6`
- github.com/containerd/containerd/v2 `v2.3.3` → `v2.3.4`
- github.com/containerd/platforms `v1.0.0-rc.4` → `v1.0.0-rc.5`
- github.com/docker/cli `v29.6.1+incompatible` → `v29.7.2+incompatible`
- github.com/docker/go-connections `v0.7.0` → `v0.8.1`
- github.com/fatih/color `v1.18.0` → `v1.19.0`
- github.com/gabriel-vasile/mimetype `v1.4.13` → `v1.4.15`
- github.com/google/go-containerregistry `v0.21.7` → `v0.21.9`
- github.com/google/pprof `v0.0.0-a4b03ec` → `v0.0.0-ef3492d`
- github.com/googleapis/enterprise-certificate-proxy `v0.3.14` → `v0.3.19`
- github.com/googleapis/gax-go/v2 `v2.17.0` → `v2.23.0`
- github.com/hashicorp/aws-sdk-go-base/v2 `v2.0.0-beta.72` → `v2.0.0-beta.74`
- github.com/hashicorp/go-getter `v1.8.6` → `v1.8.8`
- github.com/hashicorp/go-version `v1.8.0` → `v1.9.0`
- github.com/klauspost/compress `v1.19.1` → `v1.19.2`
- github.com/mattn/go-isatty `v0.0.20` → `v0.0.24`
- github.com/moby/moby/client `v0.5.0` → `v0.5.1`
- github.com/spiffe/go-spiffe/v2 `v2.6.0` → `v2.7.0`
- github.com/stretchr/objx `v0.5.2` → `v0.5.3`
- github.com/stretchr/testify `v1.11.1` → `v1.12.1`
- go.opentelemetry.io/contrib/detectors/gcp `v1.43.0` → `v1.44.0`
- go.opentelemetry.io/otel `v1.43.0` → `v1.44.0` **(🟢 remediated [GO-2026-5158](https://github.com/open-telemetry/opentelemetry-go/security/advisories/GHSA-5wrp-cwcj-q835))**
- go.opentelemetry.io/otel/exporters/stdout/stdoutmetric `v1.40.0` → `v1.44.0`
- go.opentelemetry.io/otel/metric `v1.43.0` → `v1.44.0`
- go.opentelemetry.io/otel/sdk `v1.43.0` → `v1.44.0`
- go.opentelemetry.io/otel/sdk/metric `v1.43.0` → `v1.44.0`
- go.opentelemetry.io/otel/trace `v1.43.0` → `v1.44.0`
- golang.org/x/crypto `v0.54.0` → `v0.55.0`
- golang.org/x/mod `v0.38.0` → `v0.40.0` **(🟢 remediated [GO-2026-6179](https://go.dev/issue/80744), [GO-2026-6180](https://go.dev/issue/80745))**
- golang.org/x/net `v0.57.0` → `v0.58.0`
- golang.org/x/text `v0.40.0` → `v0.41.0`
- golang.org/x/tools `v0.48.0` → `v0.49.0`
- google.golang.org/api `v0.271.0` → `v0.292.0`
- google.golang.org/genproto `v0.0.0-8636f87` → `v0.0.0-aa98bba`
- google.golang.org/genproto/googleapis/api `v0.0.0-afd174a` → `v0.0.0-925bb5d`
- google.golang.org/genproto/googleapis/rpc `v0.0.0-afd174a` → `v0.0.0-6ac0973`
- google.golang.org/grpc `v1.82.1` → `v1.83.0`
- modernc.org/cc/v4 `v4.29.0` → `v4.29.1`
- modernc.org/libc `v1.74.1` → `v1.74.4`
- modernc.org/sqlite `v1.55.0` → `v1.56.0`
</details>

<details>
<summary>Added (1 package)</summary>

- go.opentelemetry.io/otel/metric/x `v0.66.0`
</details>

<details>
<summary>Removed (1 package)</summary>

- github.com/aws/aws-sdk-go-v2/internal/ini `v1.8.6`
</details>

**[(Full Changelog)](anchore/syft@v1.51.0...v1.51.1)**

</pre>
  <p>View the full release notes at <a href="https://github.com/anchore/syft/releases/tag/v1.51.1">https://github.com/anchore/syft/releases/tag/v1.51.1</a>.</p>
</details>
<hr>

See merge request: Harmonybrew/homebrew-core!17926
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants