# Security Policy

`mgf-test-web` (ProofWarden) is a federation sibling of
[`mgf-common`](https://codeberg.org/magogi-admin/mgf-common). Its base is the
**warden** — a per-project resident broker that is the *sole executor* of tests —
plus the `testctl` CLI and the runner adapters, built on the `mgf-fedres` spine.
It runs **no network service** and handles **no credentials**, so its security
surface is limited to its **local IPC** (a Unix-domain socket), how it **spawns
test child processes**, and how it **parses the requests + config** it is handed.

The defining posture is **fail-closed**: if the warden is down, the client refuses
(raises `WardenUnreachable`) rather than running a test on its own — a down
authority never degrades into an unguarded execution path, because executing
outside the warden would defeat the single entry point.

## A note on the IPC, the subprocess, and parsing

- **Local IPC, not a network port.** The warden listens on a **Unix-domain socket**
  (`fed-resources/live/warden.sock`) — filesystem-permissioned, no TCP port — so its
  reachability is bounded by filesystem permissions, not the network. Exactly one
  warden per project is enforced by an `fcntl` lock on a pidfile; a leftover socket
  from a crashed warden is reclaimed only by the process that holds that singleton
  lock.
- **Subprocess execution is safe by construction.** The runner spawns the test as a
  child via an **argv list with `shell=False`** (`SC-02`) — no shell interpolation;
  the command shape is fixed (`python -m pytest <node-id>`). The warden owns the
  child and **survives its failure**: a runner exception is translated to an `error`
  event, never a warden crash. Test code is arbitrary by nature; isolation is "the
  warden's child process", not a sandbox.
- **Safe deserialization.** Socket requests and per-run config are parsed with the
  stdlib `json` module only — no `pickle`, no `yaml.load`, no `eval`. Each request
  is guarded (an unknown op is an error, not a crash; a malformed request can never
  take the warden down), and the client fails closed on a truncated/absent response.
- **No secrets, no outbound network.** The base opens no outbound connections and
  reads/writes no credentials. (The future `[web]` console and the CI-trigger will
  add an HTTP surface; their security model will be audited when they are built.)

## Supported versions

In the 0.x window, **only the latest MINOR receives fixes** (per
[SemVer 0.x](https://semver.org/#spec-item-4) and rule **AP-03**). Fixes ship as
the next PATCH on the latest MINOR.

| Version | Supported |
|---------|-----------|
| `0.1.x` | ✅ — latest MINOR (pre-alpha) |
| `< 0.1` | ❌ — pre-publish development |

## Reporting a vulnerability

**Please do not open a public issue or pull request** until we have had a chance
to respond. Email the maintainer (see the Codeberg profile for `magogi-admin`)
with a description, reproduction, and impact.
