Files
doos/CHANGELOG.md
T
retoorandClaude Sonnet 5 d1541b77e6
ci / test (push) Waiting to run
ci / audit (push) Waiting to run
ci / build (push) Successful in 1m25s
ci / valgrind (push) Successful in 2m37s
Add --mount/--davmount WebDAV auto-mount via a managed, verified rclone
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-25 08:05:02 +01:00

13 KiB

Changelog

Docs: README · SPEC · ARCHITECTURE · RESEARCH · COMPARISON · AGENTS · CHANGELOG · CI

1.6.0 - 2026-10-25

  • --mount/--davmount with a dav://, davs://, http:// or https:// source: auto-mounts WebDAV. doos downloads, GPG-verifies against a pinned key and installs rclone once under $DOOS_HOME/tools/ (never the system, never PATH, same trust model as the catalog images), then drives it on the host with an on-the-fly connection string (no config file, password passed through rclone obscure, never on the mount's command line) before the container's namespaces exist. The mount is deduplicated by target (url + credentials + vendor), reused across containers and attaches, and runs detached so it outlives the attach that created it. --dav-user, --dav-pass, --dav-vendor and --dav-insecure configure a target without putting credentials in the URL. Tracked as gap G13 in RESEARCH; measured there against a local rclone serve webdav fixture (install, reuse at ~40 ms, write-back durability, and each failure mode: wrong credentials, unreachable server, non-WebDAV endpoint).
  • doos davmount list / doos davmount umount [--yes] ID: inspect or tear down a managed WebDAV mount; dry-run by default like delete/image delete.
  • Fix (found while building the above): the classic --mount SRC:DST[:ro] could not take credentials with :/; in them because mounts were serialized as one delimited line; container meta now stores mounts as indexed keys (one field per line), with the old single-line format still read for containers created under 1.5.0.
  • Refactor: curl/gpg download-and-verify helpers moved from image.cpp into util.{hpp,cpp} (fetchText, fetchFile, TempDir, isHex64, verifyDetachedSignature, verifyClearsignedSignature) so davmount.cpp reuses the exact same, already-tested verification code instead of a second copy; no behavior change (full image signature test suite re-passes).
  • New dependency, only for davmount: unzip (to unpack rclone's release archive) and fusermount3/fusermount (to unmount it); documented in README/AGENTS.
  • Tests: 10 new end-to-end checks against a real local WebDAV server (read, write durability, idempotent reuse, --davmount with --dav-user/--dav-pass, read-only, wrong-password classification, unknown vendor rejected, davmount list/umount).
  • Docs: COMPARISON section 4's "Where Docker is better" no longer lists bind mounts as a doos gap (stale since 1.5.0); charts and generated numbers re-measured.

1.5.0 - 2026-10-24

  • --mount SRC:DST[:ro] (repeatable, max 8): bind-mounts a host directory into the container, outside the --size cap. Lets a container reach storage that is not local, for example a WebDAV share mounted on the host first with rclone mount or davfs2; doos never speaks a network filesystem protocol itself, it only bind-mounts what the host already mounted. Changeable like --memory/--pids/--cpus: replaces the whole mount list, applies at the next start. Tracked as gap G12 in RESEARCH; 5 new end-to-end checks (read, write, read-only, missing source rejected, too many rejected).
  • Docs: COMPARISON section 1 and the gaps list updated (doos now has host-dir bind mounts); charts and generated numbers re-measured (make bench && make charts).

1.4.0 - 2026-10-24

  • CI: .gitea/workflows/ci.yml (Gitea Actions) runs build, valgrind, test and audit on every push. build/valgrind run on any Docker-mode runner; test/audit need a self-hosted host-mode runner (real namespaces, cgroup v2 delegation, the AppArmor profile), documented with its one-time setup in the new docs/CI.md. Every step wraps its own timeout, since Gitea Actions parses but does not enforce timeout-minutes/concurrency (checked against the 1.25 docs).
  • Fixed, from review2.md: parseSize (src/util.cpp) overflowed silently on an oversized input (--size 16777217t was accepted as exactly 1.0T instead of rejected); now checked before the shift and rejected. Tracked as gap G9 in RESEARCH; regression case added to tests/run.sh.
  • Fixed, from review2.md: newuidmap, newgidmap, slirp4netns and pasta were each pinned to one hardcoded /usr/bin/... path; they now go through resolveBinary() (state-dir override, then a fixed list of system directories), the same resolution curl/tar/sha256sum/gpg already used. Tracked as gap G10.
  • Docs: the setns-before-hardening ordering invariant in Sandbox::join and Sandbox::start (seccomp denies setns, and a filter is inherited for life) is now a comment at both call sites, not only in reviewer heads. The hand-rolled Alpine/Debian catalog parsers are logged as an accepted trade-off, gap G11, rather than left undocumented.
  • Added LICENSE (MIT).
  • Docs: README's two overlapping, partly stale intro blocks (a leftover currently 1.1.3 version line, a narrower duplicate usage example) collapsed into one accurate one.

1.3.1 - 2026-10-24

  • Docs: gap G8 (fsutil::mkdirs following a planted symlink, RESEARCH) marked fixed, re-measured with make -C audit/CVE-2021-30465 test (PASS); removed from COMPARISON's gaps list. The fix itself shipped in 1.3.0 as part of the security-review hardening; this corrects the docs to match.

1.3.0 - 2026-10-24

  • Security review applied (review.md): slirp4netns, pasta, newuidmap and newgidmap are never searched on PATH; they exec via absolute paths with availability checked up front, and the helpers run with a scrubbed PATH.
  • Compat-directory mounts pin the parent through an O_PATH fd so a symlink swap between check and use cannot happen (TOCTOU); symlinks whose target cannot be pinned are not recreated, fail closed instead.
  • --i-understand is now required for --hardening relaxed and --net host; reduced sandboxing is also reported loudly at attach time.
  • Tests: the e2e suite covers all of the above (passed=88 failed=0). Docs: RESEARCH, SPEC, README updated in the same change.

1.2.1 - 2026-10-23

  • scripts/release.sh: commit trailer model name corrected (no functional change).

1.2.0 - 2026-10-23

  • audit/: 10 more named, sourced CVEs (18 total): the overlayfs-in-unprivileged-userns family (CVE-2021-3493, CVE-2023-2640, CVE-2023-32629, CVE-2015-1328, directly doos's own mount on every attach), CVE-2022-0492 (cgroup v1 release_agent; doos mounts no /sys), CVE-2022-27650 (inheritable capabilities at container start), CVE-2019-16884 and CVE-2023-28642 (runc's /proc mount-target handling, tested against doos's own /proc mount), CVE-2018-12020 (GnuPG SigSpoof, static check of the exact gpg invocation in src/image.cpp), CVE-2020-7039 (libslirp memory-safety cluster, version check against slirp4netns --version).

1.1.5 - 2026-10-23

  • audit/: 8 named, sourced CVEs relevant to doos's own mechanisms (overlay writes, tar extraction, mount/directory creation, net namespace sharing, the mount-family seccomp denylist, kernel user-namespace exposure), each with its own README.md, Makefile and non-destructive reproduce.sh against build/doos. make audit runs them concurrently (-j8, recursive make); make -C audit list|report also available. Kernel memory-corruption CVEs (Dirty Pipe, Dirty COW, legacy_parse_param) are checked by kernel version only, no exploit code.
  • Found by the audit and disclosed: fsutil::mkdirs follows a symlink planted at a container's path, so a symlink under $DOOS_HOME/containers/<name> redirects where that container's state is written (low severity: needs write access to the caller's own $DOOS_HOME). Tracked as gap G8 in RESEARCH and in COMPARISON; not yet fixed.
  • Docs: scripts/check-docs.sh excludes audit/*.md (a separate, self-contained doc set); README.md and AGENTS.md link to audit/README.md.

1.1.4 - 2026-10-23

  • Docs: COMPARISON section 6.1 answers whether doos is a security-wise Docker replacement (same class as rootless Podman, not for untrusted code), summarized in the README safety summary.

1.1.3 - 2026-10-23

  • Charts: startup time, executable size and CPU limit as SVG (light and dark palettes, doos highlighted), embedded in COMPARISON and RESEARCH.
  • Reproducible measurements: scripts/bench.sh writes docs/charts/bench.json; docs/charts/make_charts.py builds the charts and rewrites every generated number and table in the documents from it, so text, tables and charts cannot drift apart.
  • Makefile wrapper (make help), expanded .gitignore.

1.1.2 - 2026-10-23

  • Docs: new COMPARISON (doos against Docker, rootless Docker, Podman, bubblewrap, systemd-nspawn, LXC/Incus, Apptainer, Distrobox/Toolbx, gVisor, Kata/Firecracker) with sourced pros and cons, startup and disk measurements against Docker, Podman and bubblewrap on the same machine, a gaps list tied to code, and a conclusion.
  • Docs: every document now has a navigation line and links to every other document. scripts/check-docs.sh enforces it (and that relative links resolve) and runs inside scripts/release.sh.

1.1.1 - 2026-10-23

  • doos apparmor prints a profile for the exact path of the running binary (own profile name per path, so several installs coexist). A start that fails because of AppArmor now prints the install command instead of only mount bind /: Permission denied. Verified with a copy in ~/.local/bin.
  • apparmor/doos (packaging) covers more standard install paths.
  • Docs: Networking section with a verified example per mode (slirp, pasta, host, none), the inbound/loopback behavior of each, and the pasta port-detection delay.
  • Tests: 86 checks (adds apparmor output, none, slirp has no inbound path, pasta container to container).

1.1.0 - 2026-10-23

  • Limits: --memory, --pids, --cpus (cgroup v2; whole-container OOM kill; reports OOM kills and pid-limit hits). Later attaches run in their own cgroup leaf with the same limits.
  • Hardening (default): Docker's default capability set, a seccomp filter (arch check, x32 guard, clone3 ENOSYS, no nested user namespaces, no mounts/keyrings/bpf/perf/io_uring/...), host /etc allowlist. --hardening relaxed turns it off per container.
  • Networking: --net pasta (host-like reachability, private namespace and abstract sockets). --net host now prints a note.
  • Size cap: measured from inside the id map (counts other uids), paced by scan cost (2 s floor), RLIMIT_FSIZE bounds single files.
  • Images: Debian in the catalog (debian, debian-RELEASE); Alpine and Ubuntu signatures verified against pinned key fingerprints.
  • Fix: a failed get_or_create no longer leaves an unreadable container directory behind.
  • Tests: 83 end-to-end checks.

1.0.0 - 2026-10-23

Breaking: state layout changed (private /etc, meta keys). Containers from 0.x must be deleted and recreated.

  • Images: doos image list|add|delete, --image NAME on get_or_create/attach (fetched on demand). Catalog: alpine, ubuntu, ubuntu-VERSION; also https URL with --sha256, or a local tarball. sha256 verified before extraction.
  • --size: cap for what a container writes (default 4g). Warns at 80%, freezes at 100% via cgroup v2, thaws below 95%.
  • --ids: subuid mapping through newuidmap/newgidmap by default (chown, su and apt's _apt work); falls back to one id.
  • Host mode fixes: directory skeleton so host-owned directories are writable, private copy of /etc, pre-seeded /var and dpkg state. apt-get install now completes.
  • Deleting trees with subuid-owned files works (runs inside the id map).
  • Usage measurement counts hard links once.
  • Tests: 56 end-to-end checks, including real image downloads, apt/apk installs and the size freeze.

0.1.3 - 2026-10-23

  • Docs: field trial of apt and common tools, new gap G7 (host-owned lower layer), README limits section. No code change.

0.1.2 - 2026-10-23

  • Docs: researched solutions for all known gaps (G1 to G6) in docs/RESEARCH.md, with measurements. Nothing implemented yet.

0.1.1 - 2026-10-23

  • Docs: AGENTS.md release workflow, ARCHITECTURE.md, expanded README, this changelog.
  • Tooling: scripts/release.sh (bump, build, test, commit, tag).

0.1.0 - 2026-10-23

  • First release: list, get_or_create, attach, delete.
  • overlayfs over host /usr /etc /opt, user/mount/pid/uts/ipc/net namespaces.
  • Networking: slirp4netns (default), host, none.
  • End-to-end test suite and AppArmor profile for Ubuntu 24.04+.