The AI Coding Assistant Is Spending Tokens to Find What The Scanner Already Found

Purple Hook cover: a metal hook lifts a red code block out of a stream of AI-written code before it reaches a pull request, with the line Blocked at the agent, Enforced at the PR.

Executive summary

A scanner finds a real bug. The report lands three days later. By then the engineer has moved on, and the person who knew that code is in another sprint. We’ve seen this for years in security programs. AI coding assistants make it worse. And now the cost shows up on the bill.

Key takeaways

  • If you scan at the pull request, in CI or at night, every finding on agent-written code goes back through a person and a new session. That costs reviewer hours and tokens.
  • Engineers turn off a gate they can’t read. Every block should say what ran, what it found and why it stopped the work.
  • Block only on new findings in the changed lines. A ten-line change shouldn’t fail because of an old backlog.
  • We found the same shell-injection bug three times in Claude Code CLI. It’s common in agent-written code. Catch it while the assistant still has the change open.
  • Keep the server-side pull request check as the enforced layer. A local hook is fast, but a developer can remove it.

The problem: the finding arrives after the work is done

An assistant writes a feature, pushes and closes the session. The pull request check runs later. Or CI runs later. Or the nightly scan. All of them run after the context is gone.

Then the expensive part starts. A reviewer looks at the result. An engineer copies the finding into a new session. The assistant reads the repository again to find the lines, works out the change again and looks for a fix. Every one of those reads costs tokens.

So the team pays for one finding twice. First in reviewer hours, when vulnerable code reaches the pull request. Then in rework and tokens, when the finding goes back to an assistant that starts from zero.

There’s one more cost, and people rarely count it. Engineers switch off checks that block without saying why. We’ve watched teams disable a gate within a week, because it stopped a merge and nobody could tell what it had scanned. That’s worse than an honest warning, because the dashboard still says the control is on.

What three CVEs in Claude Code taught us

On 31 March 2026, Claude Code CLI v2.1.88 went out on npm with a 59.8 MB source map. It mapped the minified code back to the original TypeScript. Our Purple Code Navigator research started that same evening.

We treated the CLI like any tool that reads repository files and environment variables: as software that handles untrusted input.

Static analysis gave us more than 100 findings. That’s the usual problem. They’re real, they’re not ranked, and nobody can check that many by hand. So we ran triage on the Purple code graph, which maps files, functions, calls and imports. For each finding we asked one question. Can untrusted input reach this point, and what does it touch when it gets there?

That cut the list to eight. Runtime tests confirmed three. They’re now CVE-2026-35020, CVE-2026-35021 and CVE-2026-35022, all OS command injection (CWE-78). We reported them to Anthropic on 31 March and published the technical write-up in April.

One root cause, three places

All three come from the same pattern. A config or environment value goes into a string, and that string goes to a shell. One is in terminal detection, one in the editor launch path, one in the authentication helpers.

None of them is inside the agent loop, where the CLI’s permission engine and sandbox do their work. The protections were real. They were just guarding a different door.

Chained together, the three turn a planted repository setting into stolen credentials. The risk is highest in CI/CD. There the assistant often runs with no person watching, against pull request branches, and the trust prompt a developer would normally see is skipped. We’ve left payloads and tooling out of this post.

Why this matters for your code

Command injection is a common bug. It was number nine in the 2025 CWE Top 25. It’s also the kind of code an assistant writes when a shell string is the shortest way to get something done. If a team that builds a coding assistant shipped this pattern three times, assume it’s in your agent-written code too.

For us the main lesson was about timing. Our graph found these in hours. So the question for any engineering team is simple: does the same finding reach your assistant in hours, or a reviewer in days?

Purple Hook: the check runs inside the session

That’s why we built Purple Hook. It’s generally available today for Phoenix Purple customers.

Purple Hook is a local check that runs inside the AI coding assistant your developers already use. It works at a few fixed moments:

  • When a session starts, it asks Phoenix to fetch the branch, so Phoenix’s copy stays current.
  • After a push, it starts a scan and hands back a ticket. The assistant keeps working, and the result shows up in the session on its next action.
  • When the assistant opens a pull request, it scans the whole branch against main. Your policy decides if it blocks, warns or goes through.

Commits are not scanned, and pushes are not held up. A scan on every commit would slow the session down for very little.

We built it around two rules. We’d ask the same from any tool that sits in this spot.

Rule one: engineers can see what it did

Every answer says what ran, what blocked, what didn’t and what couldn’t run. Findings come in three lists: the ones that block, the others worth fixing, and the ones an approver has waived, with a link to the decision.

If a scan was skipped or didn’t finish, the answer says so and gives the reason. It’s never shown as a pass. This rule matters most to us. A gate that quietly passes a failed scan is how a breach report ends up saying “the control was in place.”

The hook keeps a local log on the developer’s machine. Blocks and skips are reported to the organization by repository, workspace and time. Reports don’t name the developer, and the install screen says this up front.

Rule two: tokens go into the fix

Each finding comes with its file, line, severity and remedy. The remedy is built from the same Purple code graph that found the Claude Code CVEs. So the assistant goes straight to the fix and doesn’t spend a round of reads looking for the code.

The rest of the design comes from the token budget:

  • Only findings in the changed lines can block. Older findings go to a “fix these too” list, so a ten-line change is judged on those ten lines.
  • The notice has a fixed size. If there are more findings than fit, it says how many and how to ask for them.
  • A slow scan returns a ticket. The assistant keeps going and gets the result on its next action, with no polling and no retries.
  • AI-suggested fixes are optional. When an admin turns them on, each one is marked as an unverified suggestion. It can’t remove a finding or change a verdict. People still review and merge every pull request.

The logic is easy to follow. Every step the hook removes is a step the assistant no longer pays for.

Security sets the floor

Admins set the policy for each moment in Settings > Scanning > Hook policy. For each one they choose off, warn, scan receipt or block. They also pick which areas to scan, which severities block and whether to include remediation.

The organization policy is the minimum. A workspace can make it stricter, never weaker. The Enforcement page shows which repositories have the hook installed and up to date, and which workspaces have gone quiet. Every developer installs the hook with their own narrow key, which can run the check and do nothing else.

The hook lives in the developer’s project, so a developer can remove it. That’s why Phoenix’s server-side pull request check stays on. The hook is the fast layer. The server check is the one nobody can switch off, and a repository without the hook is still gated there.

What a session looks like with the hook

Take the same bug class and put it in a normal feature. An engineer asks the assistant to add an export job. To call a conversion tool, the assistant builds a command string from a filename and sends it to a shell.

The assistant pushes. The push goes through right away. The hook asks Phoenix to fetch and scan the branch, and gets a ticket back. The assistant moves on to the tests.

A few minutes later, on its next action, the result shows up in the session. One blocking finding: command injection, with the file, the line, the severity and the fix. The fix is to pass an argument list instead of a shell string. Below it, two older medium findings from the same module sit in the “fix these too” list.

The assistant applies the fix, runs the tests and pushes again. It doesn’t need to search the repository or re-learn the export job. It never lost that context.

Now the pull request. This workspace blocks on Critical and High code findings at pull request time. The hook scans the whole branch against main. The command injection is gone, nothing else blocks, and the pull request opens. Phoenix’s own pull request check runs too and records that a local check ran for that commit. The reviewer opens a pull request that’s already clean.

If the scan had taken longer than the admin’s wait time, five minutes by default, the pull request would have opened with a ticket, and the verdict would have followed. If the finding had been a false positive, the answer would have ended with the command to request a waiver. An approver in the organization decides, and the finding moves to the Waived list with a link to the decision.

Purple Hook terminal output showing the server policy, block on rule CRITICAL/HIGH and AI CRITICAL, the scan job ID, the waiver request command for a false positive and exit 2.
Every block says which policy applied and how to ask for a waiver.

Without the hook, the same feature goes very differently. The finding shows up on the pull request the next morning. Someone pastes it into a new session. The assistant spends its first reads looking for code it wrote yesterday.

What to check on Monday morning

Whether you use Phoenix or not, these are the checks we’d run on any team that ships agent-written code.

  1. Check when your findings land. Take ten recent findings on agent-written code. Note the time from the commit to the moment an engineer saw the finding. If the median is in days, the assistant is paying to rediscover its own work.
  2. Read your gate’s output like a developer would. If a block doesn’t say what ran and why it stopped the merge, expect someone to turn it off. A skipped scan that shows up green is a problem by itself.
  3. Block only on the change. Block on new findings in the changed lines, at the severities you care about. Put the backlog in a separate list with its own campaign.
  4. Search for shell strings. Look in agent-written code for commands built from string interpolation and sent to a shell. Replace them with argument lists. That’s the bug behind all three Claude Code CVEs, and it’s cheap to fix.
  5. Keep a server-side gate. Whatever runs on the laptop, keep a pull request check that nobody can turn off. Watch for repositories that stop reporting.
  6. Measure tokens per fix. Take a fixed set of fix tasks. Compare tokens and time with and without findings in the session. Bring that number to your next budget talk.

Next steps

  • Read the full Claude Code CVE write-up for the vulnerability chain and hardening steps for teams running the CLI.
  • Ask your Phoenix admin to set a hook policy for one workspace, then install the hook from the Enforcement page.
  • Book a demo to see Purple Hook block a pull request and hand the assistant the fix in the same session.

Protect yourself with Phoenix Purple – find TRUE critical chainable vulnerabilities with exploits

Francesco is an internationally renowned public speaker, with multiple interviews in high-profile publications (eg. Forbes), and an author of numerous books and articles, who utilises his platform to evangelize the importance of Cloud security and cutting-edge technologies on a global scale.

Discuss this blog with our community on Slack

Join our AppSec Phoenix community on Slack to discuss this blog and other news with our professional security team

From our Blog

Node2Shell was the headline. The expansion is the story: a Brotli decoder bug that now sits in .NET, data engines, archive tools, firmware and fonts, most of which no distribution update will fix.
Marcus Webb
Phoenix Security’s latest platform release tackles the three points where AI security tools break down: unverified findings, firewalls nobody can live with, and remediation that stops at a ticket. Grounded verification, real exception workflows, and PR-first remediation replace guesswork with proof, and tickets with merged code.
Alex Evangelou
Anthropic’s models found 29,439 candidate vulnerabilities in open source. Its dashboard shows 516 patched upstream. That 1.75% is the real story. Vulnerability management now depends on prioritisation, ownership and how fast you consume upstream fixes, because exploits arrive in minutes and median KEV remediation sits at 43 days.
Francesco Cipollone
Derek

Derek Fisher

Head of product security at a global fintech

Derek Fisher – Head of product security at a global fintech. Speaker, instructor, and author in application security.

Derek is an award winning author of a children’s book series in cybersecurity as well as the author of “The Application Security Handbook.” He is a university instructor at Temple University where he teaches software development security to undergraduate and graduate students. He is a speaker on topics in the cybersecurity space and has led teams, large and small, at organizations in the healthcare and financial industries. He has built and matured information security teams as well as implemented organizational information security strategies to reduce the organizations risk.

Derek got his start in the hardware engineering space where he learned about designing circuits and building assemblies for commercial and military applications. He later pursued a computer science degree in order to advance a career in software development. This is where Derek was introduced to cybersecurity and soon caught the bug. He found a mentor to help him grow in cybersecurity and then pursued a graduate degree in the subject.

Since then Derek has worked in the product security space as an architect and leader. He has led teams to deliver more secure software in organizations from multiple industries. His focus has been to raise the security awareness of the engineering organization while maintaining a practice of secure code development, delivery, and operations.

In his role, Jeevan handles a range of tasks, from architecting security solutions to collaborating with Engineering Leadership to address security vulnerabilities at scale and embed security into the fabric of the organization.

Jeevan Singh

Jeevan Singh

Founder of Manicode Security

Jeevan Singh is the Director of Security Engineering at Rippling, with a background spanning various Engineering and Security leadership roles over the course of his career. He’s dedicated to the integration of security practices into software development, working to create a security-aware culture within organizations and imparting security best practices to the team.
In his role, Jeevan handles a range of tasks, from architecting security solutions to collaborating with Engineering Leadership to address security vulnerabilities at scale and embed security into the fabric of the organization.

James

James Berthoty

Founder of Latio Tech

James Berthoty has over ten years of experience across product and security domains. He founded Latio Tech to help companies find the right security tools for their needs without vendor bias.

christophe

Christophe Parisel

Senior Cloud Security Architect

Senior Cloud Security Architect

Chris

Chris Romeo

Co-Founder
Security Journey

Chris Romeo is a leading voice and thinker in application security, threat modeling, and security champions and the CEO of Devici and General Partner at Kerr Ventures. Chris hosts the award-winning “Application Security Podcast,” “The Security Table,” and “The Threat Modeling Podcast” and is a highly rated industry speaker and trainer, featured at the RSA Conference, the AppSec Village @ DefCon, OWASP Global AppSec, ISC2 Security Congress, InfoSec World and All Day DevOps. Chris founded Security Journey, a security education company, leading to an exit in 2022. Chris was the Chief Security Advocate at Cisco, spreading security knowledge through education and champion programs. Chris has twenty-six years of security experience, holding positions across the gamut, including application security, security engineering, incident response, and various Executive roles. Chris holds the CISSP and CSSLP certifications.

jim

Jim Manico

Founder of Manicode Security

Jim Manico is the founder of Manicode Security, where he trains software developers on secure coding and security engineering. Jim is also the founder of Brakeman Security, Inc. and an investor/advisor for Signal Sciences. He is the author of Iron-Clad Java: Building Secure Web Applications (McGraw-Hill), a frequent speaker on secure software practices, and a member of the JavaOne Rockstar speaker community. Jim is also a volunteer for and former board member of the OWASP foundation.

Join our Mailing list!

Get all the latest news, exclusive deals, and feature updates.

The IKIGAI concept
Protected By
Shield Security PRO