How to Use Claude for Adversarial Testing of Your Own Source Code
A practical method for running an adversarial AI pass over code you own — how to frame the prompt so it finds real defects, why nothing counts until you reproduce it, and what this will never catch.
Published
The short answer: Asking a model to "review this code" produces a politely shaped summary. Asking it to break one specific assumption at one specific trust boundary produces findings worth triaging. Both cost the same five minutes; only one is useful. The discipline that makes it work is refusing to count any finding you have not reproduced. The discipline that keeps it legitimate is that this is your own code, on your own systems, with authorisation.
Most software has never been attacked on purpose. It has been reviewed by the people who wrote it, run through whatever the build pipeline includes, and then shipped — and the first genuinely adversarial reader it meets is not on your side.
A penetration test by qualified people is the right answer to that, and it costs real money on a real schedule. Between doing nothing and commissioning an engagement there is a cheap intermediate step: spend an afternoon attacking your own code with a model that is very good at reading unfamiliar code and generating hypotheses about how it fails. Done properly this finds real defects. Done the way most people do it, it finds nothing and leaves everyone feeling reassured, which is worse than not doing it.
Everything below assumes the code is yours and the systems are yours, or that you have written authorisation from whoever owns them. That is not a formality — it is the line between security work and something else entirely, and it is worth having in writing before you start rather than after someone asks.
Why "Ask the AI to Review This Code" Finds Almost Nothing
The failure is in the prompt, not the model.
It has no target, so it optimises for coverage. Asked to review, it returns the things that are always true of code: error handling could be better, this function is long, consider adding tests. All correct, none of it a vulnerability.
It does not know which inputs an attacker controls. Without a trust boundary, a string is just a string. The same concatenation is a non-issue in a startup script and a serious problem in a request handler, and nothing in the file itself tells the model which one it is looking at.
It is agreeable unless told otherwise. "Does this look secure?" is a question that invites reassurance, and you will get it. The framing has to make finding a problem the successful outcome, not the awkward one.
A file in isolation is missing the part that matters. What calls this, with what, on whose behalf, after which checks — that context lives elsewhere in the codebase, and a review of the file alone is a review of a fragment.
What Adversarial Framing Changes
How Do You Prompt Claude to Attack an Assumption Instead of Summarising a File?
State the assumption you want broken, in one sentence, and ask for its refutation. Not "review this authorisation code" but "this endpoint assumes a caller can only reference order IDs belonging to their own organisation — find every path by which that could be false." One assumption per pass. The narrower the target, the more usable the output.
Demand an exploitation path, not a verdict. A finding should arrive as a sequence: this input, sent in this state, by this actor, produces this result. A claim without a path is a guess dressed as a finding, and asking for the path filters out a large share of them before you ever look.
Give it permission to find nothing. Say explicitly that "no viable attack on this assumption given this code" is an acceptable and useful answer. Without that, the space gets filled.
Make it rank against your own model. Ask which of the findings an attacker would actually try first and why. The reasoning it gives is often more informative than the ranking, and it exposes when the model has misunderstood your architecture.
Which Context Actually Changes the Answer?
Four things, and their absence is why most attempts fail.
The trust boundary — where attacker-controlled data enters, and what the system believes about data on each side of that line. The authentication and authorisation model — how the caller's identity is established, where entitlement is checked, and what happens when the check is skipped. The data model — what is scoped to a tenant, a user, or nothing at all. The threat model — an internal tool with twelve named users and a public sign-up form deserve completely different attention.
Give it those and it reasons about your system. Withhold them and it invents a plausible architecture, then reviews the one it invented.
A Practical Adversarial Pass, Step by Step
Build the Target Model Before You Prompt Anything
Spend half an hour writing down the entry points, the roles, what each role is permitted to do, where the data you would least like to lose lives, and the three assumptions you would be most upset to discover were wrong. That document is what the entire pass runs against, and it has value even if you stop there — most teams have never written it down, which is itself part of the problem.
Run One Attack Hypothesis at a Time
Work boundary by boundary and assumption by assumption. A prompt covering ten concerns returns shallow output on all ten; a prompt covering one returns something you can act on. Keep the scope to code that makes sense together — a handler plus the middleware and data access it depends on, rather than a whole repository, which will not fit and would dilute attention if it did.
Vary the attacker deliberately. An unauthenticated stranger, an authenticated customer belonging to a different organisation, a former employee whose token has not expired, and someone who can replay a request they legitimately made an hour ago are four different readers of the same code, and they find different things.
Triage: Nothing Counts Until You Reproduce It
Every finding gets exactly one label. Reproduced means you made the bad thing happen — in a test, against a local instance, with the steps written down. Refuted means you traced the path and it does not exist. Needs more information is a holding pen, not a conclusion, and a finding that stays there for a week is a finding nobody believed.
Only the reproduced ones become work. This rule feels harsh on the first pass and is the entire reason the exercise is worth anything.
Adversarial AI Review vs Static Analysis vs a Real Penetration Test
- Cost — AI review wins outright. It is the price of a subscription and an afternoon.
- Breadth of code covered — Static analysis wins. It runs over everything, every build, without anyone deciding what to look at.
- Understanding of intent and business logic — AI review wins clearly. A scanner cannot tell that this refund path should never be reachable by a customer; a model reasoning about your target document can.
- False-positive burden — Static analysis and AI review both lose, in different ways. Scanners produce many mechanical false positives you learn to filter; AI review produces fewer but far more convincing ones.
- Chained and multi-service exploitation — Penetration testing wins outright. Combining a weak reset flow with an information leak in another service is what experienced testers do and neither of the others attempts.
- Assurance you can show a client or an auditor — Penetration testing wins, and it is not close. A report from a qualified tester is evidence; a chat transcript is not.
Read that as a sequence rather than a menu. AI review before static analysis before an engagement means the expensive step is not spent finding things you could have found for free.
The False-Positive Problem
Fluent, plausible prose is the model's strongest output and your largest cost. Two failure modes matter, and they look identical on the page.
The first is a finding that describes a real vulnerability class accurately, in code that does not actually do that — the model pattern-matched a shape and narrated the consequence. The second is a finding that is technically correct and unreachable, because a check three layers up already prevents it. Both read as confident, specific and alarming.
There is also a cost people miss: a false positive you *fix* is worse than one you ignore. You changed working code, you spent the review, and you came away believing the system is safer than it was. Reproduce first. Always.
What This Will Never Catch
Runtime and infrastructure misconfiguration. The storage bucket with the wrong permissions, the security group open to the world, the admin panel still on a default credential — none of that is in the source.
Anything in code you did not provide, which includes every dependency you have.
Chained exploitation across services. The individually harmless information leak that turns a hard attack into an easy one lives in the gap between two systems, and you reviewed them separately.
Business-logic abuse an outsider spots. Pricing edge cases, refund flows, race conditions in a multi-step workflow — some of this is visible in code, and the most valuable examples are visible only to someone thinking about the business rather than the file.
Your build pipeline and secrets handling, unless you deliberately pointed it there, which almost nobody does.
That list is why the honest answer to "does this replace a penetration test?" is no, and why saying so is the argument rather than a disclaimer.
Getting This Right — Source-Code Confidentiality, Authorisation, and When to Bring in IT
Three things to settle before this becomes routine.
First, authorisation. Your own code and your own systems, and if any part of it belongs to a customer, permission in writing before you start. When you reach the point where the findings need independent validation — or where a client, insurer or auditor wants evidence rather than assurances — that is what penetration testing by certified testers provides, including open-box engagements where the testers get architecture detail and work the way this article does, only with accountability attached.
Second, confidentiality. Source code is usually a company's most sensitive artefact and this workflow sends it out of your environment. Read the data-handling and training terms for the specific product tier you use rather than assuming, since business and enterprise tiers commonly differ from consumer ones and terms change. Strip credentials from anything you paste — and if code containing a live secret has already gone into any external tool, rotate the secret rather than reasoning about whether it was retained.
Third, what happens to the findings. Reproduced defects belong where the rest of your work is tracked, with the reproduction steps attached; our piece on turning support tickets into structured bug reports covers that write-up problem directly. Our AI+ support practice helps set this kind of work up on company accounts with governed access rather than on a developer's personal login, and our managed IT support covers the credential rotation and access hygiene the exercise tends to expose. Brocent has run managed IT and security work across Asia since our founding in Beijing in 2007, with headquarters in Singapore and a Hong Kong office since 2016.
Frequently Asked Questions
Is it safe to send proprietary source code to an AI model?
That depends on the tier and the provider, and it is a decision to make deliberately rather than by default. Check the current data-handling and training terms for the exact product you use, prefer business or enterprise tiers where the terms are written for this, and treat any secret that has been pasted as compromised. For genuinely sensitive systems, scope what leaves your environment rather than pasting whole repositories.
How many of its findings are typically real?
Expect most of a first pass to be noise, and do not trust anyone quoting a universal figure — it depends heavily on your prompting, your codebase and how much context you supplied. What matters is measuring your own rate: track reproduced versus refuted for a few passes and you will quickly see whether your framing is working.
Does this replace a penetration test?
No. It reviews the code you show it and nothing else, it cannot chain findings across systems it has not seen, and its output is not evidence anyone will accept. It is a cheap way to find and fix the obvious things before you pay for the expensive step — which makes the expensive step better value.
Can we run this in CI?
It works far better as a gate on changed code than as a scan of the whole repository. Reviewing a diff against the security assumptions relevant to what changed is bounded and useful; running an unbounded adversarial pass on every build produces alert fatigue in about a week, which ends with people ignoring it entirely.
What do we do with a finding we cannot reproduce?
Keep it in a list with the reasoning, and revisit it if related code changes. Do not fix it, do not report it upward, and do not let it become a task — an unreproduced finding is a hypothesis, and treating hypotheses as defects is how teams lose confidence in the whole exercise.
Does the model need the whole codebase to be useful?
No, and giving it everything usually makes the output worse. What helps is the right slice — the boundary you are testing, its callers, the checks in between — plus the target model you wrote down. Precision beats volume here, which is also why one hypothesis per pass works better than a sweep.
Where to Start
Pick the one assumption whose failure would be worst: usually that a user cannot reach another organisation's data. Write it in a sentence, gather the handler and everything it calls on the way to the database, and ask for every path by which it could be false. Then reproduce whatever comes back before you tell anyone about it. One boundary done properly teaches you more about your own system than a whole-repository review will, and it gives you a repeatable shape for the next one. If you would rather have that work validated by certified testers, or the credential and access hygiene it uncovers handled properly, get in touch.
Share:
Ready to take action?
Turn these insights into a roadmap for your business.
Book a 15-minute no-obligation consultation with our APAC IT experts. We'll review your current setup and provide a tailored IT roadmap within 24 hours.
Free Checklist
10 Critical Checks Before Expanding IT to Greater China
PIPL compliance, network segmentation, bilingual helpdesk setup, and more — everything your IT team needs before Day 1 in China.
Request the checklist →📬 Monthly Asia IT Insights
China compliance updates, cybersecurity alerts, and IT tips for APAC teams — once a month.
No spam. Unsubscribe anytime.