karapace/docs/security-model.md
Marco Allegretti e6e0f3dd6d docs: rewrite all documentation from source code
Delete 14 old docs files (AI-generated, riddled with Phase/M1/1.0
jargon, references to non-existent commands, stale CI snippets).

New documentation (6 files), written from repository source analysis:
- docs/architecture.md — crate graph, engine lifecycle, identity
  computation, runtime backends, store design, WAL, GC, unsafe blocks
- docs/cli-reference.md — all 23 commands with syntax, args, flags,
  exit codes, env vars, verified against crates/karapace-cli/src/main.rs
- docs/storage-format.md — directory layout, objects, layers, metadata,
  manifest format, lock file, WAL, atomic write contract
- docs/security-model.md — mount/device/env var policies with exact
  defaults from security.rs, trust assumptions, what is NOT protected
- docs/build-and-reproducibility.md — CI env vars, RUSTFLAGS, cargo
  profile, reproducibility verification, toolchain pinning
- docs/contributing.md — setup, verification, project layout, code
  standards, testing, CI workflows

README.md rewritten: concise, no marketing language, prerequisites
first, usage example, command table, limitations section.

CONTRIBUTING.md now points to docs/contributing.md.
CHANGELOG.md cleaned: removed M1-M8 labels, Phase refs, stale counts.
2026-02-23 01:25:07 +01:00

105 lines
3.9 KiB
Markdown

# Security Model
Defined in `karapace-runtime/src/security.rs::SecurityPolicy`.
## Privilege model
Karapace runs entirely as an unprivileged user. No SUID binaries. No root daemon. Isolation is provided by Linux user namespaces (`unshare`).
The OCI backend delegates to rootless runtimes (`crun`, `runc`, `youki`).
## Mount policy
Absolute host paths in manifest `[mounts]` are validated against an allowlist.
**Default allowed prefixes:** `/home`, `/tmp`.
Relative paths (e.g. `./`) are always permitted. Mounts outside the allowlist are rejected at build time with `RuntimeError::MountDenied`.
Path traversal is prevented by `canonicalize_logical()` in `security.rs`, which resolves `..` components before checking the prefix.
Defined in `SecurityPolicy::validate_mounts`.
## Device policy
Default policy denies all device access.
- `hardware.gpu = true` → allows `/dev/dri`
- `hardware.audio = true` → allows `/dev/snd`
No implicit device passthrough. Defined in `SecurityPolicy::validate_devices`.
## Environment variable control
**Allowed** (propagated into the container):
```
TERM, LANG, HOME, USER, PATH, SHELL, XDG_RUNTIME_DIR
```
**Denied** (never propagated):
```
SSH_AUTH_SOCK, GPG_AGENT_INFO, AWS_SECRET_ACCESS_KEY, DOCKER_HOST
```
Only variables present in the allowed list and absent from the denied list are passed through. Defined in `SecurityPolicy::filter_env_vars`.
## Resource limits
Declared in manifest `[runtime.resource_limits]`:
- `cpu_shares`: CPU shares limit
- `memory_limit_mb`: memory limit in MB
If the policy defines upper bounds, requesting values above them causes a build-time error (`RuntimeError::ResourceLimitExceeded`). Defined in `SecurityPolicy::validate_resource_limits`.
## Store integrity
- **Objects:** blake3 hash verified on every read. Key = hash of content.
- **Metadata:** blake3 checksum embedded in each metadata file, verified on every `get()`.
- **Layers:** file content re-hashed against filename on read.
- **Images:** content digest stored on download, re-verified on cache hits.
## Concurrency
File locking (`flock(2)`) on `store/.lock` for all mutating operations. Both CLI and D-Bus service acquire the lock. Defined in `karapace-core/src/concurrency.rs::StoreLock`.
Running environments cannot be destroyed (must be stopped first).
## Shell injection prevention
Sandbox scripts use POSIX single-quote escaping for all paths and values. Environment variable keys are validated against `[a-zA-Z0-9_]`. Defined in `karapace-runtime/src/sandbox.rs`.
## Manifest parsing
Strict TOML parser with `deny_unknown_fields` on all sections. Unknown keys cause a parse error.
## What is NOT protected
- Karapace does not protect against a compromised host kernel.
- Karapace does not verify the authenticity of upstream base images beyond content hashing.
- The OCI runtime (if used) is trusted.
- Filesystem permissions on the store directory are the user's responsibility.
- Network isolation (`runtime.network_isolation`) depends on the backend implementation.
- No MAC (SELinux/AppArmor) enforcement within the container.
## Trust assumptions
1. The host kernel provides functioning, secure user namespaces.
2. The store directory has correct ownership and permissions.
3. `fuse-overlayfs` is correctly installed and not compromised.
4. The OCI runtime (if used) is a trusted binary.
5. Base images from `images.linuxcontainers.org` are fetched over HTTPS but not GPG-verified.
## Unsafe code
Five `unsafe` blocks, all FFI calls to libc:
| File | Call | Purpose |
|------|------|---------|
| `karapace-core/src/engine.rs` | `libc::kill(SIGTERM)` | Stop running environment |
| `karapace-core/src/engine.rs` | `libc::kill(SIGKILL)` | Force-kill after timeout |
| `karapace-runtime/src/sandbox.rs` | `libc::getuid()` | Get UID for namespace mapping |
| `karapace-runtime/src/sandbox.rs` | `libc::getgid()` | Get GID for namespace mapping |
| `karapace-runtime/src/terminal.rs` | `libc::isatty()` | Detect terminal for interactive mode |