docker.io/minio/minio
validated pin current tags: RELEASE.2025-09-07T16-13-09Z
minio — minimum Linux capabilities, derived by drop-test against the default single-node invocation (`server /data`). ZERO-cap: cap_drop:[ALL] with no cap_add — the jellyfin-class story (a single static Go binary running AS ROOT with no privilege drop, serving the unprivileged :9000, writing only to its /data VOLUME; the whole Docker default set is over-grant, residual risk = the root uid, harden further with user:). Immutable RELEASE.* tag. See criteria/docker.io/minio/minio.md. filesystem: read_only:true, tmpfs:[]. minio's only writes are to its object store /data (a persistent VOLUME, not tmpfs); it runs correctly under a read-only rootfs with no additional tmpfs. /tmp was drop-tested and is NOT required. Derived by drop-test.
Use it
services:
minio:
image: docker.io/minio/minio:RELEASE.2025-09-07T16-13-09Z
cap_drop: [ALL]
security_opt: ["no-new-privileges:true"]
read_only: true
This profile has multiple dimensions and is applied as a unit. Dimensions can interact — a capability can be required only because of a sibling read-only/tmpfs recommendation — so where they do, the minimum was derived under the sibling dimension's context. See the criteria doc and each dimension's recorded invocation below before applying them separately.
Dimension: capabilities
cap_drop: ALL (no cap_add)
| tool | container-sec-derive 0.7.0 |
|---|---|
| observer | drop-test |
| validated image | docker.io/minio/minio@sha256:14cea493d9a3… |
| validated date | 2026-07-16 |
| confidence | high |
| validated via | drop-test, ci-smoke |
| workload | profiles/workloads/minio.sh |
| workload sha256 | 1e722eac496a… |
| ig version | v0.51.0 |
Drop-test evidence
Each candidate removed in turn, the container restarted, and the workload re-verified.
| Removed | Verdict | Observed |
|---|---|---|
CHOWN | removable | correct: S3 mb/put/get round-trip ok |
DAC_OVERRIDE | removable | correct: S3 mb/put/get round-trip ok |
FSETID | removable | correct: S3 mb/put/get round-trip ok |
FOWNER | removable | correct: S3 mb/put/get round-trip ok |
MKNOD | removable | correct: S3 mb/put/get round-trip ok |
NET_RAW | removable | correct: S3 mb/put/get round-trip ok |
SETGID | removable | correct: S3 mb/put/get round-trip ok |
SETUID | removable | correct: S3 mb/put/get round-trip ok |
SETFCAP | removable | correct: S3 mb/put/get round-trip ok |
SETPCAP | removable | correct: S3 mb/put/get round-trip ok |
NET_BIND_SERVICE | removable | correct: S3 mb/put/get round-trip ok |
SYS_CHROOT | removable | correct: S3 mb/put/get round-trip ok |
KILL | removable | correct: S3 mb/put/get round-trip ok |
AUDIT_WRITE | removable | correct: S3 mb/put/get round-trip ok |
Recorded invocation (run_config)
The minimum is valid for this invocation; a different user:, volume state, or entrypoint can change it.
| command | server/data |
|---|---|
| security_opt | no-new-privileges:true |
| env | MINIO_ROOT_USERMINIO_ROOT_PASSWORD |
Workload script (profiles/workloads/minio.sh)
#!/usr/bin/env bash
# Workload exerciser for the minio reference image (single-node
# `server /data`).
#
# A real S3 round-trip via the pinned `mc` client run as a sidecar in the
# target's netns (the server image ships no client): make-bucket, pipe an
# object in, cat it back byte-identical. The MC_HOST_ env alias keeps mc
# config-free — the only writes are the object store's own.
#
# Required env: MINIOCONTAINER (target container name or id). The container
# is expected to run with MINIO_ROOT_USER=csdadmin /
# MINIO_ROOT_PASSWORD=CsdProbe-Pw-12345 (the derivation credentials).
set -euo pipefail
: "${MINIOCONTAINER:?MINIOCONTAINER must be set}"
C="${MINIOCONTAINER}"
MC_IMAGE="${CSD_PROBE_MC_IMAGE:-minio/mc@sha256:a7fe349ef4bd8521fb8497f55c6042871b2ae640607cf99d9bede5e9bdf11727}"
mcx() { docker run --rm --entrypoint /bin/sh --network "container:${C}" \
-e MC_HOST_csd=http://csdadmin:CsdProbe-Pw-12345@localhost:9000 "$MC_IMAGE" -c "$*"; }
deadline=$((SECONDS + 45))
until mcx 'mc ls csd/ >/dev/null 2>&1'; do
(( SECONDS >= deadline )) && { echo "minio never answered" >&2; exit 1; }
sleep 2
done
got="$(mcx 'mc mb -p csd/csdbucket >/dev/null 2>&1; echo csd-payload-42 | mc pipe csd/csdbucket/probe.txt >/dev/null 2>&1 && mc cat csd/csdbucket/probe.txt 2>/dev/null')"
if [ "$got" != "csd-payload-42" ]; then
echo "S3 round-trip failed (got: ${got:0:60})" >&2
exit 1
fi
Dimension: filesystem
read_only: true, no tmpfs
| tool | container-sec-derive 0.7.0 |
|---|---|
| observer | drop-test |
| validated image | docker.io/minio/minio@sha256:14cea493d9a3… |
| validated date | 2026-07-16 |
| confidence | high |
| validated via | drop-test, ci-smoke |
| workload | profiles/workloads/minio.sh |
| workload sha256 | 1e722eac496a… |
| ig version | v0.51.0 |
Drop-test evidence
Each candidate removed in turn, the container restarted, and the workload re-verified.
| Removed | Verdict | Observed |
|---|---|---|
/tmp | removable | correct: S3 mb/put/get round-trip ok |
Recorded invocation (run_config)
The minimum is valid for this invocation; a different user:, volume state, or entrypoint can change it.
| command | server/data |
|---|---|
| env | MINIO_ROOT_USERMINIO_ROOT_PASSWORD |
Workload script (profiles/workloads/minio.sh)
#!/usr/bin/env bash
# Workload exerciser for the minio reference image (single-node
# `server /data`).
#
# A real S3 round-trip via the pinned `mc` client run as a sidecar in the
# target's netns (the server image ships no client): make-bucket, pipe an
# object in, cat it back byte-identical. The MC_HOST_ env alias keeps mc
# config-free — the only writes are the object store's own.
#
# Required env: MINIOCONTAINER (target container name or id). The container
# is expected to run with MINIO_ROOT_USER=csdadmin /
# MINIO_ROOT_PASSWORD=CsdProbe-Pw-12345 (the derivation credentials).
set -euo pipefail
: "${MINIOCONTAINER:?MINIOCONTAINER must be set}"
C="${MINIOCONTAINER}"
MC_IMAGE="${CSD_PROBE_MC_IMAGE:-minio/mc@sha256:a7fe349ef4bd8521fb8497f55c6042871b2ae640607cf99d9bede5e9bdf11727}"
mcx() { docker run --rm --entrypoint /bin/sh --network "container:${C}" \
-e MC_HOST_csd=http://csdadmin:CsdProbe-Pw-12345@localhost:9000 "$MC_IMAGE" -c "$*"; }
deadline=$((SECONDS + 45))
until mcx 'mc ls csd/ >/dev/null 2>&1'; do
(( SECONDS >= deadline )) && { echo "minio never answered" >&2; exit 1; }
sleep 2
done
got="$(mcx 'mc mb -p csd/csdbucket >/dev/null 2>&1; echo csd-payload-42 | mc pipe csd/csdbucket/probe.txt >/dev/null 2>&1 && mc cat csd/csdbucket/probe.txt 2>/dev/null')"
if [ "$got" != "csd-payload-42" ]; then
echo "S3 round-trip failed (got: ${got:0:60})" >&2
exit 1
fi
Evidence & provenance
- Validation criteria — per-image scenarios and pass criteria
- Profile source in the repository
- Version history — every previously published pin, with the full profile as validated against it
Raw profile YAML
# minio — minimum Linux capabilities, derived by drop-test against the
# default single-node invocation (`server /data`). ZERO-cap: cap_drop:[ALL]
# with no cap_add — the jellyfin-class story (a single static Go binary
# running AS ROOT with no privilege drop, serving the unprivileged :9000,
# writing only to its /data VOLUME; the whole Docker default set is
# over-grant, residual risk = the root uid, harden further with user:).
# Immutable RELEASE.* tag. See criteria/docker.io/minio/minio.md.
# filesystem: read_only:true, tmpfs:[]. minio's only writes are to its object
# store /data (a persistent VOLUME, not tmpfs); it runs correctly under a
# read-only rootfs with no additional tmpfs. /tmp was drop-tested and is NOT
# required. Derived by drop-test.
#
schema_version: "1.5"
image: docker.io/minio/minio
reference_url: https://tmatens.github.io/container-security-profiles/profiles/docker.io/minio/minio.html
applies_to:
tags: ["RELEASE.2025-09-07T16-13-09Z"]
status: validated
dimensions:
capabilities:
cap_drop: [ALL]
cap_add: []
derivation:
tool: container-sec-derive
tool_version: "0.7.0"
sidecar_schema_version: "1.5"
observer: drop-test
validated_image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
validated_date: "2026-07-16"
duration_seconds: 300
confidence: high
workload: profiles/workloads/minio.sh
workload_sha256: "1e722eac496a234dd1f454b222c25aa486ca57ec995d7f7aa0c7cebf6e897e1b"
validated_via: [drop-test, ci-smoke]
observation_backend:
ig_version: v0.51.0
gadgets: []
run_config:
user: ""
command: ["server", "/data"]
entrypoint: ""
network: ""
pid: ""
devices: []
security_opt: ["no-new-privileges:true"]
mounts: []
env: [MINIO_ROOT_USER, MINIO_ROOT_PASSWORD]
drop_test:
checks:
- {removed: CHOWN, required: false, observed: "correct: S3 mb/put/get round-trip ok"}
- {removed: DAC_OVERRIDE, required: false, observed: "correct: S3 mb/put/get round-trip ok"}
- {removed: FSETID, required: false, observed: "correct: S3 mb/put/get round-trip ok"}
- {removed: FOWNER, required: false, observed: "correct: S3 mb/put/get round-trip ok"}
- {removed: MKNOD, required: false, observed: "correct: S3 mb/put/get round-trip ok"}
- {removed: NET_RAW, required: false, observed: "correct: S3 mb/put/get round-trip ok"}
- {removed: SETGID, required: false, observed: "correct: S3 mb/put/get round-trip ok"}
- {removed: SETUID, required: false, observed: "correct: S3 mb/put/get round-trip ok"}
- {removed: SETFCAP, required: false, observed: "correct: S3 mb/put/get round-trip ok"}
- {removed: SETPCAP, required: false, observed: "correct: S3 mb/put/get round-trip ok"}
- {removed: NET_BIND_SERVICE, required: false, observed: "correct: S3 mb/put/get round-trip ok"}
- {removed: SYS_CHROOT, required: false, observed: "correct: S3 mb/put/get round-trip ok"}
- {removed: KILL, required: false, observed: "correct: S3 mb/put/get round-trip ok"}
- {removed: AUDIT_WRITE, required: false, observed: "correct: S3 mb/put/get round-trip ok"}
filesystem:
read_only: true
tmpfs: []
derivation:
tool: container-sec-derive
tool_version: "0.7.0"
sidecar_schema_version: "1.5"
observer: drop-test
validated_image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
validated_date: "2026-07-16"
duration_seconds: 3
confidence: high
workload: profiles/workloads/minio.sh
workload_sha256: "1e722eac496a234dd1f454b222c25aa486ca57ec995d7f7aa0c7cebf6e897e1b"
validated_via: [drop-test, ci-smoke]
observation_backend:
ig_version: v0.51.0
gadgets: []
run_config:
user: ""
command: [server, /data]
entrypoint: ""
network: ""
pid: ""
devices: []
security_opt: []
mounts: []
env: [MINIO_ROOT_USER, MINIO_ROOT_PASSWORD]
drop_test:
checks:
- {removed: /tmp, required: false, observed: "correct: S3 mb/put/get round-trip ok"}