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)
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
--readonly only covers create. Rejected: that is not a useful "read-only" mode, and the README already promises more.
Environment
- Docker 29.4.0 (OrbStack),
main at 3c7fe0b.
Additional context
Consider a security note for the affected releases once fixed.
Describe the bug
--readonlyonly blocks container create.ReadonlyGatelives 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.mdsays ReadonlyGate "Denies allPOST,PUT,DELETE,PATCH", so an operator relying on--readonlygets far less than documented. Found in the review of #74 (the same unreachable-gate pattern as the ExecGate removed there).Affected implementation(s)
To Reproduce
Go binary from
main,--readonly,--config-dir=deploy/config, against Docker 29.4.0:POST /containers/createvalidation failed: read-only mode: POST requests are not allowedPOST /containers/zz-no-such/stop{"message":"No such container: zz-no-such"}(forwarded to the daemon)DELETE /containers/zz-no-such{"message":"No such container: zz-no-such"}(forwarded to the daemon)POST /images/create?fromImage=…(no body)empty request body(denied for another reason; a pull with a body was not tried)With a real container name,
stopandDELETEwould act on it.Expected behavior
In read-only mode every method other than
GET/HEADis denied for every path, before routing or as a router rule, with the existing messageread-only mode: <METHOD> requests are not allowed, in all three implementations. Spec: add aREADONLYflag tospec/router.qntwith a property "readonly ⇒ no non-GET/HEAD request is allowed", arouter_readonlyinstance, and table rows; unit tables in all three; an integration run with--readonly.Alternatives considered:
--readonlyonly covers create. Rejected: that is not a useful "read-only" mode, and the README already promises more.Environment
mainat3c7fe0b.Additional context
Consider a security note for the affected releases once fixed.