Repository navigation
Description
Describe the bug
--readonly only blocks container create. ReadonlyGate lives in the middleware chain, and the chain runs only when the router returns the create route (go/internal/proxy/handler.go:75, rs/src/handler.rs:78, ts/src/handler.ts:43). The flag feeds nothing else (go/main.go:82, rs/src/main.rs:106, ts/src/index.ts:67). So in read-only mode the proxy still forwards container lifecycle actions (start, stop, restart, kill, wait, pause, unpause), DELETE /containers/{name}, and image pulls that pass the router.
README.md says ReadonlyGate "Denies all POST, PUT, DELETE, PATCH", so an operator relying on --readonly gets far less than documented. Found in the review of #74 (the same unreachable-gate pattern as the ExecGate removed there).
Affected implementation(s)
- All (reproduced on Go; Rust and TS have the same structure by code reading)
To Reproduce
Go binary from main, --readonly, --config-dir=deploy/config, against Docker 29.4.0:
| Request | Status | Body |
|---|---|---|
POST /containers/create |
403 | validation failed: read-only mode: POST requests are not allowed |
POST /containers/zz-no-such/stop |
404 | {"message":"No such container: zz-no-such"} (forwarded to the daemon) |
DELETE /containers/zz-no-such |
404 | {"message":"No such container: zz-no-such"} (forwarded to the daemon) |
POST /images/create?fromImage=… (no body) |
403 | empty request body (denied for another reason; a pull with a body was not tried) |
With a real container name, stop and DELETE would act on it.
Expected behavior
In read-only mode every method other than GET/HEAD is denied for every path, before routing or as a router rule, with the existing message read-only mode: <METHOD> requests are not allowed, in all three implementations. Spec: add a READONLY flag to spec/router.qnt with a property "readonly ⇒ no non-GET/HEAD request is allowed", a router_readonly instance, and table rows; unit tables in all three; an integration run with --readonly.
Alternatives considered:
- Run the chain on every route. Rejected: the other gates are create-specific (image, binds, env, cmd) and would need per-route guards.
- Document that
--readonlyonly covers create. Rejected: that is not a useful "read-only" mode, and the README already promises more.
Environment
- Docker 29.4.0 (OrbStack),
mainat3c7fe0b.
Additional context
Consider a security note for the affected releases once fixed.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Activity
fix: enforce --readonly in the router for every write (#75) (#77)