catalog / docker.io/library/mongo
docker.io/library/mongo
validated pin current tags: 8.0
mongo — minimum Linux capabilities, derived by drop-test against MongoDB's default (root-then-drop) invocation. This profile trims the full Docker default cap set 14 -> 2. capabilities: cap_drop:[ALL] + cap_add:[SETGID, SETUID]. The entrypoint starts as root, `find`-chowns /data/db + /data/configdb (a no-op — the image ships both pre-owned by the mongodb user, uid 999), best-effort chowns its stdio fds (`|| :`, never load-bearing), then re-execs itself as the mongodb user via gosu. Dropping either cap fails the gosu switch and the container never starts. Both are STARTUP caps, invisible to runtime observation — the mariadb/redis shape. NOT required: CHOWN (data dirs ship pre-owned; a FOREIGN-owned bind mount re-introduces it) and SYS_NICE — the official image test adds `--cap-add SYS_NICE` for NUMA hosts, but it is not in the Docker default set and mongod treats a failed setpriority as a warning; nothing beyond the gosu drop is load-bearing under this invocation. See criteria/docker.io/library/mongo.md. filesystem: read_only:true, tmpfs:[/tmp]. The data dirs /data/db and /data/configdb are declared VOLUMEs (persistent). Under a read-only rootfs mongod additionally needs /tmp writable — it creates its unix socket (/tmp/mongodb-27017.sock) there. Derived by drop-test.
Use it
services:
mongo:
image: docker.io/library/mongo:8.0
cap_drop: [ALL]
cap_add: [SETGID, SETUID]
security_opt: ["no-new-privileges:true"]
read_only: true
tmpfs:
- /tmp
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 + cap_add: SETGID, SETUID
| tool | container-sec-derive 0.7.0 |
|---|---|
| observer | drop-test |
| validated image | docker.io/library/mongo@sha256:3ce3de7f40e9… |
| validated date | 2026-07-16 |
| confidence | high |
| validated via | drop-test, ci-smoke |
| workload | profiles/workloads/mongo.sh |
| workload sha256 | 92f7ac2097a9… |
| 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: mongosh round-trip ok, mongod uid=999 (non-root) |
DAC_OVERRIDE | removable | correct: mongosh round-trip ok, mongod uid=999 (non-root) |
FSETID | removable | correct: mongosh round-trip ok, mongod uid=999 (non-root) |
FOWNER | removable | correct: mongosh round-trip ok, mongod uid=999 (non-root) |
MKNOD | removable | correct: mongosh round-trip ok, mongod uid=999 (non-root) |
NET_RAW | removable | correct: mongosh round-trip ok, mongod uid=999 (non-root) |
SETGID | required | container failed to start: error: failed switching to 'mongodb': operation not permitted |
SETUID | required | container failed to start: error: failed switching to 'mongodb': operation not permitted |
SETFCAP | removable | correct: mongosh round-trip ok, mongod uid=999 (non-root) |
SETPCAP | removable | correct: mongosh round-trip ok, mongod uid=999 (non-root) |
NET_BIND_SERVICE | removable | correct: mongosh round-trip ok, mongod uid=999 (non-root) |
SYS_CHROOT | removable | correct: mongosh round-trip ok, mongod uid=999 (non-root) |
KILL | removable | correct: mongosh round-trip ok, mongod uid=999 (non-root) |
AUDIT_WRITE | removable | correct: mongosh round-trip ok, mongod uid=999 (non-root) |
Recorded invocation (run_config)
The minimum is valid for this invocation; a different user:, volume state, or entrypoint can change it.
| security_opt | no-new-privileges:true |
|---|
Workload script (profiles/workloads/mongo.sh)
#!/usr/bin/env bash
# Workload exerciser for the mongo reference image.
#
# Drives a representative write/read round-trip via mongosh — insertOne,
# countDocuments, findOne read-back, drop — mirroring the official
# docker-library mongo-basics test shape (unauthenticated default invocation).
# Returns 0 if every step succeeded. The non-root privilege-drop (the
# entrypoint's gosu root->mongodb) is asserted by the drop-test correctness
# check (see the criteria doc), not here.
#
# Required env: MONGOCONTAINER (target container name or id).
set -euo pipefail
: "${MONGOCONTAINER:?MONGOCONTAINER must be set}"
C="${MONGOCONTAINER}"
deadline=$((SECONDS + 60))
# capture-then-match — never `producer | grep -q` under pipefail (grep's early
# exit SIGPIPEs the producer and a matching response reads as failure).
until grep -q 1 <<<"$(docker exec "$C" mongosh --quiet --eval 'db.runCommand({ping:1}).ok' 2>/dev/null)"; do
if (( SECONDS >= deadline )); then
echo "mongod did not answer ping in 60s" >&2
exit 1
fi
sleep 1
done
out="$(docker exec "$C" mongosh --quiet csdprobe --eval '
db.probe.insertOne({_id: "csd", v: 42});
const n = db.probe.countDocuments();
const v = db.probe.findOne({_id: "csd"}).v;
db.probe.drop();
print(n + ":" + v);' 2>&1 | tail -1)"
if [ "$out" != "1:42" ]; then
echo "workload round-trip failed (got: $out)" >&2
exit 1
fi
Dimension: filesystem
read_only: true + tmpfs: /tmp
| tool | container-sec-derive 0.7.0 |
|---|---|
| observer | drop-test |
| validated image | docker.io/library/mongo@sha256:3ce3de7f40e9… |
| validated date | 2026-07-16 |
| confidence | high |
| validated via | drop-test, ci-smoke |
| workload | profiles/workloads/mongo.sh |
| workload sha256 | 92f7ac2097a9… |
| 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 | required | container exited: {'t':{'$date':'2026-07-16T20:55:24.945+00:00'},'s':'F', 'c':'ASSERT', 'id':23092, 'ctx':'initandl |
Workload script (profiles/workloads/mongo.sh)
#!/usr/bin/env bash
# Workload exerciser for the mongo reference image.
#
# Drives a representative write/read round-trip via mongosh — insertOne,
# countDocuments, findOne read-back, drop — mirroring the official
# docker-library mongo-basics test shape (unauthenticated default invocation).
# Returns 0 if every step succeeded. The non-root privilege-drop (the
# entrypoint's gosu root->mongodb) is asserted by the drop-test correctness
# check (see the criteria doc), not here.
#
# Required env: MONGOCONTAINER (target container name or id).
set -euo pipefail
: "${MONGOCONTAINER:?MONGOCONTAINER must be set}"
C="${MONGOCONTAINER}"
deadline=$((SECONDS + 60))
# capture-then-match — never `producer | grep -q` under pipefail (grep's early
# exit SIGPIPEs the producer and a matching response reads as failure).
until grep -q 1 <<<"$(docker exec "$C" mongosh --quiet --eval 'db.runCommand({ping:1}).ok' 2>/dev/null)"; do
if (( SECONDS >= deadline )); then
echo "mongod did not answer ping in 60s" >&2
exit 1
fi
sleep 1
done
out="$(docker exec "$C" mongosh --quiet csdprobe --eval '
db.probe.insertOne({_id: "csd", v: 42});
const n = db.probe.countDocuments();
const v = db.probe.findOne({_id: "csd"}).v;
db.probe.drop();
print(n + ":" + v);' 2>&1 | tail -1)"
if [ "$out" != "1:42" ]; then
echo "workload round-trip failed (got: $out)" >&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
# mongo — minimum Linux capabilities, derived by drop-test against MongoDB's
# default (root-then-drop) invocation. This profile trims the full Docker default
# cap set 14 -> 2.
#
# capabilities: cap_drop:[ALL] + cap_add:[SETGID, SETUID]. The entrypoint starts
# as root, `find`-chowns /data/db + /data/configdb (a no-op — the image ships both
# pre-owned by the mongodb user, uid 999), best-effort chowns its stdio fds
# (`|| :`, never load-bearing), then re-execs itself as the mongodb user via gosu.
# Dropping either cap fails the gosu switch and the container never starts. Both
# are STARTUP caps, invisible to runtime observation — the mariadb/redis shape.
#
# NOT required: CHOWN (data dirs ship pre-owned; a FOREIGN-owned bind mount
# re-introduces it) and SYS_NICE — the official image test adds `--cap-add
# SYS_NICE` for NUMA hosts, but it is not in the Docker default set and mongod
# treats a failed setpriority as a warning; nothing beyond the gosu drop is
# load-bearing under this invocation. See criteria/docker.io/library/mongo.md.
# filesystem: read_only:true, tmpfs:[/tmp]. The data dirs /data/db and
# /data/configdb are declared VOLUMEs (persistent). Under a read-only rootfs
# mongod additionally needs /tmp writable — it creates its unix socket
# (/tmp/mongodb-27017.sock) there. Derived by drop-test.
#
schema_version: "1.5"
image: docker.io/library/mongo
reference_url: https://tmatens.github.io/container-security-profiles/profiles/docker.io/library/mongo.html
applies_to:
tags: ["8.0"]
status: validated
dimensions:
capabilities:
cap_drop: [ALL]
cap_add: [SETGID, SETUID]
derivation:
tool: container-sec-derive
tool_version: "0.7.0"
sidecar_schema_version: "1.5"
observer: drop-test
validated_image: docker.io/library/mongo@sha256:3ce3de7f40e914034b03b7dec654005ab54f7dc8306937e44ec6760d9e9409a1
validated_date: "2026-07-16"
duration_seconds: 300
confidence: high
workload: profiles/workloads/mongo.sh
workload_sha256: "92f7ac2097a9ea3b519c970470905331cae8dea8df0b08020327ba99d395d78d"
validated_via: [drop-test, ci-smoke]
observation_backend:
ig_version: v0.51.0
gadgets: []
run_config:
user: ""
command: []
entrypoint: ""
network: ""
pid: ""
devices: []
security_opt: ["no-new-privileges:true"]
mounts: []
env: []
drop_test:
checks:
- {removed: CHOWN, required: false, observed: "correct: mongosh round-trip ok, mongod uid=999 (non-root)"}
- {removed: DAC_OVERRIDE, required: false, observed: "correct: mongosh round-trip ok, mongod uid=999 (non-root)"}
- {removed: FSETID, required: false, observed: "correct: mongosh round-trip ok, mongod uid=999 (non-root)"}
- {removed: FOWNER, required: false, observed: "correct: mongosh round-trip ok, mongod uid=999 (non-root)"}
- {removed: MKNOD, required: false, observed: "correct: mongosh round-trip ok, mongod uid=999 (non-root)"}
- {removed: NET_RAW, required: false, observed: "correct: mongosh round-trip ok, mongod uid=999 (non-root)"}
- {removed: SETGID, required: true, observed: "container failed to start: error: failed switching to 'mongodb': operation not permitted"}
- {removed: SETUID, required: true, observed: "container failed to start: error: failed switching to 'mongodb': operation not permitted"}
- {removed: SETFCAP, required: false, observed: "correct: mongosh round-trip ok, mongod uid=999 (non-root)"}
- {removed: SETPCAP, required: false, observed: "correct: mongosh round-trip ok, mongod uid=999 (non-root)"}
- {removed: NET_BIND_SERVICE, required: false, observed: "correct: mongosh round-trip ok, mongod uid=999 (non-root)"}
- {removed: SYS_CHROOT, required: false, observed: "correct: mongosh round-trip ok, mongod uid=999 (non-root)"}
- {removed: KILL, required: false, observed: "correct: mongosh round-trip ok, mongod uid=999 (non-root)"}
- {removed: AUDIT_WRITE, required: false, observed: "correct: mongosh round-trip ok, mongod uid=999 (non-root)"}
filesystem:
read_only: true
tmpfs: [/tmp]
derivation:
tool: container-sec-derive
tool_version: "0.7.0"
sidecar_schema_version: "1.5"
observer: drop-test
validated_image: docker.io/library/mongo@sha256:3ce3de7f40e914034b03b7dec654005ab54f7dc8306937e44ec6760d9e9409a1
validated_date: "2026-07-16"
duration_seconds: 5
confidence: high
workload: profiles/workloads/mongo.sh
workload_sha256: "92f7ac2097a9ea3b519c970470905331cae8dea8df0b08020327ba99d395d78d"
validated_via: [drop-test, ci-smoke]
observation_backend:
ig_version: v0.51.0
gadgets: []
run_config:
user: ""
command: []
entrypoint: ""
network: ""
pid: ""
devices: []
security_opt: []
mounts: []
env: []
drop_test:
checks:
- {removed: /tmp, required: true, observed: "container exited: {'t':{'$date':'2026-07-16T20:55:24.945+00:00'},'s':'F', 'c':'ASSERT', 'id':23092, 'ctx':'initandl"}