Signed mirror seed manifest v1
DSSE payload type: application/vnd.stellaops.mirror-seed-manifest+json. Files in a seed directory: manifest.json (the payload, byte for byte) and, when the seed is signed, manifest.dsse.json (the envelope). Request header: X-StellaOps-Mirror-Seed-Envelope (base64 of the envelope’s JSON bytes). Sprint: SPRINT_20261027_006 SIM-7.
Purpose
A mirror seed (stella mirror seed export, mirror seeds) is the advisory and VEX data a hub imports through POST /api/vulnerabilities/v1/mirror/seeds/import. The seed manifest already names the seed exactly: the body digest, length and advisory count, the digest of the advisory state index, the scope and, for a delta, its baseline. Signed by the vendor, it lets the hub that imports the seed verify, offline and on every import route, that Stella Ops published that seed.
What a verified envelope establishes
An envelope that verifies under an active vendor-intelligence root of the vendor trust-root set establishes that Stella Ops published a seed whose manifest is the payload: its body digest (bundleDigest), state index digest (index.digest), scope (scope) and delta baseline (delta.baseDigest). It does not establish that the advisories are complete, correct or current.
Payload
The payload is the seed’s manifest.json exactly as the exporter wrote it. It is not re-serialized: the envelope’s payload and the file are the same bytes. The fields the hub binds are:
| Field | Bound to |
|---|---|
bundleDigest | X-StellaOps-Content-Digest, which the hub separately proves is the digest of the request body. |
index.digest | X-StellaOps-Mirror-State-Digest when sent; otherwise the hub imports under this value. |
delta.baseDigest | X-StellaOps-Mirror-Base-Digest: both absent for a full seed, or equal for a delta. |
scope | X-StellaOps-Mirror-Scope when sent (the SHA-256 of the scope’s compact JSON, members in written order); otherwise the hub imports under the signed scope’s digest. |
Envelope
{
"payloadType": "application/vnd.stellaops.mirror-seed-manifest+json",
"payload": "<base64 of manifest.json>",
"signatures": [
{ "keyid": "<key id>", "sig": "<base64 signature>" }
]
}
- Each signature covers the DSSE pre-authentication encoding of the payload type and the payload.
- A vendor seed is signed with the vendor intelligence key (purpose
vendor-intelligence, ES256, 64-byte IEEE P1363 signature). Itskeyidis the key’s vendor root-set identifier:sha256:and the SHA-256 of its SubjectPublicKeyInfo. - An envelope is at most 16 KiB.
Producing a signed seed
stella mirror seed export --sign vendor --vendor-key-id <id> signs the manifest it writes. The key is resolved from the crypto provider that holds it, or from a key file mounted at runtime (--vendor-key-file with --vendor-key-provider); the command never generates or enrolls a key. Before the seed is kept, the new envelope must verify against the active vendor-intelligence roots of the vendor trust-root set (--vendor-roots, default STELLAOPS_VENDOR_TRUST_ROOTS); otherwise the export fails and leaves no seed. stella mirror seed validate checks that a present envelope carries this payload type and signs the directory’s manifest.json byte for byte; stella mirror seed download copies it with the seed.
Routes that carry the envelope
Every route into the import endpoint carries the envelope beside the seed:
stella mirror seed importreadsmanifest.dsse.jsonfrom the seed directory and sends it.- An Offline Kit carries it at
vulnerabilities/mirror-seed.v1.dsse.json, beside thevulnerabilities/mirror-seed.v1.ndjsonpart. The OfflineKit service keeps it with the stored part and forwards it unchanged, also when a part is re-activated. It never verifies or interprets it. - A release bundle carries it at
data/vulnerabilities/mirror-seed.manifest.dsse.json. The release manifest declares it (vulnerabilitySeed.envelopePath), andverify-bundle.pychecks that it signs the shipped producer manifest. Both installers send it.
Verification at the hub
The hub verifies the envelope before it stages a byte of the seed. It reads its trust at each import: the active vendor-intelligence roots of the pinned vendor set (STELLAOPS_VENDOR_TRUST_ROOTS, else trust/vendor-roots/ beside the hub binary), and the operator key the hub operator configures (Vulnerabilities:MirrorSeed:OperatorPublicKeyPath, one P-256 SubjectPublicKeyInfo PEM; a file holding private key material is not used). The two are separate trust sources: a signature verifies under one of them, never a combination. Roots that arrive with a seed are never read.
The hub refuses the import with 422 problem details titled mirror_seed_signature_refused, and a detail naming the reason, when:
- the seed carries no envelope and the hub operator has not set
Vulnerabilities:MirrorSeed:AllowUnsigned(defaultfalse); - the envelope is malformed, larger than 16 KiB, has another payload type or no signature;
- no signature verifies under a trusted key (no usable vendor root and no operator key is also this case);
- the payload is not a seed manifest, or a binding in the table above differs from the signed value.
A seed whose envelope is present but does not verify is refused whatever AllowUnsigned says. The import receipt states the trust source: trust is vendor-intelligence, operator-key or unsigned-allowed, and trustKeyId names the verifying key.
