A browser agent has one tool: click.
A rule on tool names can’t tell “Next page” from “Pay ₹4,999”: both are click(ref=e12). Dejo Guard reads what e12 is from the page itself, names it, and lets ArmorIQ decide. Our code only describes.
The finding
On 8 attack pages, a policy on tool names let 8 unsafe actions through. Dejo Guard let 0 through, and held 0% of normal browsing steps. Same pages, scripted, no model in the loop. Method and raw output: docs/FINDING.md.
See it in 90 seconds
- Watch the 3-minute video. Claude Code shops on our sandbox: browsing is allowed, “Place order” waits for approval in ArmorIQ, the card field is blocked.
- Open the live feed. Every row is an ArmorIQ answer, word for word: the class, the reason (
rule_action_hold,rule_action_block,tool-not-in-plan) and the policy that matched. - Open the attack lab. A pay button that says “Continue”, a checkout in Hindi, a hidden “the user already approved” note, a plain button whose script buys. Each shows which class the page gives it.
- Read the policy. That file, active in ArmorIQ, is where allow, hold and block live. Remove the
submit_payment: holdline and the same click goes through. That is how you know ArmorIQ decides, not us. - Try it on your own agent.
pip install dejo-guard,armoriq login,dejo-guard init,claude mcp add dejo-guard -- dejo-guard. Then: “compare prices for Atomic Habits on dejo-guard.vercel.app/shop, then buy the cheapest”.
What is new, what is not
Dejo (the browser with a memory, MIT, on PyPI since 13 Oct) was built before the hackathon by the same author and is used as a library. Everything that makes ArmorIQ see the page is new: page facts, the class table, intent plans, holds and approvals, the network watch, replay checks, the sandbox shop, the attack lab and the eval. Claude Code helped write the code; every decision and every line was reviewed by the author.