# Security Policy

`mgf-apiprobe` is a federation sibling of [`mgf-common`](https://pypi.org/project/mgf-common/),
shipping REST-API verification primitives (typed probes, auth
flows, schema validators, findings). A vulnerability here may
affect every consumer that runs probes against production
endpoints, so we take security reports seriously.

## Supported versions

In the 0.x window, **only the latest MINOR receives security
patches.** Per [SemVer 0.x](https://semver.org/#spec-item-4) and
rule **AP-03** from `mgf-standard/docs/standards/API_DESIGN.md`,
each MINOR release MAY break the public API.

| Version | Supported |
|---------|-----------|
| `0.3.x`  | ✅ — latest MINOR; security patches ship as `0.3.Y` |
| `0.2.x`  | ❌ — superseded by `0.3.x` |
| `0.1.x`  | ❌ — pre-federation-v0.30; upgrade to `0.3.x` |

## Reporting a vulnerability

**Please do not open a public issue or pull request** until we have
had a chance to triage and patch.

- **Email:** `bassam@magogi.org` with subject prefix
  `[mgf-apiprobe security]`.
- **Codeberg private security advisory:** open a private
  vulnerability report at
  [the repository's Security tab](https://codeberg.org/magogi-admin/mgf-apiprobe/security).

### What to include

- A description of the vulnerability and its impact.
- Steps to reproduce — a minimal failing probe definition is
  ideal. For auth-flow issues, the exact token/cookie shape
  matters.
- The version(s) of `mgf-apiprobe` and `mgf-common` affected.
- Python version + OS.

### What to expect

| Stage | Timeline |
|---|---|
| Acknowledgement | within 3 business days |
| Initial assessment + severity rating | within 7 business days |
| Patch + release | within 30 days for high-severity, 90 days for medium |
| Credit + public disclosure | coordinated with the reporter |

90-day default embargo.

## Scope

**In scope:**

- Code in `src/mgf/apiprobe/` (the published `mgf-apiprobe`
  package). Specifically: the probe-execution engine, the
  auth-flow runners (`auth/flows.py` — bearer-token / cookie
  / mTLS / OAuth2 client-credentials handlers), the
  schema validators (`schema/pydantic.py`), the configuration
  layer.
- Build / release infrastructure (`pyproject.toml`, the manual
  release flow specified in
  [`mgf-standard/docs/standards/RELEASING.md`](https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/docs/standards/RELEASING.md)).

**Out of scope:**

- Vulnerabilities in `mgf-common` itself — report to
  [`mgf-common/SECURITY.md`](https://codeberg.org/magogi-admin/mgf-common/src/branch/main/SECURITY.md).
- Vulnerabilities in `httpx`, `pydantic`, or other transitive
  deps — report to the upstream project.
- Consumer-authored probe content that exercises an
  unsafe-by-design endpoint (e.g., a probe that hits a
  production write-endpoint with mutating data without
  consumer authorization) — that's deployment / probe-suite
  hygiene, not library scope.

## Hardening recommendations for consumers

- **Probe credentials live in a vault.** Never inline bearer
  tokens / OAuth client secrets in committed probe
  definitions. Use environment variables sourced from
  Ansible Vault / cloud KMS / HashiCorp Vault per **SC-01**.
- **Read-only by default.** Production probes SHOULD use
  read-only endpoints (`GET` / `HEAD` / `OPTIONS`); mutating
  probes belong in staging-only sweeps.
- **Rate-limit between probes.** A probe sweep is a load
  source; respect the target's published rate limits.
- **Redact response bodies.** Probe findings + response
  bodies pass through `mgf-common`'s `Redactor` before
  logging per **LG-04** + **SC-09**.

## A note on the standards

`mgf-apiprobe` is a **federation sibling** under the
project-shape taxonomy from
[`mgf-standard/docs/standards/DOCUMENTATION.md`](https://codeberg.org/magogi-admin/mgf-standard/src/branch/main/docs/standards/DOCUMENTATION.md) §2.0.
The cross-project engineering standards live in `mgf-common`;
this project inherits them PLUS adds a project-specific
[`docs/standards/SCOPE.md`](docs/standards/SCOPE.md) (Shape B
extension per DOCUMENTATION.md §2.0.4). See
[`docs/standards/README.md`](docs/standards/README.md) for the
pointer.
