# Security Policy ## Supported versions No version has been tagged yet (see `CHANGELOG.md`); this project is pre-1.0 (`README.md`'s "Status"). Only the latest commit on the default branch is supported — there is no LTS branch and no backport policy while the project is at `0.x`. ## What PackFS actually claims as a security boundary Stated precisely, per this project's documentation standard (`CLAUDE.md`), rather than a generic "we take security seriously": - **Path containment for `dir` mounts is a hard requirement** (`concept.md` Section 6, `CLAUDE.md`'s "Load-bearing constraints"). On Linux 5.6+, every lookup beneath a `dir` mount uses `openat2(RESOLVE_BENEATH | RESOLVE_NO_SYMLINKS)` to atomically block `..` escapes, symlink escapes, and the canonicalize-then-open TOCTOU window in one kernel call. `vfs_harden_process_with_landlock` (Section 6.2) is an additional, **opt-in** kernel-level layer — not applied automatically, since Landlock restrictions are cumulative, irreversible, and process-wide, which would be a surprising side effect for an embeddable library to trigger on its own. - **On platforms or kernels without `openat2`, containment falls back to per-component `O_NOFOLLOW` plus canonicalize-and-verify** (Section 6.3) — an accepted, **explicitly weaker** residual-risk posture, not a claim of equal strength. Code and documentation that describe this fallback as equivalent to the `openat2` path would themselves be a bug worth reporting. - **The VFS core canonicalizes `.`/`..` in the virtual namespace itself**, before any backend is reached, so a crafted path cannot escape a mount's prefix even when no host directory is involved. - **A pack file is treated as untrusted input unless it came from this run's own compaction** (Section 7). Every index entry's offsets and sizes are bounds-checked against the actual file/strings-region length before being trusted; a failed check invalidates the whole pack load. An externally-sourced pack additionally needs a checksum verified at load. Loading an attacker-supplied `.img` file that PackFS accepts without detecting corruption, or that causes an out-of-bounds read/write, is a security bug. - **Journal records are length/checksum self-describing** (Section 4.4), so replay stops cleanly at the first torn or corrupted record rather than reading past it. ## What PackFS explicitly does *not* claim Reporting these as vulnerabilities is not necessary — they are documented, known limitations, not silent gaps: - **`mode` (permission bits, symlinks, hard links) is stored and restored but not enforced.** Nothing in the VFS core interprets it as an access control boundary in v0 (`concept.md` Section 10). - **Cross-process concurrency is specified (an LMDB-style reader-table design, Section 5.6) but not implemented.** Two uncoordinated processes writing the same host directory through a `dir` mount are not synchronized against each other. - **`zip`/`tar` are permanently out of scope** (`CLAUDE.md`, "Project decisions that supersede concept.md") — there is no archive-format parsing code in this project to have a vulnerability in. ## Reporting a vulnerability Please do not open a public GitHub issue for a suspected security vulnerability. Once this repository has a hosting remote and private security advisories are available there, prefer that. Until then, or as an alternative, report privately to the maintainer: **retoor** — `retoor@molodetz.nl` When reporting, include: the affected function(s) or file(s), a minimal reproduction (ideally as a `tests/test_*.c`-style program using only the public API in `include/packfs.h`), and which of the guarantees above (or which `concept.md` section) you believe is violated — this project's own verification discipline (`make test`, ASan/UBSan/TSan per `CONTRIBUTING.md`) depends on being able to turn a report into a permanent regression test. ## Verification this project already does Every change to `src/upper.c`, `src/overlay.c`, or `src/vfs.c` is required to pass under `-fsanitize=address,undefined` and `-fsanitize=thread` before being considered done (`CLAUDE.md`) — this process has already caught and fixed a real heap-use-after-free in the snapshot-reclamation logic during development (see the `reclaim_gate` note in `src/internal.h`). `.github/workflows/ci.yml` runs the full test suite plus both sanitizer passes on every push.