Skip to content

fix(bake): grant fs.read for a Dockerfile outside the context - #14286

Closed
locker95 wants to merge 2 commits into
docker:mainfrom
locker95:bake-dockerfile-fs-read
Closed

locker95 wants to merge 2 commits into
docker:mainfrom
locker95:bake-dockerfile-fs-read

Conversation

@locker95

@locker95 locker95 commented Oct 5, 2026

Copy link
Copy Markdown

buildx 0.37.2 started checking fs.read even for bake --progress rawjson, which is how compose always invokes bake. We only granted the context, so a dockerfile outside it dies with "additional privileges requested". That's the devcontainer case, where the CLI points dockerfile: at a temp Dockerfile-with-features.

This adds that local path to the allow list. Git and remote contexts are left alone.

Fixes #14285

bake --progress rawjson now enforces filesystem entitlements. Compose
only allowed the context, so a dockerfile path outside it fails the check.

Signed-off-by: Dean Chen <862469039@qq.com>
@codecov

codecov Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.44068% with 8 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pkg/compose/build_bake.go 86.44% 5 Missing and 3 partials ⚠️

📢 Thoughts on this report? Let us know!

@ndeloof ndeloof 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.

Thanks for tackling this. These notes come from a static read of the diff (AI-assisted review): I did not run a bake build against them, so please treat the first point as "to verify" rather than established.

The main concern is the scope of the grant: bake reads the Dockerfile's directory (the dockerfile local source plus the .dockerignore files next to it), so granting only the Dockerfile file path may not make the reported error go away for a Dockerfile outside the context. Details inline.

One more general remark: the entitlement set is rebuilt by hand from the compose fields (context, additional contexts, dockerfile). Other local inputs (secrets: file:, cache_from: type=local, ...) will need the same kind of special case later. Deriving the paths from the generated bake definition, or from buildx's own entitlement detection, would be more future-proof — probably out of scope here, but worth keeping in mind.

Comment thread pkg/compose/build_bake.go Outdated
if contextType == build.ContextTypeGit || contextType == build.ContextTypeRemote || strings.Contains(buildConfig.Context, "://") {
return ""
}
return dockerFilePath(buildConfig.Context, buildConfig.Dockerfile)

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 believe the grant needs to be the Dockerfile's directory, not the file: with context: ./app and dockerfile: ../docker/Dockerfile.prod, bake loads the dockerfile local source from /proj/docker (and reads Dockerfile.prod.dockerignore / .dockerignore there). --allow fs.read=/proj/docker/Dockerfile.prod would not cover that directory, so the build could still fail with the same entitlement error. Something like filepath.Dir(...) on the resolved path looks needed — could you confirm with a real bake run for that layout?

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 got this one wrong, sorry — the recommendation to grant the Dockerfile's directory doesn't hold up. I ran a real bake with the layout from my comment (context: ./app, dockerfile: ../docker/Dockerfile.prod), from a working directory that contains neither (buildx implicitly allows the cwd subtree, so the failure only shows when the Dockerfile is outside it). buildx v0.37.2, default builder:

grants result
context only fails: Pass "--allow=fs.read=../docker/Dockerfile.prod" to grant requested privileges
context + docker/Dockerfile.prod (the file) builds
context + docker/ (the directory) builds

So the entitlement buildx asks for is the Dockerfile file, not its directory. The dockerfile local source doesn't need a directory-level grant.

The sibling ignore files don't change that either. With a docker/Dockerfile.prod.dockerignore excluding g and a COPY g, the file grant and the directory grant behave identically: the ignore file is honored (CopyIgnoredFile warning, then "/g": not found) in both cases. A plain docker/.dockerignore next to the Dockerfile isn't read at all in either case. Only the context's .dockerignore and <dockerfile>.dockerignore are picked up.

Granting the directory is therefore broader than needed, and it can matter: dockerfile: ~/Dockerfile or a Dockerfile in a shared tmp dir would open $HOME or /tmp to the build, where before this change only the context was granted.

Suggestion: grant the resolved file instead of its parent.

  • localDockerfileDir → return the output of dockerFilePath as is (drop the filepath.Dir); update its comment, which currently says bake reads the directory including the .dockerignore.
  • dirCovered already works on a file path (the filepath.Rel containment check), so a Dockerfile inside the context is still skipped.
  • In the test, flip the assertions: expect filepath.Join(resolvedDir, "Dockerfile") in the list and the bare directory out (the current !containsPath(got, wantFile) pins the wrong grant).

Caveat: I only checked buildx v0.37.2 with the docker driver — worth a quick run with a docker-container builder before settling.

Comment thread pkg/compose/build_bake.go Outdated
return ""
}
contextType, _ := build.DetectContextType(buildConfig.Context)
if contextType == build.ContextTypeGit || contextType == build.ContextTypeRemote || strings.Contains(buildConfig.Context, "://") {

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.

This remote/git context detection is a copy of the one at the top of dockerFilePath (which is then called on the next line and repeats it). The two copies can drift apart. A small shared isRemoteContext(ctx) helper, or having dockerFilePath tell the caller whether it resolved a local path, would avoid that.

Comment thread pkg/compose/build_bake.go Outdated
for _, path := range buildConfig.AdditionalContexts {
paths = append(paths, path)
}
if df := localDockerfilePath(buildConfig); df != "" {

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.

In the common case (context: ., Dockerfile inside it) this now adds a second --allow fs.read= per service for a path the context grant already covers, and localPaths is not deduplicated, so N services carry 2N flags. Could we skip the Dockerfile entry when it is under the context, and/or dedupe the final list?

Comment thread pkg/compose/build_bake.go Outdated
}
var local []string
for _, path := range paths {
if _, _, err := gitutil.ParseGitRef(path); !strings.Contains(path, "://") && err != nil {

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.

Minor: this filter (ParseGitRef + ://) was designed for contexts and now also sees a resolved host Dockerfile path. A path like /work/github.com/org/repo/Dockerfile might parse as a git ref and be silently dropped, which would bring the entitlement error back. Worth checking, or classifying each path by type up front instead of filtering after the fact.

Comment thread pkg/compose/build_bake_test.go Outdated
},
})
assert.Assert(t, containsPath(got, ctxDir))
assert.Assert(t, containsPath(got, wantDF))

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.

This only checks that the Dockerfile file path is in the returned list, so it would pass with the wrong grant (file instead of directory, see my comment on build_bake.go). Once the expected grant is settled, the assertion should pin it, and ideally an e2e / bakeArgs-level case should exercise a Dockerfile outside the context so bake's acceptance of the grant is actually covered.

Bake reads the dockerfile source from that directory, so a file grant
misses a sibling dockerignore. Skip the extra allow when the directory
is already inside a context, and keep the git-ref filter off host paths.

Signed-off-by: Dean Chen <862469039@qq.com>
@locker95

locker95 commented Oct 7, 2026

Copy link
Copy Markdown
Author

yeah, the file grant was too narrow. bake reads that directory (the dockerignore sits next to the Dockerfile), so the extra --allow is the directory now, and only when it isn't already covered by the context.

left the git-ref check on contexts only. an absolute host path doesn't parse as a git ref today, but a directory with github.com in the name shouldn't have to depend on that. the test pins the directory, and checks the --allow bake actually gets.

stefanoginella added a commit to stefanoginella/aicontainer that referenced this pull request Oct 10, 2026
Buildx 0.37.2 (GHSA-gwr2-q96m-6682) makes bake enforce filesystem
entitlements under `--progress rawjson`, which Compose always uses.
Compose grants fs.read only for the build context, but the Dev Containers
CLI points `dockerfile:` at a temp Dockerfile-with-features outside it, so
every build-mode `devcontainer up` in the smoke jobs now fails.

Set BUILDX_BAKE_ENTITLEMENTS_FS=0 on the smoke job of both workflows. The
scope is CI-only and the inputs are this repository's own fixtures.
Remove it once docker/compose#14286 ships in the runner image.

Refs: docker/compose#14285
Refs: devcontainers/cli#1320

@ndeloof ndeloof 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.

Thanks for tackling this. Requesting changes on two points, both checked with a real buildx bake (v0.37.2, default builder, run from a directory unrelated to the files so the implicit cwd grant doesn't hide anything).

1. The grant should be the Dockerfile file, not its directory.
buildx asks for the file (Pass "--allow=fs.read=../docker/Dockerfile.prod"), and a file-level grant is enough: a sibling <dockerfile>.dockerignore is honored with the file grant exactly as with the directory grant, and a plain .dockerignore next to the Dockerfile isn't read in either case. Granting the parent directory is broader than needed (dockerfile: ~/Dockerfile opens $HOME) and the comment on localDockerfileDir claiming bake reads the directory is inaccurate. My earlier recommendation of the directory was wrong — details and the suggested change in this thread.

2. Other host paths trigger the same entitlement error and aren't covered.
As noted in this comment on #14285, the failure isn't specific to dockerfile:. With only the context granted, buildx rejects each of these:

build option requested grant
ssh: [my_id=/path/to/key] fs.read=<key path>
secrets: with file: (type=file,src=…) fs.read=<file>
cache_from: [type=local,src=…] fs.read=<dir>
cache_to: [type=local,dest=…] fs.write=<dir> — bakeArgs can't emit fs.write at all today

So a project with a key-path ssh: or a file secret still breaks after this PR with the same additional privileges requested error. Could you either extend the grants to these (the file secret and ssh key path are the most common), or state explicitly that this PR is scoped to the Dockerfile and track the rest in a follow-up so #14285 isn't closed as fully fixed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants