fix(templates): do not mount the CodeArtifact secret while building project code - #526
Closed
stephen-wang24 wants to merge 1 commit into
Closed
stephen-wang24 wants to merge 1 commit into
stephen-wang24 wants to merge 1 commit into
Conversation
…roject code
`Dockerfile-uv.j2` installs in two steps and mounted the broker secret on both.
The second step runs `uv sync` after `COPY project`, which builds the agent's
own project — and a PEP 517 backend is project-controlled code, either an
in-tree module named by `backend-path` or whatever `[build-system] requires`
pulls in. With the secret mounted there it can read the token, and the build
has network.
Reproduced before fixing. The vector needs only files the templates already
copy — `pyproject.toml` declaring `backend-path = ["project"]`, plus one module
under `project/` — so no Dockerfile change is required, which is exactly the
threat PRIVATE_INDEX.md already says it defends against: a contributed change
to a project file is far less conspicuous in review than a curl in a
Dockerfile. What the backend captured:
secret-file: index-url = https://aws:FAKE%2BTOKEN%2FVALUE%3D@.../simple/
env password: FAKE+TOKEN/VALUE= <- decoded, not just the encoded URL
The second step no longer mounts it. Dependencies, private ones included, are
already installed by the first step, so nothing is lost. Verified against a
package published ONLY to a local private index and absent from public PyPI
(pypi.org returns 404 for it), which is the sgp-obs case:
| build succeeds | both steps: yes | step 1 only: yes |
| private-index package installs | yes | YES |
| backend reads the secret file | yes | <absent> |
| backend reads the decoded token | yes | <unset> |
`Dockerfile.j2`, the requirements.txt variant, never had this: it installs and
only then copies the project, so no project-controlled code runs while the
secret is mounted. Left alone.
Raised by Greptile on #525. Fixing it here rather than there — #525 is the
release-please branch, and a push to it would be overwritten by the next
regeneration.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Dockerfile-uv.j2installs in two steps and mounted the broker secret on both. Thesecond one runs
uv syncafterCOPY project, which builds the agent's own project— and a PEP 517 build backend is project-controlled code. With the secret mounted there
it can read the CodeArtifact token, and the build has network.
Raised by Greptile on #525. Fixing it here instead: #525 is the release-please branch, so
a push there gets overwritten by the next regeneration.
Reproduced first
The vector needs only files the templates already copy — a
pyproject.tomldeclaringbackend-path = ["project"]and one module underproject/. No Dockerfile edit. That isexactly the threat
PRIVATE_INDEX.mdalready claims to defend against:What the project's own build backend captured during
uv sync:Not only the mounted file — the decoded token too, the one the template extracts into
UV_INDEX_SCALE_PYPI_PASSWORD. Written to the image layer here; a real one would POST it.The fix, and proof nothing is lost
The second step no longer mounts the secret. Dependencies — private ones included — are
already installed by the first step.
Verified against a package published only to a local private index and absent from
public PyPI (
pypi.org/simple/fake-private-obs/returns 404), which is thesgp-obscase:<absent><unset>So the mirror still works for exactly what it exists for, and project-controlled code no
longer sees the credential.
Scope
Dockerfile-uv.j2— secret dropped from the project-build step onlyPRIVATE_INDEX.md— documents which step holds the secret and whyDockerfile.j2(therequirements.txtvariant) never had this problem — it installs andonly then copies the project, so no project-controlled code runs while the secret is
mounted. Left alone.
Template-only; no Python changed.
Testing
Both variants built with BuildKit against a local private index. One caveat: the full
rendered template could not finish building on my machine — its
apt-getlayer needs~1.2 GB and the local VM ran out of disk — so the behaviour above was measured on a
minimal build with the identical two-step shape, and the rendered template was checked
structurally (one secret mount, on the dependency step only). Worth a real build in CI.
🤖 Generated with Claude Code
The PR appears safe to merge. Adding a test for the secret boundary would make the fix harder to undo by accident.
What we checked:
Summary
The
Dockerfile-uv.j2templates now mount the CodeArtifact secret only while installing dependencies, not while building the agent's own project. The private package index still works, while project-controlled build code no longer receives the credential.Diagram
sequenceDiagram participant Build as Docker build participant Broker as Broker secret participant UV as uv participant Index as Private index participant Backend as Project build backend Build->>Broker: Mount codeartifact-pip-conf Build->>UV: uv sync --no-install-project UV->>Index: Install dependencies with token Build-->>Broker: End dependency step and unmount secret Build->>Build: COPY project Build->>UV: uv sync without broker secret UV->>Backend: Build and install project Note over Backend: Secret file and token variables are absentReviews (1) · Last reviewed commit: "fix(templates): do not mount the CodeArt..."