The join is the product
You can get a contract review that never names the model. The matching AI review will skip the signer. We review the place they share a principal.
Failure modes we review
Examples, not a catalog. Each one disappears if you review either surface alone.
- An agent that can
signortransferwithout the human in the loop the invariant named. The contract is correct. The signer is not who the spec assumed. - A model inside a prover or compiler pass that can change what the circuit means. A learned heuristic picks constraints. A synthesis step drops a range check under a cost function nobody audited.
- Tool-calling as authorization. The tool schema says
sign_tx(to, value, data). The policy that should gate it lives in a system prompt, which is text, not a control. - Keepers writing model-scored params on-chain. LTV, liquidation threshold, oracle weight. No bound, no rate limit, no second signer.
- Intent flows that replay. A solver can resubmit a signed intent after the agent’s context changed, because nonce and expiry lived in a prompt template, not in the contract.
- Shared memory between a public channel and the wallet plugin. Discord writes to a store the signer reads. Injected text becomes a transfer.
- A “read-only” agent that still holds a production key, because the same process runs the tool loop and the signer, and the key sits in its environment.
- Glue scripts that neither repo’s threat model mentions: the cron that rotates the keeper key, the CI job that deploys the model and the contract in one step, the simulation RPC whose result is trusted as a go/no-go.
What a join review covers
- One threat model for the on-chain surface, the model or agent surface, and the glue. Both benches sign the same invariants.
- Who may author a transaction, who may sign it, and whether any component can be both.
- Tool authorization. Schemas, argument validation, confirmation gates. What happens when a tool returns text that looks like an instruction.
- Memory and retrieval are trust boundaries. Who can write, what the signer reads, whether a document can become a decision.
- Model artifacts in the pipeline: file formats, provenance, custom ops, and the loader that runs them next to keys.
- Prover and compiler paths. If an ML pass can touch soundness or completeness, it is in scope.
- Keepers, oracles, parameter writes. Model output to a state change, including bounds and rate limits.
- A retest of the fixes you land. The report names what crosses each hop.
What it does not cover
- Protocol economics, except the invariants we agree in scope. We check that the wrong principal cannot write the parameter. Whether the parameter is wise is a different job.
- Model quality. Benchmark scores, helpfulness, and accuracy are not security properties. If an eval claims a safety property, we review that claim.
- Training data provenance stays out unless artifact chain of custody is explicitly in scope.
- Hosting and cloud infrastructure penetration testing, unless the agent runtime itself is scoped.
- Social engineering of your team. Physical security. Incident response.
- Continuous monitoring. A review is a point in time. Continuous review is for the deltas after a first engagement.
- We do not prove the system is safe. The report lists what we attacked, what we found, and what we did not look at.
How this differs from two separate audits
Two vendors write two threat models. The contract report assumes the signer is a known key. The model report assumes the tool call is gated downstream. Each can be internally correct. The glue sits in both out-of-scope lists.
A join review starts from one brief: the written threat model and the invariants. A hop is a finding. Model output to a signature. Retrieval to a parameter write. A prover heuristic that changes a constraint. Same severity scale as reentrancy or a deserialization flaw. One team holds both ends.
You get one retest and one document. It names each hop, which side owns the fix, and what was never in scope. Counsel should not have to reconcile two PDFs that each disclaimed the glue.
Request a scoping call
Bring the wallet, the agent, and the glue in one request. If another vendor already owns one of those, say so. Split scope is a decline or a rewrite.