From 183ce5cbbcb3fce692f2eaca2ebf2740400a1738 Mon Sep 17 00:00:00 2001 From: aevesdocker Date: Wed, 1 Apr 2026 16:31:46 +0100 Subject: [PATCH 1/4] Compose security --- .../manuals/compose/how-tos/oci-artifact.md | 1 + content/manuals/compose/how-tos/production.md | 1 + .../manuals/compose/how-tos/use-secrets.md | 1 + content/manuals/compose/release-notes.md | 2 +- .../compose/support-and-feedback/_index.md | 2 +- content/manuals/compose/trust-model.md | 119 ++++++++++++++++++ 6 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 content/manuals/compose/trust-model.md diff --git a/content/manuals/compose/how-tos/oci-artifact.md b/content/manuals/compose/how-tos/oci-artifact.md index b90028cfc793..fa2e96d1585a 100644 --- a/content/manuals/compose/how-tos/oci-artifact.md +++ b/content/manuals/compose/how-tos/oci-artifact.md @@ -145,6 +145,7 @@ $ docker compose publish -y username/my-compose-app:latest ## Next steps +- [Familiarise yourself with Compose's trust model](/manuals/compose/trust-model.md) - [Learn about OCI artifacts in Docker Hub](/manuals/docker-hub/repos/manage/hub-images/oci-artifacts.md) - [Compose publish command](/reference/cli/docker/compose/publish/) - [Understand `include`](/reference/compose-file/include.md) diff --git a/content/manuals/compose/how-tos/production.md b/content/manuals/compose/how-tos/production.md index d2c8e4189942..a075ac8d79db 100644 --- a/content/manuals/compose/how-tos/production.md +++ b/content/manuals/compose/how-tos/production.md @@ -68,5 +68,6 @@ commands work with no further configuration. ## Next steps +- [Familiarise yourself with Compose's trust model](/manuals/compose/trust-model.md) - [Using multiple Compose files](multiple-compose-files/_index.md) diff --git a/content/manuals/compose/how-tos/use-secrets.md b/content/manuals/compose/how-tos/use-secrets.md index 72886b135734..d4f8fdc0d5ea 100644 --- a/content/manuals/compose/how-tos/use-secrets.md +++ b/content/manuals/compose/how-tos/use-secrets.md @@ -109,6 +109,7 @@ secrets: ## Resources +- [Familiarise yourself with Compose's trust model](/manuals/compose/trust-model.md) - [Secrets top-level element](/reference/compose-file/secrets.md) - [Secrets attribute for services top-level element](/reference/compose-file/services.md#secrets) - [Build secrets](https://docs.docker.com/build/building/secrets/) diff --git a/content/manuals/compose/release-notes.md b/content/manuals/compose/release-notes.md index aef0b8ae9022..c6055dbd2f0f 100644 --- a/content/manuals/compose/release-notes.md +++ b/content/manuals/compose/release-notes.md @@ -1,6 +1,6 @@ --- title: Release notes -weight: 80 +weight: 90 params: sidebar: goto: "https://github.com/docker/compose/releases" diff --git a/content/manuals/compose/support-and-feedback/_index.md b/content/manuals/compose/support-and-feedback/_index.md index 175836c6b405..cda0bf5b3042 100644 --- a/content/manuals/compose/support-and-feedback/_index.md +++ b/content/manuals/compose/support-and-feedback/_index.md @@ -2,5 +2,5 @@ build: render: never title: Support and feedback -weight: 70 +weight: 80 --- \ No newline at end of file diff --git a/content/manuals/compose/trust-model.md b/content/manuals/compose/trust-model.md new file mode 100644 index 000000000000..763c55517102 --- /dev/null +++ b/content/manuals/compose/trust-model.md @@ -0,0 +1,119 @@ +--- +title: Trust model for Compose files +weight: 70 +description: Learn how Docker Compose treats Compose files as trusted input and what this means when using files you did not author. +keywords: compose, security, trust model, oci, remote, registry, include, extends, supplu chain, trust, best practices +--- + +Docker Compose treats every Compose file as trusted input. When a Compose file +requests elevated privileges, host filesystem access, or any other +configuration, Compose applies it as written. This is the same behavior as +passing flags directly to `docker run`. + +This means that any Compose file you run, whether it lives on your local +filesystem, in a Git repository, or in an OCI registry, has full control over +how containers interact with your host. The security boundary is not where the file comes from but whether you trust the author. + +Evaluating trust means asking: do you know who authored this file, can you verify it hasn't changed since you last reviewed it, and do you understand every privilege it requests? + +## The dependency chain + +A Compose application can be assembled from multiple sources. The +[`include`](/reference/compose-file/include.md) directive imports entire Compose +files, while [`extends`](/reference/compose-file/services.md#extends) inherits +configuration from a specific service in another file. Both support remote +references and can be chained: + +```text +Your command + └─ compose.yaml (local or remote) + ├─ services, volumes, networks (direct config) + ├─ include: + │ └─ oci://registry.example.com/base:v2 (remote dependency) + │ └─ services, volumes, networks (indirect config) + └─ services: + └─ app: + └─ extends: + └─ file: oci://registry.example.com/templates:v1 + └─ service: webapp (inherited config) +``` + +Each level has the same capabilities. The top-level file you inspect may appear +safe while a nested `include` or `extends` introduces services with elevated +privileges, host bind mounts, or untrusted images. These dependencies can also +change independently. For example, a tag you trusted last week may point to different +content today. Risky settings can be introduced by a nested dependency that you never +see unless you inspect the fully resolved output. + +> [!IMPORTANT] +> +> Compose warns you when a configuration references remote sources. Do not +> accept this without understanding every reference in the chain. + +## Best practices + +### Inspect the full configuration + +To see exactly what Compose applies, including all resolved `includes`, +`extends`, merged overrides, and interpolated variables, use: + +```console +$ docker compose config +``` + +For remote references: + +```console +$ docker compose -f oci://registry.example.com/myapp:latest config +``` + +Review this output before running `up` or `create`, especially when the +configuration comes from a source you have not audited. + +#### Fields to look out for + +A Compose configuration has broad control over how containers interact with the +host. The following is a non-exhaustive list of fields that carry security +implications when set by an untrusted author: + +| Field | Effect | +|-------|--------| +| `privileged` | Grants the container full access to the host | +| `cap_add` | Adds Linux capabilities such as `SYS_ADMIN` or `NET_RAW` | +| `security_opt` | Configures security profiles including seccomp and AppArmor | +| `volumes` / bind mounts | Mounts host directories into the container | +| `network_mode: host` | Shares the host network stack | +| `pid: host` | Shares the host PID namespace | +| `devices` | Exposes host devices to the container | +| `image` | Pulls and runs an arbitrary container image | + +When in doubt, look up the effect of any unfamiliar field before running the configuration. + +### CI/CD environments + +Automated pipelines are particularly sensitive because they often run with +access to credentials, cloud provider tokens, or Docker sockets. + +- Avoid referencing public or unverified Compose configurations in automated + pipelines. +- Pin all remote references to reviewed digests, not tags. Tags are mutable; digests are immutable. +- Gate updates behind your normal code review process. +- Use read-only Docker socket mounts where possible to limit your risk. + +### Other + +- Use a private registry: Host OCI artifacts on a registry your + organization controls. Restrict who can push to it. +- Audit transitive dependencies: Check every remote `include` and `extends` + reference in the chain, not just the top-level file. +- Review all Compose confirmation prompts: When loading remote Compose files, + Compose displays confirmation prompts for interpolation variables, environment + values, and remote includes. Review these before accepting. + +## Further reading + +- [OCI artifact applications](/manuals/compose/how-tos/oci-artifact.md) +- [Use Compose in production](/manuals/compose/how-tos/production.md) +- [`include` reference](/reference/compose-file/include.md) +- [`extends` reference](/reference/compose-file/services.md#extends) +- [Manage secrets in Compose](/manuals/compose/how-tos/use-secrets.md) \ No newline at end of file From 7f968ccbbca724a10bfa968abdbde5cea59c69e9 Mon Sep 17 00:00:00 2001 From: aevesdocker Date: Wed, 1 Apr 2026 16:38:45 +0100 Subject: [PATCH 2/4] fix terribly critical typo --- content/manuals/compose/trust-model.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/manuals/compose/trust-model.md b/content/manuals/compose/trust-model.md index 763c55517102..8d4520aedf0f 100644 --- a/content/manuals/compose/trust-model.md +++ b/content/manuals/compose/trust-model.md @@ -2,7 +2,7 @@ title: Trust model for Compose files weight: 70 description: Learn how Docker Compose treats Compose files as trusted input and what this means when using files you did not author. -keywords: compose, security, trust model, oci, remote, registry, include, extends, supplu chain, trust, best practices +keywords: compose, security, trust model, oci, remote, registry, include, extends, supply chain, trust, best practices --- Docker Compose treats every Compose file as trusted input. When a Compose file From 71c2d11c47f0fd1c3a6cfca46831b4814a84b88a Mon Sep 17 00:00:00 2001 From: aevesdocker Date: Thu, 2 Apr 2026 10:01:59 +0100 Subject: [PATCH 3/4] feedback --- content/manuals/compose/how-tos/oci-artifact.md | 2 +- content/manuals/compose/how-tos/production.md | 2 +- content/manuals/compose/how-tos/use-secrets.md | 2 +- content/manuals/compose/trust-model.md | 17 ++++++++++++++--- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/content/manuals/compose/how-tos/oci-artifact.md b/content/manuals/compose/how-tos/oci-artifact.md index fa2e96d1585a..6a2a6c669ee9 100644 --- a/content/manuals/compose/how-tos/oci-artifact.md +++ b/content/manuals/compose/how-tos/oci-artifact.md @@ -145,7 +145,7 @@ $ docker compose publish -y username/my-compose-app:latest ## Next steps -- [Familiarise yourself with Compose's trust model](/manuals/compose/trust-model.md) +- [Familiarize yourself with Compose's trust model](/manuals/compose/trust-model.md) - [Learn about OCI artifacts in Docker Hub](/manuals/docker-hub/repos/manage/hub-images/oci-artifacts.md) - [Compose publish command](/reference/cli/docker/compose/publish/) - [Understand `include`](/reference/compose-file/include.md) diff --git a/content/manuals/compose/how-tos/production.md b/content/manuals/compose/how-tos/production.md index a075ac8d79db..c520bf6105cd 100644 --- a/content/manuals/compose/how-tos/production.md +++ b/content/manuals/compose/how-tos/production.md @@ -68,6 +68,6 @@ commands work with no further configuration. ## Next steps -- [Familiarise yourself with Compose's trust model](/manuals/compose/trust-model.md) +- [Familiarize yourself with Compose's trust model](/manuals/compose/trust-model.md) - [Using multiple Compose files](multiple-compose-files/_index.md) diff --git a/content/manuals/compose/how-tos/use-secrets.md b/content/manuals/compose/how-tos/use-secrets.md index d4f8fdc0d5ea..2afec05e530c 100644 --- a/content/manuals/compose/how-tos/use-secrets.md +++ b/content/manuals/compose/how-tos/use-secrets.md @@ -109,7 +109,7 @@ secrets: ## Resources -- [Familiarise yourself with Compose's trust model](/manuals/compose/trust-model.md) +- [Familiarize yourself with Compose's trust model](/manuals/compose/trust-model.md) - [Secrets top-level element](/reference/compose-file/secrets.md) - [Secrets attribute for services top-level element](/reference/compose-file/services.md#secrets) - [Build secrets](https://docs.docker.com/build/building/secrets/) diff --git a/content/manuals/compose/trust-model.md b/content/manuals/compose/trust-model.md index 8d4520aedf0f..8dd377f12693 100644 --- a/content/manuals/compose/trust-model.md +++ b/content/manuals/compose/trust-model.md @@ -41,8 +41,7 @@ Your command Each level has the same capabilities. The top-level file you inspect may appear safe while a nested `include` or `extends` introduces services with elevated privileges, host bind mounts, or untrusted images. These dependencies can also -change independently. For example, a tag you trusted last week may point to different -content today. Risky settings can be introduced by a nested dependency that you never +change independently. Risky settings can be introduced by a nested dependency that you never see unless you inspect the fully resolved output. > [!IMPORTANT] @@ -96,10 +95,22 @@ access to credentials, cloud provider tokens, or Docker sockets. - Avoid referencing public or unverified Compose configurations in automated pipelines. -- Pin all remote references to reviewed digests, not tags. Tags are mutable; digests are immutable. - Gate updates behind your normal code review process. - Use read-only Docker socket mounts where possible to limit your risk. +## Pin remote references to digests + +Tags are mutable meaning anyone with push access to a registry can overwrite a tag silently, so a reference you reviewed last week may point to different content today. + +Digests are immutable. Instead of referencing by tag, pin to the digest. + +```yaml +include: + - oci://registry.example.com/base@sha256:a1b2c3d4... +``` + +Treat any update to a pinned digest as a code change. Make sure you review the new content before updating the reference. + ### Other - Use a private registry: Host OCI artifacts on a registry your From 9b704324e8d7e69ce898fa1286d7bf38d36164cb Mon Sep 17 00:00:00 2001 From: aevesdocker Date: Thu, 2 Apr 2026 10:15:04 +0100 Subject: [PATCH 4/4] missed # --- content/manuals/compose/trust-model.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/manuals/compose/trust-model.md b/content/manuals/compose/trust-model.md index 8dd377f12693..017883cb7aa4 100644 --- a/content/manuals/compose/trust-model.md +++ b/content/manuals/compose/trust-model.md @@ -98,7 +98,7 @@ access to credentials, cloud provider tokens, or Docker sockets. - Gate updates behind your normal code review process. - Use read-only Docker socket mounts where possible to limit your risk. -## Pin remote references to digests +### Pin remote references to digests Tags are mutable meaning anyone with push access to a registry can overwrite a tag silently, so a reference you reviewed last week may point to different content today.