Repository navigation
Allow the Nexus S3 blob store that packages.nuxeo.com redirects to - #291
v-abhishekbhaskar merged 1 commit into
Conversation
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The narrowly scoped host entry follows existing security conventions and has comprehensive boundary tests.
Review effort: Balanced
Findings: None
What changed in this PR
Adds Nuxeo’s exact S3 blob-store host so Maven/Gradle requests can follow redirects from packages.nuxeo.com.
Changes:
- Adds the exact regional S3 hostname to JVM defaults.
- Tests allowed access and blocks sibling, cross-region, and child hosts.
| File | Description |
|---|---|
internal/handlers/egress_allowlist_defaults.yaml |
Adds the exact Nuxeo S3 backend host. |
internal/handlers/egress_allowlist_test.go |
Adds positive and anti-widening regression coverage. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
packages.nuxeo.com is already in the Maven defaults, but the entry is incomplete: Nexus 302-redirects every download to its S3 blob store on nuxeo-devtools-nexus-central.s3.eu-west-1.amazonaws.com, which is blocked under proxy-egress-enforce. Listed as an exact virtual-hosted bucket, never a glob: "nuxeo-devtools-" is not a reserved AWS namespace, so any sibling name is registrable by anyone and a glob over the bucket or the region would match an attacker-controlled bucket. Co-authored-by: Claude <noreply@anthropic.com>
d7602b6 to
95d839a
Compare
|
@v-abhishekbhaskar, not sure if you're the person, but as you've merged a similar PR, do you think you could please have a look, otherwise redirect to the right reviewer? |
|
@ataillefer apologies for the delay in reviewing this PR. I'm going to deploy it now. Thanks! |
|
@v-abhishekbhaskar no problem, thanks! |
What are you trying to accomplish?
packages.nuxeo.comis already in the Maven defaults, but the entry is incomplete. Nexus302-redirects every GET — metadata and artifacts alike, in bothmaven-publicandmaven-public-lts— to its S3 blob store onnuxeo-devtools-nexus-central.s3.eu-west-1.amazonaws.com, and that host is not allowlisted, so the redirect is blocked underproxy-egress-enforce:Dependabot then falls back to Maven Central, so artifacts mirrored there recover silently and only artifacts unique to this repository fail, surfacing as
private_source_authentication_failureagainstpackages.nuxeo.com. Onnuxeo/nuxeo-ltsthat is 33 dependencies per run, across three release branches, every day since 2026-09-30.HEADis served directly by Nexus without a redirect, which is why jarHEADprobes in the log return200while every metadataGETfails.This adds the blob store host so the existing
packages.nuxeo.comentry actually works.The repository is public and anonymous. Following the redirect with plain
curland no credentials returns200:The bucket is owned by Nuxeo and backs
packages.nuxeo.com, Nuxeo's public distribution repository for the open-source Nuxeo Platform.Anything you want to highlight for special attention from reviewers?
Why the exact form, and not a glob. AWS reserves no
nuxeo-devtools-prefix, so any sibling name is registrable by anyone —nuxeo-devtools-nexus-evilandnuxeo-devtools-nexus-central-xboth return404 NoSuchBuckettoday. Anuxeo-devtools-*.s3.*.amazonaws.compattern would therefore hand every job an attacker-registrable destination. Same reasoning as thejulialang-storage-*entries, which have the identical<bucket>.s3.<region>.amazonaws.comshape. The exact entry is safe because the bucket is already registered: an unsigned GET returns403 AccessDenied, not404 NoSuchBucket, so the name cannot currently be taken by anyone else.On ownership evidence. The bucket's TLS certificate is AWS's
CN = *.s3-eu-west-1.amazonaws.comwildcard and is therefore not evidence of who controls it. The corroboration is thatpackages.nuxeo.com— valid certificate,CN = packages.nuxeo.com— is what issues the pre-signed URLs pointing at it, plus confirmation from Nuxeo. Flagging this explicitly rather than presenting the certificate as proof.Allowlisting grants no access on its own. Every object requires a pre-signed URL that Nexus issues only after authorising the request; unsigned or tampered requests return
403. This matches the acceptedjfrog-prod-*precedent, where the same buckets back private tenants.Placement. Added alongside
a8c-libs.s3.amazonaws.comin the exact-S3-bucket group rather than immediately next topackages.nuxeo.com, whose group comment ("verified anonymous: each returns 404 (not 401) for an absent artifact") does not describe a blob store. Happy to move it if you would rather keep the registry and its backend adjacent.Alternative considered. Declaring the registry under
registries:independabot.ymldoes not work here:dynamicHostsonly derives redirect backends for ECR, viaecrHostPatterninegress_dynamic_hosts.go, so the S3 host would still be blocked. This is the same situation as #285.How will you know you've accomplished your goal?
Reproduction of the block, before the change:
curl -sI https://packages.nuxeo.com/repository/maven-public-lts/org/nuxeo/build/nuxeo-distribution-tools/maven-metadata.xml # HTTP/2 302, location: https://nuxeo-devtools-nexus-central.s3.eu-west-1.amazonaws.com/storage/content/...Affected job log: https://github.com/nuxeo/nuxeo-lts/actions/runs/36932442506/job/110604806942 — 589 blocked requests, all for that one host.
Covered by tests in
TestEgressAllowlist_PublicRegistriesThirdWaveAllowed, wherepackages.nuxeo.comis already asserted:nuxeo-devtools-nexus-evil.s3.eu-west-1.amazonaws.comstays blockednuxeo-devtools-nexus-central.s3.us-east-1.amazonaws.comstays blockedevil.nuxeo-devtools-nexus-central.s3.eu-west-1.amazonaws.comstays blocked, catching a later widening to a leading-dot entryThe existing path-style apex probes (
s3.amazonaws.com,s3.us-east-1.amazonaws.com) already guard the rest.Checklist
Note:
script/testpasses in full.golangci-lintcould not be run locally — its released image is built with Go 1.25 while the repo targets 1.26 — sogofmt,go vetandyamllint -c .yamllint.yamlwere run instead and are clean. CI will cover the linter.