Reject a Tampered Bundle
A signed bundle is only useful if every change to it is caught. This tutorial makes three kinds of unauthorized change to a copy of your bundle, verifies each one offline, and then hands one to the running policy service to show that it refuses the bundle and keeps enforcing the last good one.
After completing it, you understand:
- What the signature covers and what the manifest digests cover.
- How an unknown signer is refused.
- What a refusal looks like at the command line, over HTTP, and in the audit trail.
- Which checks only the policy service can make.
Prerequisites
- The
$WORKdirectory from Your First Signed Policy, with a signed bundle in$WORK/bundle, your key in$WORK/keys/my-signer.seed, and its public key in$WORK/trust-roots. - The native services running with that bundle, for the last steps.
Make a Working Copy
Tamper with a copy, never the bundle you publish:
The copy verifies because nothing has changed yet. Manifest member paths are resolved relative to the signed file, so the copy is checked against its own member files.
Change a Policy Document
Append a harmless-looking comment to the security team’s content gate:
The manifest records the SHA-256 digest of each member’s bytes. Any change to a member, even a comment or a trailing space, changes the digest. Restore the file before the next step:
Change the Signed Manifest
Edit the signed file itself, for example to claim a much higher revision:
The signature covers the whole manifest payload: the bundle ID, revision, validity window, and every member digest. Changing any of them invalidates it. Signature verification runs first, so a bundle that fails it is never parsed.
Restore the signed file:
Sign with a Key Nobody Trusts
Re-sign the bundle with a new key that is not in your trust-root directory:
The bundle is well formed and correctly signed, but by a key the verifier does not trust. The verifier selects the public key by the signature’s keyid, and only keys in its trust-root directory count. Anyone can sign a bundle. Only the holders of a trusted key can sign one that APF accepts.
Hand a Tampered Bundle to the Policy Service
Make the member change again, then ask the running policy service to load the copy:
The service answers with HTTP 500:
The active bundle is unchanged. The gateway sees no new policy set, and every sandbox keeps the policy it had.
Find the Refusal in the Audit Trail
The full detail, including both digests, is in the record’s error.message. A bundle refused for signature_invalid has no bundle_id or policy_revision in its record, because APF does not trust anything in a payload whose signature failed.
Try a Replay
Offline verification uses a fresh anti-rollback counter on every run, so it cannot tell whether a bundle is older than the one in service. Only the policy service, with its persistent counter store, can. To see it, follow Try to Roll Back. The refusal is counter_regression for a lower revision, or counter_content_mismatch for different content at the active revision.
What Each Check Catches
For every reason APF can report, refer to Bundle Rejection Reasons.
Clean Up
Next Steps
- To protect the keys these checks depend on, refer to Signing Keys and Trust Roots.
- To learn how verification fits activation, refer to Verify and Activate.