Skip to main content
[AVAILABLE], all three runs below are real output from this session, commit 651497a.

Goal

Confirm three different kinds of tampering are actually caught, not just documented as caught: a changed parameter, a forged signature, and a replayed nonce.

Prerequisites

Steps

examples/tutorials/ 35 through 46 are a dedicated negative-path suite: each one generates something valid, mutates exactly one thing, re-verifies, and asserts the mutation is caught. They run in CI on every change (npm run examples), so “the tests are always green” and “the guide’s claims are true” are the same fact. Three representative ones:

1. Parameter tampering

node_modules/.bin/tsx examples/tutorials/36-parameter-tampering/run.ts
Original Hash
4b7761f6f7bb6cf672d1193298423c60b39ac47d7c00dbfd2739b153c8abf015

Tampered Hash
82285dfe0635541f7f72e719b4e5eb959e581b1b0a69631789e4d6599983368a

✓ Parameter tampering detected.
Execution rejected.
Changing paymentAmount in the executable content changes the recomputed businessTransactionHash, this is the exact mechanism The gateway runs on every real request, exercised directly here instead of through HTTP because the REST API generates and checks the authorization within one call, giving an external client no tamper point to observe.

2. Forged signature

node_modules/.bin/tsx examples/tutorials/29-authorization-tampering/run.ts
Generating authorization...
✓ Authorization generated.

Authorization payload modified.

Verifying tampered authorization...

Valid               : false
Version Supported   : true
Signature Verified  : false
Not Expired         : true

✓ Tampering detected.
Note which check failed and which didn’t: Version Supported and Not Expired both stayed true, only Signature Verified flipped. EnvelopeVerifier reports each check independently, a caller can distinguish “this is forged” from “this is expired” rather than getting one opaque false.

3. Nonce reuse

node_modules/.bin/tsx examples/tutorials/42-nonce-reuse/run.ts
First Verification
--------------------------------------------------
Accepted     : true
Nonce Unseen : true

Second Verification
--------------------------------------------------
Accepted     : false
Nonce Unseen : false

✓ Nonce reuse detected.
Execution rejected.
The exact same, unmodified authorization is verified twice. The first call marks the nonce seen; the second call, identical envelope, identical signature, is rejected solely because the nonce was already consumed, single-use enforced by the NonceStore, not by anything in the signature itself.

Verify

All three runs above completed with their respective ✓ ... detected. line and a non-zero distinguishing signal (hashMatches: false, Signature Verified: false, Nonce Unseen: false), confirmed in this session. None of the three silently passed, none threw an unrelated error instead of the expected rejection.

Troubleshoot

  • You expected an HTTP 4xx from the REST API and got something else. These three scenarios operate on the authorization envelope directly, at the library level, they don’t go through POST /execute. The REST API’s gateway rejection looks like a generic 500 with a message naming the failed check (ExecutionGateway.ts’s describeFailure, see The gateway), not a per-check breakdown like EnvelopeVerifier gives you here.
  • Want to see more variants? examples/tutorials/ also covers action substitution (37), target substitution (38), policy substitution (39), expired authorization (41), stolen authorization (43), direct API bypass (44), connector bypass (45), and TOCTOU protection end to end (46), same pattern each time: generate, mutate one thing, re-verify, confirm rejection.

Next

Verify a trust record independently

The same tamper-then-fail pattern, applied to a trust record’s own hash.

Content Binding & TOCTOU

The mechanism behind the parameter-tampering check above.