Security · Operations

Advisories receipt ceremony

This is the one-page runbook to publish security advisories as receipts: an append‑only feed, a deterministic root, and detached signatures. The posture is intentional: missing or unverifiable evidence ⇒ HOLD (fail‑closed).

Scope
Publish (1) an advisory JSON + detached signature, (2) append a line to advisories.ndjson, (3) refresh the root DSSE payload (feed sha256), then (4) publish signatures via a controlled ceremony.
Private keys must remain offline. Do not paste secrets into CI logs, issues, or tickets.
Publish (required)
  • /security/advisories/<YYYY>/<MM>/MVG-ADV-....json
  • /security/advisories/<YYYY>/<MM>/MVG-ADV-....json.asc (detached signature)
  • /security/advisories/advisories.ndjson (append‑only)
  • /security/advisories/advisories.root.dsse.json (root payload points to feed sha256)
If signatures are missing, verifiers MUST output HOLD. That is expected until GO‑LIVE.
Placement (max impact)
  • /trust-center/: “Vulnerability disclosure & advisories” card
  • /security/advisories/: lookup UI + expected outputs
  • /legal/security-disclosure/: official intake + safe harbor
  • /press/: brand defense (official feeds)

Procedure

1) Preflight

Confirm official channels + the published public key fingerprint. Confirm the feed is append‑only.

# Official intake + key fingerprint (public)
curl -fsS https://meridianverity.com/.well-known/security.txt | sed -n '1,180p'

# Confirm you are appending (not rewriting) the feed
tail -n 3 security/advisories/advisories.ndjson

2) Draft the advisory JSON

Create an ID (MVG-ADV-YYYY-NNNN). Include CVE(s) if applicable. Keep customer‑specific details out of the public artifact.

# Example path (month-sharded)
security/advisories/2026/02/MVG-ADV-2026-0001.json

3) Sign the advisory (offline; detached ASCII armor)

Run on an offline/signing machine using your existing MVG security signing key.

gpg --armor --detach-sign \
  --local-user <MVG_SIGNING_KEY_FPR> \
  --output security/advisories/2026/02/MVG-ADV-2026-0001.json.asc \
  security/advisories/2026/02/MVG-ADV-2026-0001.json

4) Append to the feed (append‑only)

Add exactly one NDJSON line. Do not reorder existing lines. The line should pointer to the advisory JSON + signature.

# Example feed line (single line JSON)
{"id":"MVG-ADV-2026-0001","date":"2026-02-22","title":"<short title>","severity":"<low|med|high|critical>","cves":["CVE-2026-XXXX"],"json_url":"/security/advisories/2026/02/MVG-ADV-2026-0001.json","sig_url":"/security/advisories/2026/02/MVG-ADV-2026-0001.json.asc"}

5) Refresh the root payload (feed sha256)

Compute the feed sha256 and update the root DSSE payload (scaffold) to reference it deterministically.

# Compute feed sha256
sha256sum security/advisories/advisories.ndjson

# Root DSSE scaffold points to the feed sha256 (payload)
cat security/advisories/advisories.root.dsse.json | sed -n '1,200p'

If root signatures are not yet published, root verification should yield HOLD (expected).

6) Verify offline (expected)

# Import the published public key (if needed)
gpg --import pgp.asc

# Verify detached signature
# Expected output includes: "Good signature"
gpg --verify security/advisories/2026/02/MVG-ADV-2026-0001.json.asc \
  security/advisories/2026/02/MVG-ADV-2026-0001.json

Expected outputs: PASS when signatures verify; HOLD when signatures are missing/unverifiable; FAIL on mismatches.

Audit ticket text (copy/paste)

Minimal, procurement‑friendly. Replace <...> as needed.

Vulnerability disclosure (official):
- /legal/security-disclosure/ (safe harbor + intake)

Official advisories feed (append-only):
- /security/advisories/advisories.ndjson
- Root scaffold: /security/advisories/advisories.root.dsse.json

Advisory receipt (example):
- /security/advisories/<YYYY>/<MM>/MVG-ADV-....json
- Signature: /security/advisories/<YYYY>/<MM>/MVG-ADV-....json.asc

Offline verification (expected):
- gpg --verify MVG-ADV-....json.asc MVG-ADV-....json

Expected outputs:
- PASS: signatures verify deterministically
- HOLD: missing/unverifiable signatures (fail-closed)
- FAIL: tamper-evident mismatch

References

Auditor start: /trust-center/