Security model#
imagegate proves where an image came from. It does not control what a container may do once it runs.
In scope#
- Unsigned, tampered or re-pushed images.
- Images signed by the wrong identity: a fork's workflow, another branch, a personal key.
- Missing, unsigned or mismatched SBOMs.
- Mutable tags: every check is by digest, and start re-checks the image the container actually uses.
Design invariants#
- Never lock operators out. Only POST create, start and restart can be denied. Every other call and every response passes, even on internal errors.
- Fail closed on gated paths. Unparseable requests, panics and missing
containers deny. Only genuine "could not reach" errors follow
failClosed. - Match dockerd's router. Any
/v[0-9.]+prefix and container names containing/are classified exactly as dockerd routes them. - Verify what runs. Only the digest dockerd resolved counts, never a platform child whose selection imagegate cannot see.
- Registry data is hostile. Reads are bounded, annotations are never trusted for decisions, and the verified statement is what's checked.
Known gaps#
These run image code without a create or start API call, or sit outside what an image gate can see.
| Gap | Impact | Mitigation |
|---|---|---|
An allowed image run with --privileged or -v /:/host |
Can edit the policy or stop imagegate | Planned v1.1 container-config rules |
ctr, nerdctl, Podman on the same host |
Bypass outside Docker | Remove or restrict those tools |
| Daemon-initiated restarts (restart policies) | No API call to gate | Containers predating imagegate keep restarting until started via the API |
docker build |
RUN executes the FROM image in BuildKit |
Restrict builds on enforced hosts |
docker plugin install |
Runs a plugin image; /plugins/* is never gated |
Restrict plugin management |
swarm init + services create |
Task containers are created internally | Disable Swarm on enforced hosts until v1.1 |
PUT /containers/{id}/archive |
Can change a created container's files before start | Restrict API access |
| Revoked signing identity | Cached allows linger up to allowTTL |
Remove the identity (changes the policy hash) or imagegate cache purge |
failClosed: false |
Unreachable registries allow | Keep true for any registry attackers can influence |
Not a boundary against full API access
Anyone who can talk to the Docker API can use the paths above, or run an
allowed image with --privileged. imagegate raises the bar against
unsigned and tampered images; it does not make API access safe.
Hardening the plugin itself#
- Policy, overrides and keys root-owned, mode 0644 (keys 0600). Override files that are not root-owned or are group/world-writable are ignored.
- Outbound calls only to configured registries and Sigstore endpoints.
- Verify the imagegate binary itself at install with your configuration management; release checksums are published with each release.
- The systemd unit runs with no capabilities,
NoNewPrivilegesandProtectSystem=strict.
Reporting vulnerabilities#
See SECURITY.md. Report privately through GitHub security advisories, not issues.