docs: add SECURITY.md (vulnerability disclosure policy)

OpenSSF-template-shaped policy covering supported versions, reporting
channels (private email primary; GitHub Security Advisories on the
mirror as a structured-coordination secondary), response timeline, the
embargo+disclosure flow, CVE assignment process, and in-scope vs
out-of-scope examples.

Closes the NIST SI-5 (vulnerability disclosure) gap from the
federal-readiness gap analysis. Useful for every customer, federal
or not — formalizes the "where do I report this" question that
otherwise goes unanswered.

Out-of-scope examples explicitly enumerate the documented behaviors
that reporters sometimes mistake for vulnerabilities (email-header
forgery via direct bind-address connection; anonymous info disclosure
on /; apps: URL-fetch trust). Saves both reporter and maintainer time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZDDC 2026-05-04 17:53:13 -05:00
parent 5c33c8a821
commit ca0364c197

171
SECURITY.md Normal file
View file

@ -0,0 +1,171 @@
# 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.