# For security reviewers

> **Who you are.** You're auditing `mgf-common` for a security
> review (third-party assessment, internal-team pre-adoption
> review, or vulnerability research). You want the threat
> model + the SC-* rules + the redaction story.

## In one paragraph

`mgf-common`'s security model is **defence-in-depth at the
edges**: secrets never enter logs by accident (redaction),
process launches reject shell strings (command-injection
elimination by API design), config validation fails loud at
startup, and crash reports scrub PII. The
The SECURITY_STANDARD (`mgf-fed standards SECURITY_STANDARD`)
codifies SC-* rules; every public name has a unit test pinning
its security-relevant behaviour (TS-10).

## Read first

1. [`SECURITY.md`](../../SECURITY.md) — vulnerability
   reporting policy (per SC-12).
2. `mgf-fed standards SECURITY_STANDARD` — the SC-* rule
   corpus + threat model.
3. `mgf-fed standards TESTING` §10 — security tests
   (TS-10): negative-pattern grep, positive behaviour
   assertions, redaction pins, audit-event pins.

## The threat surfaces

| Surface | What's at risk | Mitigation |
|---|---|---|
| **Subprocess launches** (`mgf.common.process.run`, `Service`) | Command injection via shell strings | List-only API by construction (rejects strings; `["/bin/sh", "-c", "…"]` requires explicit shell opt-in) |
| **Captured subprocess output** | Secrets in child's stdout/stderr leaking to logs / disk | `Redactor` runs over each line BEFORE log emit, when bootstrap is active; explicit `redact=False` opt-out is documented as debug-only |
| **Configuration values** (`MgfSettings.*`) | Credentials in `.env` files committed to git | `dotenv_filtering="match_prefix"` (BOOTSTRAP-01) prevents reading unprefixed keys; pydantic schema rejects malformed values; `extra="forbid"` catches typos |
| **Vault backends** | Secrets at rest | Three built-in backends (env / keyring / encrypted file) + registry pattern for consumer-registered backends; SC-09 vault-rotation rule |
| **Crash reports** | PII / secrets in stack traces shipped to remote | `Redactor` runs over crash payload before sink fan-out; SC-08 redaction-on-crash rule |
| **HTTP client** (`mgf.http`, sibling `mgf-http`) | TLS bypass; default-on `verify_tls`; warn-on-disable | TLS-verify default-on with `UserWarning` on opt-out; secret-header redaction in logs |
| **Dependencies** | Supply-chain compromise | SC-13 pinned `requirements/lock.txt`; SC-15 `make audit` runs `pip-audit` in CI |

## The redaction model

Single canonical primitive:
[`mgf.common.observability.Redactor`](../reference/observability.md).

Built-in patterns (always-on when Redactor is active):

- Bearer / Basic auth tokens
- JWTs
- PEM private keys
- API key prefixes: OpenAI (`sk-…`), GitHub (`ghp_/gho_/ghu_/ghs_/ghr_…`),
  AWS access keys (`AKIA…`), Slack (`xox[baprs]-…`), Google API (`AIza…`)

Consumer-supplied patterns: passed via
`MgfSettings.redaction.extra_keys` (key-name match) +
`extra_value_patterns` (regex against value strings).

Strict mode (off by default; HIGH false-positive rate; enable
only when legal/compliance requires): adds patterns for
email, IPv4/v6, US phone, SSN, IBAN, Luhn-validated credit
cards. See SC-08 (`mgf-fed standards SECURITY_STANDARD`).

## Where redaction is wired

When `mgf.common.bootstrap()` is active:

- **Log records**: every record's payload runs through
  `Redactor.redact()` before formatter emission.
- **Captured subprocess output**: `mgf.common.process.run`
  and `Service` consult `get_active_redactor()` and scrub
  each line before it lands in `ProcessResult.stdout` /
  `.stderr` AND before the line becomes a log record.
- **Crash reports**: the local + Sentry + OTLP + HTTP sinks
  redact their payload before ship.

When `bootstrap()` is NOT active OR the consumer's framework
owns logging via `setup_logging=False` (BOOTSTRAP-01), the
default is **no redaction** (silent). Consumers must wire
their framework's handlers through a `Redactor` themselves.
This is documented at
[`docs/recipes/framework-owned-logging.md`](../recipes/framework-owned-logging.md).

## Negative-pattern grep tests (TS-10)

A handful of forbidden patterns are pinned by tests that
grep `src/`:

- `subprocess.run(..., shell=True)` — forbidden; `mgf.common.process.run`
  exists for a reason.
- `yaml.load(...)` without `safe_load` — forbidden.
- `pickle.load(...)` on untrusted input — forbidden.
- Bare `except:` (catches `KeyboardInterrupt` / `SystemExit`)
  — forbidden by EH-* rules.

See `tests/unit/security/` for the live pin tests.

## Token / secret handling in this project

- **PyPI token**: scoped to project `mgf-common`; rotated
  after extended use periods. Never committed. See
  [`docs/audience/release.md`](release.md).
- **Codeberg deploy keys**: per-user; `.pypirc`-equivalent
  for SSH push. Documented in [`docs/release/ci.md`](../release/ci.md).
- **OTel exporter credentials**: read from
  `OTEL_EXPORTER_OTLP_ENDPOINT` + `_HEADERS` env vars by the
  OpenTelemetry SDK directly; mgf-common does not see them.
- **Vault backend secrets**: per-backend; the `keyring`
  backend uses the OS credential store; the `file` backend
  uses an encrypted file at a configured path.

## Reporting a vulnerability

[`SECURITY.md`](../../SECURITY.md) is canonical. Short
form: report privately to the maintainer (contact info in
`SECURITY.md`). We follow standard responsible-disclosure
timelines; CVE assignment is project-managed.

## What's deliberately not in scope

`mgf-common` does NOT provide:

- Cryptographic primitives (use `cryptography` directly).
- Authentication frameworks (use the framework's;
  `django.contrib.auth`, `fastapi.security`, etc.).
- Authorization policy engines.
- Web-app CSP / CORS / CSRF — that's framework-side.

These are deliberate limits. Consumers compose `mgf-common`
WITH their framework's security primitives, not in lieu of
them.

## Audit cadence

The cookiecutter template ships a `make audit` target that
runs:

- `pip-audit` (dep CVE check)
- `bandit` (lint for unsafe patterns)
- `ruff` (some security rules in the `S` ruleset)

Documented in `mgf-fed standards SECURITY_STANDARD` SC-15.
