# Security Policy

This document describes how to report vulnerabilities in ZDDC and what to expect
in response. Compatible with the OpenSSF [`SECURITY.md` template] and addresses
NIST 800-53 SI-5 (vulnerability disclosure) for federal evaluators.

[`SECURITY.md` template]: https://github.com/ossf/oss-vulnerability-guide

## Supported versions

Security fixes are issued for:

- **Latest stable release** of every artifact (six HTML tools + zddc-server) —
  always supported.
- **Previous stable major-minor** (e.g. `v1.2.x` while `v1.3.x` is current) —
  best-effort backports for issues with severity ≥ High (CVSS v3.1 ≥ 7.0).
- **Earlier versions** — out of scope. Reproduce the issue on a current
  release before reporting.

zddc-server's release tags (`zddc-server-vX.Y.Z`) and the HTML tool tags
(`<tool>-vX.Y.Z`) all share the same X.Y.Z on lockstep cuts; "current stable"
means the highest X.Y.Z tagged across the seven artifacts.

## Reporting a vulnerability

**Preferred channel: private email.**

Send a description of the issue, reproduction steps, and (if known) a
suggested fix to:

> **caseywitt@proton.me**

Include in the email:

1. The artifact and version affected (e.g. `zddc-server-v0.0.16` or
   `archive-v0.0.16`).
2. The shortest reproduction you can produce — a single curl command, a
   `.zddc` fixture that triggers the issue, etc.
3. Your assessment of severity (CVSS v3.1 vector if you can; otherwise a
   short description of impact).
4. Whether you'd like attribution in the eventual advisory or prefer to
   stay anonymous.

PGP encryption is available on request — reply to the initial email asking
for the key; we'll send it from the same address.

**Secondary channel: GitHub Security Advisories.** This repository's
upstream is at <https://codeberg.org/VARASYS/ZDDC>; a mirror is published
on GitHub when one is needed for ecosystem compatibility. If you prefer
the GitHub workflow over email, use the "Report a vulnerability" link on
the GitHub mirror's Security tab. Codeberg does not yet have an
equivalent of GitHub Security Advisories, so for embargoed coordination
GitHub is the better path.

**Do not** open a public issue on either Codeberg or the GitHub mirror
for security reports. Do not post reproduction details to any public
chat, mailing list, or social channel until the embargo lifts.

## Response timeline

| Time | What to expect |
|---|---|
| Within 3 business days of report | Acknowledgement that we received it and are looking at it |
| Within 14 days | Initial assessment: confirmed / not-a-vulnerability / need-more-info, with severity rating |
| Within 90 days | Fix released, or an updated timeline if the issue is genuinely complex |

If you don't hear back within 3 business days, retry — the email may have
been mis-filed. Mention "ZDDC security" in the subject so it stands out.

## Embargo and disclosure

We coordinate disclosure via embargo when the issue is non-trivial:

1. **Embargo agreed.** Reporter and maintainer agree on a public-disclosure
   date (default 90 days from confirmation; sooner for severity Critical
   issues with active exploitation).
2. **Fix developed.** Patch + tests in a private branch; reproduction case
   added to the regression suite.
3. **Pre-disclosure notification.** ~1 week before the embargo lifts, we
   notify known downstream redistributors (Helm-chart consumers,
   container-image bakers) so they can stage updates.
4. **Coordinated release.** On the embargo date: release the fixed version,
   publish the advisory (with reporter attribution if desired), request a
   CVE if applicable.
5. **Public reproduction details.** Public proof-of-concept code is held
   until 30 days after the fix release, to give operators a window to
   upgrade.

## CVE assignment

For issues meeting the [MITRE CVE rules][cve-rules] (severity ≥ Medium,
publicly redistributed code, identifiable distinct vulnerability), we
request CVE IDs via:

- **GitHub Security Advisories**, when the GitHub mirror is the
  disclosure channel (GitHub is a CVE Numbering Authority and assigns
  IDs automatically for advisories published through their flow).
- **MITRE direct request**, otherwise, with the original report
  attached as evidence.

[cve-rules]: https://www.cve.org/Resources/General/Counting-Rules.pdf

The CVE ID, when assigned, appears in:

- The release-notes section of the fixed version's tag annotation.
- The published advisory.
- The relevant entry in `CHANGELOG.md` (when one exists; not every
  release ships with one).

## In-scope vulnerabilities

Examples of issues we want to hear about:

- Authentication / authorization bypass — anything that lets a caller
  reach a directory their `.zddc` chain or external OPA policy says
  they shouldn't.
- Path traversal — directory listings, archive resolutions, or form
  submissions that escape `ZDDC_ROOT`.
- Injection — XSS in tool HTML, command injection in shell scripts,
  YAML deserialization issues in `.zddc` parsing.
- Cryptographic weaknesses — though the production binary uses Go
  stdlib crypto and the transmittal-signing feature uses Web Crypto;
  TLS hardening is configurable.
- Cross-tool data leaks — one tool's storage being accessible via
  another tool's UI or URL.
- Rate-limiting / resource-exhaustion — if a single unauthenticated
  request can pin CPU, exhaust file descriptors, or fill disk.
- Supply-chain — tampering with vendored libraries, the `apps:` URL
  fetch path, or the cross-compile build.

## Out of scope

- **Email-header forgery via direct connection to the bind address.**
  Documented behavior — `zddc-server` trusts whatever the upstream
  proxy sets as `X-Auth-Request-Email`. Network isolation is the
  operator's responsibility (see `zddc/README.md` § "Trust boundary").
  Reports of "I bypassed auth by curl-ing 127.0.0.1:8080 directly"
  are not vulnerabilities; the documented deployment model requires
  the bind address to be unreachable except via the proxy.
- **Anonymous information disclosure on `/` and `/.profile`.**
  Documented as intentional — the public landing page is a project
  picker filtered by ACL. Operators who can't tolerate disclosure
  gate `/` behind their proxy's auth-required path.
- **`apps:` URL-fetch trust.** Documented — fetched-once-and-cached,
  no integrity verification. Treat `.zddc` write authority as full
  UI-mounting authority. (SHA-256 pinning is on the federal-readiness
  roadmap; see `zddc/README.md` § "Federal-readiness gap analysis".)
- **Theoretical issues without a working reproduction** — we'll engage
  with proof-of-concept code; not with hypothetical chains.
- **Issues in third-party dependencies that we vendor** — report those
  to the upstream project. We'll backport their fix in the next
  release cut. (Vendored libs: jszip, docx-preview, xlsx in some
  HTML tools; gopkg.in/yaml.v3, fsnotify, lumberjack, klauspost
  compress in zddc-server.)
- **Social engineering / phishing / misconfigured customer
  deployments** unless the misconfiguration is plausibly the default.

## Federal evaluators

Key references for ATO conversations:

- `zddc/README.md` § "Federal-readiness gap analysis" — every NIST
  control we know is incomplete, with the planned remediation.
- `ARCHITECTURE.md` § "Server security model" — commercial-vs-federal
  trust model side-by-side.
- `zddc/internal/policy/` — pluggable OPA-compatible policy decider
  for federal customers running their own audited Rego policies.

We do not currently hold an ATO, FedRAMP authorization, or any other
formal accreditation. The system is designed to be ATO-able by
customers; the documentation aims to make that path obvious.
