Security operations

Evidence,
not assurances.

An audit ledger that recomputes its own hash chain every time this page loads. Envelope encryption whose rotation never touches a ciphertext. A bill of materials CI refuses to let go stale. And a SAML validator that rejects an attack a correct signature check cannot — with the forged response run live, below.

The audit ledger, verified now.

Each entry hashes over the previous entry’s hash, so editing any field of any row breaks that row’s hash and every link after it. The verification below ran when this page rendered — it is not a stored result.

Empty ledger

No entries yet. The first admin role change writes one.

The ledger is empty. It records privilege-relevant writes — currently role changes — and the genesis link is 0000000000000000

This is tamper-evident, not tamper-proof, and the difference is the whole claim. An attacker with write access to the database can edit a row and recompute every hash after it, and the result verifies cleanly. A hash chain buys exactly one property: nobody can make a quiet edit. Closing the gap needs the chain head published somewhere the attacker does not control — a notary, a counterparty, a transparency log. Nothing here does that, so nothing here claims it. There is a test that pins the limitation rather than the wish.

Envelope encryption, and why rotation is cheap.

A random 256-bit data key encrypts each record; the master key encrypts only that data key. Both layers are AES-256-GCM, so both are authenticated — CBC would encrypt without detecting modification, which for a wrapped key is a padding oracle with extra steps.

Rotation never decrypts anythingNo plaintext

Rotating unwraps the ~60-byte data key under the old master and rewraps it under the new one. The payload is byte-identical afterwards, and the plaintext never exists in memory during a sweep — which is what makes running one against production defensible. Encrypting directly under a master key would mean decrypting and re-encrypting every row instead.

Old key versions must stayOutage risk

Every envelope names the version that wrapped it, and all configured versions are loaded. Deleting the previous key at rotation time is the single most common way a rotation causes an outage: every envelope not yet swept becomes undecryptable, and nothing warns you until a read fails.

Bound to its recordAAD

The record’s identity goes in as additional authenticated data, so a ciphertext moved from one row to another stops decrypting. Without it, an attacker with write access swaps two users’ encrypted fields and both decrypt perfectly — confidentiality was never the property that would have caught that.

Status on this deploymentInert

No master key is configured on this deployment, so the module is inert rather than half-working. A key of the wrong length is refused outright rather than padded — a silently truncated key would 'work' at a fraction of the intended strength.

SAML, and the attack a valid signature does not stop.

Nearly every historical SAML bypass is not a broken signature check. It is a signature that verifies correctly over an element the application then does not use. Each response below is validated live when this page renders.

A legitimate response

One assertion, signed, referencing itself, issued for us, inside its window, answering our request.

Acceptedshivam@example.com

  • Parses as XML, with no DTDpassNo DOCTYPE or entity declarations.
  • Root element is a Responsepass<samlp:Response>
  • IdP reported successpassurn:oasis:names:tc:SAML:2.0:status:Success
  • Exactly one assertionpassOne <Assertion> in the document.
  • Response or assertion is signedpass1 signature(s), referencing a-1.
  • The signature covers the assertion being consumedpassReference URI #a-1 is the assertion this result reads.
  • Signature verified cryptographicallyskippedNot implemented here. Verifying an XML signature requires exclusive canonicalisation, and a hand-rolled c14n that disagrees with the IdP's by one byte either rejects valid logins or accepts modified ones. This belongs to the IdP SDK or the gateway.
  • Issuer is the expected IdPpasshttps://idp.example.com
  • We are the intended audiencepasshttps://www.shivamsfolio.com/sp
  • Assertion is inside its validity windowpassValid until 2026-08-17T12:30:00.000Z.
  • Answers our AuthnRequestpassreq-1
  • Assertion has not been used beforeskippedNo replay store supplied.

Signature wrapping

A forged assertion is placed ahead of the real one, complete in every respect — same issuer, same audience, same validity window, same request id — with only the subject changed. The signature still references the genuine assertion and would verify perfectly. Every ordinary check passes. Only the two structural checks fail, and they are the whole thing standing between this and a full authentication bypass.

Rejected — would have authenticated as attacker@evil.test

  • Parses as XML, with no DTDpassNo DOCTYPE or entity declarations.
  • Root element is a Responsepass<samlp:Response>
  • IdP reported successpassurn:oasis:names:tc:SAML:2.0:status:Success
  • Exactly one assertionfail2 assertions found — the classic wrapping shape, where the signed one is not the one consumed.
  • Response or assertion is signedpass1 signature(s), referencing a-1.
  • The signature covers the assertion being consumedfailSignature references #a-1, but the assertion consumed is #forged-1. This is signature wrapping: the signature would verify and the authentication would still be forged.
  • Signature verified cryptographicallyskippedNot implemented here. Verifying an XML signature requires exclusive canonicalisation, and a hand-rolled c14n that disagrees with the IdP's by one byte either rejects valid logins or accepts modified ones. This belongs to the IdP SDK or the gateway.
  • Issuer is the expected IdPpasshttps://idp.example.com
  • We are the intended audiencepasshttps://www.shivamsfolio.com/sp
  • Assertion is inside its validity windowpassValid until 2026-08-17T12:30:00.000Z.
  • Answers our AuthnRequestpassreq-1
  • Assertion has not been used beforeskippedNo replay store supplied.

XXE via an inline DTD

A SAML endpoint parses before it authenticates, which is why it is a classic place to find XML external entity injection. The parser refuses a DOCTYPE outright rather than relying on an entity-expansion flag staying switched off.

Rejected

  • Parses as XML, with no DTDfailDOCTYPE is not permitted — an inline DTD can declare entities (XXE)

An assertion for somebody else

Genuinely signed, genuinely issued, genuinely inside its window — and minted for a different service provider, one the attacker legitimately controls. Without an audience check it authenticates here.

Rejected — would have authenticated as shivam@example.com

  • Parses as XML, with no DTDpassNo DOCTYPE or entity declarations.
  • Root element is a Responsepass<samlp:Response>
  • IdP reported successpassurn:oasis:names:tc:SAML:2.0:status:Success
  • Exactly one assertionpassOne <Assertion> in the document.
  • Response or assertion is signedpass1 signature(s), referencing a-1.
  • The signature covers the assertion being consumedpassReference URI #a-1 is the assertion this result reads.
  • Signature verified cryptographicallyskippedNot implemented here. Verifying an XML signature requires exclusive canonicalisation, and a hand-rolled c14n that disagrees with the IdP's by one byte either rejects valid logins or accepts modified ones. This belongs to the IdP SDK or the gateway.
  • Issuer is the expected IdPpasshttps://idp.example.com
  • We are the intended audiencefailAssertion is for https://someone-elses-app.example. An assertion issued for another service provider must never authenticate here.
  • Assertion is inside its validity windowpassValid until 2026-08-17T12:30:00.000Z.
  • Answers our AuthnRequestpassreq-1
  • Assertion has not been used beforeskippedNo replay store supplied.

The cryptographic signature check is deliberately not implemented, and reports itself as skipped rather than passed. Verifying an XML signature requires exclusive canonicalisation, and a hand-rolled c14n that disagrees with the IdP’s by one byte either rejects valid logins or accepts modified ones — which is where SAML libraries earn their CVEs. That belongs to the IdP SDK. What is implemented is the part those libraries have historically got wrong anyway: the structural checks, which need no crypto at all.

Supply chain, and the scanner.

Components
339production dependencies
Licences
12MIT, Apache-2.0, ISC, BSD-3-Clause, BSD-2-Clause, Unlicense
SAST rules
105 block a merge
Findings
0CI fails on any high

The SBOM is served as CycloneDX 1.6 and committed, so CI can fail when dependencies move without it being regenerated — an SBOM that silently drifts is worse than none, because it gets trusted. Generating it is delegated to pnpm sbom: the first version of that script walked the dependency tree by hand, then it turned out pnpm 11 ships the command, with licences, registry hashes and a dependency graph the hand-rolled one lacked. The wrapper now adds only what pnpm does not — deterministic ordering, so the artifact is diffable, and a staleness check.

The scanner is a regex engine with judgement, not a dataflow analyser, and every rule is one a syntactic check answers correctly. Its first run produced nineteen findings and all nineteen were false — it flagged the prose explaining why dangerouslySetInnerHTML is dangerous, and its own rule definitions matched their own patterns. A rule that is right seventy per cent of the time is worse than no rule, because within a week nobody reads the output. It now reports nothing across 328 files, with two genuine call sites signed off by name in the source.

mTLS, and what runs here instead.

Four questions, four answers — including the one where this approach is genuinely worse. Open whichever you care about.

Why not the real thingmTLS

Mutual TLS authenticates the connection: the client presents a certificate during the handshake and every byte after it is attributable before the application reads anything. That is a property of the TLS terminator. Vercel terminates TLS at its edge and never surfaces a client certificate to the function. The blueprint’s Envoy gateway is where this belongs, and there is no gateway here.

What replaces itEd25519

Ed25519 request signing. A detached signature over method, path, body hash, timestamp and nonce, verified before any work is done. The private key never crosses the wire, and unlike an HMAC the verifying side holds nothing capable of producing a signature — so compromising this server does not let anyone impersonate a client elsewhere.

Where it is betterBinds the body

It binds the request body, which mTLS does not. mTLS authenticates the channel, so anything an authenticated client sends down it is trusted; a signature means a compromised proxy cannot alter a request it is permitted to forward.

Where it is worseNamed, not hidden

It cannot reject an unauthenticated peer before the body is read, which is a real denial-of-service difference, and it pays a verification per request rather than per connection. Replay is bounded by a 5-minute window and a nonce cache that is per-instance — genuinely a hole on serverless, and named as one in the source rather than left to be assumed closed.