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

toolcontainer-sec-derive 0.7.0
observerdrop-test
validated imagedocker.io/library/mongo@sha256:3ce3de7f40e9…
validated date2026-07-16
confidencehigh
validated viadrop-test, ci-smoke
workloadprofiles/workloads/mongo.sh
workload sha25692f7ac2097a9…
ig versionv0.51.0

Drop-test evidence

Each candidate removed in turn, the container restarted, and the workload re-verified.

RemovedVerdictObserved
CHOWNremovablecorrect: mongosh round-trip ok, mongod uid=999 (non-root)
DAC_OVERRIDEremovablecorrect: mongosh round-trip ok, mongod uid=999 (non-root)
FSETIDremovablecorrect: mongosh round-trip ok, mongod uid=999 (non-root)
FOWNERremovablecorrect: mongosh round-trip ok, mongod uid=999 (non-root)
MKNODremovablecorrect: mongosh round-trip ok, mongod uid=999 (non-root)
NET_RAWremovablecorrect: mongosh round-trip ok, mongod uid=999 (non-root)
SETGIDrequiredcontainer failed to start: error: failed switching to 'mongodb': operation not permitted
SETUIDrequiredcontainer failed to start: error: failed switching to 'mongodb': operation not permitted
SETFCAPremovablecorrect: mongosh round-trip ok, mongod uid=999 (non-root)
SETPCAPremovablecorrect: mongosh round-trip ok, mongod uid=999 (non-root)
NET_BIND_SERVICEremovablecorrect: mongosh round-trip ok, mongod uid=999 (non-root)
SYS_CHROOTremovablecorrect: mongosh round-trip ok, mongod uid=999 (non-root)
KILLremovablecorrect: mongosh round-trip ok, mongod uid=999 (non-root)
AUDIT_WRITEremovablecorrect: 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_optno-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

toolcontainer-sec-derive 0.7.0
observerdrop-test
validated imagedocker.io/library/mongo@sha256:3ce3de7f40e9…
validated date2026-07-16
confidencehigh
validated viadrop-test, ci-smoke
workloadprofiles/workloads/mongo.sh
workload sha25692f7ac2097a9…
ig versionv0.51.0

Drop-test evidence

Each candidate removed in turn, the container restarted, and the workload re-verified.

RemovedVerdictObserved
/tmprequiredcontainer 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

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"}