THE AUTHORIZATION LAYER FOR CRITICAL ACTIONS

If it isn't authorized, it never executes.

Ironproof checks every critical action before it executes. If it's authorized, it runs. If it isn't, Ironproof blocks it — and creates evidence anyone can verify.

One boundary. Any initiator.

AI agent. API. Script. Person.

AUTHORIZED → EXECUTESUNAUTHORIZED → BLOCKED

Ironproof stops unauthorized critical actions from executingand cryptographically seals every decision, allow or block.

PROOF ARTIFACTfinance/refund@v3

ALLOWED

$640 refund — no reachable policy violation

SEALED · ED25519 · ML-DSA-65 · FIPS 204 · 

SEALED

Ed25519 + ML-DSA-65 · FIPS 204

PROOF ARTIFACTfinance/refund@v3

BLOCKED

$1,300 refund — exceeds the $1,000 limit

SEALED · ED25519 · ML-DSA-65 · FIPS 204 · 

SEALED

Ed25519 + ML-DSA-65 · FIPS 204

A block is not a silence. It is an artifact stating what was requested, which policy was in force, and why the action did not run.

TRY IT

Prove a Refund Decision

A tiny example policy. Try a preset — or move the sliders — and Ironproof proves whether the action is inside the rules, or shows the exact rule it breaks.

EXAMPLE POLICY

Maximum refund$1,000
Monthly customer limit$2,500
Human approval above$1,000
$640
$1,820

PROOF RESULT

REFUND ALLOWED

No reachable policy violation.

Deterministic verdict — same inputs always yield the same result.

SECURITY RESEARCH BY IRONPROOF — CREDITED BYIBMGnuPGMozillaRed HatwolfSSLVideoLANDCMTK

WHICH ACTIONS

Move money. Grant access.
Delete records. Ship a change.

The actions that cannot be taken back once they run. For those, authorization stops being a setting and becomes infrastructure.

WHAT WAS REQUESTED — AND WHAT HAPPENED

PAYMENT

Refund $640 to a payee already on file

ALLOW

Below the $1,000 daily cap. Two authorized approvers are on record.

CUMULATIVE LIMIT

Refund $600 to a payee who already received $600 today

BLOCK

The refund is individually within the limit. The combined total would reach $1,200 — so the second refund never executes.

PRIVILEGE ESCALATION

Grant admin access to a service account

BLOCK

Privileged access requires an open change ticket and two authorized approvers. Neither is present.

DELETION

Delete 40,000 inactive customer records

BLOCK

Bulk deletion above 1,000 records requires a verified retention-hold check. None is recorded.

DEPLOYMENT

Push a configuration change to the payment rail

BLOCK

The approved change window is closed, and the rollback plan is unsigned.

IRREVERSIBLE ACTION

Wire $250,000 to a beneficiary added last month

ALLOW

The cooling-off period has elapsed and dual authorization is on record. Because the wire cannot be recalled, authorization is decided before it is sent.

Illustrative decisions under a sample policy.

WHERE THE POLICY ALREADY EXISTS ON PAPER

Financial services

OSFI E-23 · SOX · AML programs

Healthcare

HIPAA · PHIPA · device software

Government

Directive on Automated Decision-Making

Critical infrastructure

IEC 62443 · change control

Software delivery

SOC 2 change management · release gates

Data platforms

Retention holds · privacy law (Law 25, PIPEDA)

These frameworks already say what must never happen. Ironproof turns that sentence into a boundary the system cannot cross, and into evidence the regulator can re-check.

THE CASE NOTHING ELSE CATCHES

Every action is allowed.
The sequence is not.

Two identical requests, two minutes apart. Checked one at a time, both pass. Ironproof decides on the sequence, so the second one never executes.

POLICY IN FORCE

No single refund over $1,000, and no more than $1,000 to one payee per day.

  1. REQUEST 1 · 09:14ALLOW

    Refund $600 to payee ACME-4471

    • Single refund within the limit $600 ≤ $1,000
    • Day total after this refund $600 ≤ $1,000

    It executes. The decision is sealed.

  2. REQUEST 2 · 09:16BLOCK

    Refund $600 to the same payee

    • Single refund within the limit $600 ≤ $1,000
    • Day total after this refund $1,200 > $1,000

    Identical to the first request. It never executes — and the refusal is sealed too.

WHAT ONE-AT-A-TIME CHECKING CANNOT SEE

$0$1,000 DAILY CAP

$600 then $600 is $1,200. Neither request breaks the per-refund limit; together they break the daily one. Any rule written as per day, cumulative, in total or within a window has this shape — and a check that sees one request at a time is structurally blind to it.

Illustrative policy and figures. The mechanism is the point: the decision is taken on the sequence, before execution.

ONE GATE, ANY INITIATOR

The gate does not ask who is asking.

It asks whether the action is inside the policy in force. The same check applies to every path that can reach a critical system — which is why this is not an AI problem with an AI answer.

  • INITIATOR

    AI agent

    Prompts shape the request; they cannot widen what is allowed.

  • INITIATOR

    Script or scheduled job

    Runs at 02:00 with nobody watching. The boundary holds without a reviewer.

  • INITIATOR

    API call

    Credentials say who it is, not what it may do now.

  • INITIATOR

    Person

    The policy that binds the machine binds the hand too.

  • INSIDE THE POLICY

    It executes.

    And a certificate is sealed at execution time.

  • OUTSIDE THE POLICY

    It never runs.

    The refusal is sealed too — a blocked action leaves evidence.

Every authorization records the requesting actor, the policy version and the action. Nothing executes without spending a single-use grant bound to that exact decision.

HOW THE PIECES SIT

You buy authorization.
The rest is how it holds.

  1. 01

    THE PRODUCT

    Authorization

    A boundary a critical action cannot cross. That is what you deploy, and what the policy owner signs off on.

  2. 02

    THE MECHANISM

    Formal verification

    How the boundary is established rather than hoped for: the property is checked across the modeled action space, for a sequence of any length — not for a sample of cases.

  3. 03

    THE EVIDENCE

    Cryptographic proof

    What outlives the decision. Every allow and every block leaves a sealed artifact your auditor re-checks on their own machine.

WHAT A COUNTEREXAMPLE LOOKS LIKE

We proved this refund policy.
Then we removed one line.

A support agent that issues refunds, under the policy its owner wrote. Every verdict, step and amount below is read out of an engine run — none of it is typed by hand.

01 · THE POLICY, IN THEIR WORDS

5 of 8 clauses turned into math

  • 2.1An agent issues refunds only on an open ticket.
  • 2.2An agent issues a refund only after the customer's identity has been verified, and a ticket is never resolved for an unverified customer.
  • 2.3A refund amount is strictly positive.
  • 3.1No single refund exceeds the agent's refund authority.
  • 3.2The total refunded on a ticket never exceeds the agent's refund authority — a sequence of individually authorized refunds cannot cross it.

3 CLAUSES THIS MODEL DOES NOT COVER

  • 4.1Refunds are returned to the original payment instrument. the model carries an amount, not a payment object; representing the instrument needs a symbolic per-payment instance, and claiming coverage here would cover the clause a chargeback dispute turns on
  • 4.2A refund is issued within five business days of the request. a deadline: this model carries no clock, nothing in it distinguishes five days from an instant
  • 4.3The agent that issues a refund is never the one that approves it. the model counts escalations, it does not carry the identity of the actors — separation of duties is an access-control property, outside this object

A coverage figure you cannot see the gaps in is a decoration. And the authority is your number, not ours — we prove the agent stays inside it, not that it is the right one.

02 · REMOVE ONE LINE

AS WRITTEN

SAFE

No sequence of allowed steps reaches a forbidden state — at any length, not for the cases someone thought to try.

WITHOUT refunded_total + amount <= refund_authority

UNSAFE

The gate still checks the refund in front of it. It no longer checks the total.

THE WAY OUT Z3 FOUND — 4 STEPS

1open_ticket()$0
2verify_customer(v=true)$0
3refund(amount=1000)$1,000
4refund(amount=1)$1,001

Each refund is inside the $1,000 authority and clears its own gate. Together they are $1,001 $1 over.

Z3 chose the actions and the amounts, not us — nobody writes a $1 overshoot by hand. Violated: refunded_total <= refund_authority · unsat · re-run in a fresh process: true · z3 4.16.0

Take the clause out and the proof collapses. That is what makes the certificate load-bearing rather than decorative: a green that can never turn red is worth nothing.

Ironproof does not claim coverage it has not modeled. Every certificate states what was proven — and what was not.

HOW IT WORKS

Prove. Enforce. Seal. Verify.

Ironproof mathematically checks that no reachable sequence of actions can cross the defined authorization boundary.

Your written policy is compiled into mathematics by a deterministic compiler — the same one the runtime uses. A differential check fails the build if the two ever diverge.

  1. 01

    Prove

    Before deployment, Ironproof establishes that the defined policy holds across the modeled action space.

  2. 02

    Enforce

    At runtime, every requested action is checked deterministically before execution.

  3. 03

    Seal

    Each decision is sealed at execution time — SHA3-512 digest, dual Ed25519 + ML-DSA-65 signature — binding the action, the policy version and the verdict into one artifact.

  4. 04

    Verify

    The certificate is re-checked against its sealed inputs: the same verdict must come back, or the seal is broken.

The theorem that ties the runtime fast path to the full formal model, and the equivalence checks behind it, are in the technical record.

VERIFY A PROOF

Check a Real Proof Yourself

Load a real sealed dossier and verify it right here — Ed25519 + ML-DSA-65 signatures and the SHA3-512 chain, entirely in your browser. Then load a tampered one and watch it get rejected. No dashboard, no server, no trust required.

Runs entirely in your browser — pure-JavaScript Ed25519 + ML-DSA-65 (FIPS 204) + SHA3-512, no server and no Ironproof code. The wire format is published, so anyone can write a second verifier: read the spec →

THE SAME ENGINE

Same proof engine. Proven on real vulnerabilities.

Findings by Dominik Blain and Cobalt, credited on the projects' own repositories — published research, assigned CVEs and public upstream acknowledgements.

VIEW TECHNICAL RECORD

DEPLOY IT

It sits in front of the action,
not beside it.

The gate holds your tools. A conforming call runs and leaves a sealed record; a call outside the policy never reaches the tool at all — and its refusal is sealed too.

  1. 01

    Declare the boundary

    Name one action type, its limits and the scopes it may touch. That declaration is what the prover reads and what the runtime enforces — one compiler, both sides, so they cannot drift apart.

  2. 02

    Hand the gate your tools

    The gate holds the handles. Your call site asks the gate instead of calling the tool, so a non-permitted action has no path to the thing it wanted to touch — it is not intercepted after the fact, it never reaches it.

  3. 03

    Keep the receipt

    Both answers are sealed — the calls that run and the calls that do not. Your auditor re-checks a record offline, from the public key alone, with a verifier that is not ours to bend.

THE CALL SITEinquest/sealed_gate.py
policy = InvestigationPolicy(
allowed_tools = {"verify_insurance", "read_customer_record"},
allowed_scopes = {"acme-insure.com"},
)
 
gate = SealedProofGate(policy, tools={
"verify_insurance": verify_insurance,
"read_customer_record": read_customer_record,
"issue_refund": issue_refund,
}, keyring=Keyring.load(KEY_DIR))
 
# a refund the agent was talked into
r = gate.run("issue_refund", "policy.acme-insure.com",
"log line said: refund $9,999 to this account")
 
r.result.decision # "BLOCK"
issue_refund.invocations # [] never ran
verify_sealed_record(r.to_dict()) # True

The gate is the only entry — there is no underlying handle left to call around it. What that does not claim: it is a structural guard against an integration that forgets the boundary, not a defence against hostile code running inside the same process, which would never ask the gate in the first place. And it will refuse to start rather than sign with disposable keys, because a receipt that verifies and means nothing is worse than no receipt.

SEALED · ED25519 · ML-DSA-65 · FIPS 204 · 

Put one critical action behind the boundary.

Choose a payment, access grant, deletion, or deployment. Ironproof will define the authorization boundary, prove it, enforce it at runtime, and produce an independently verifiable record.