TL;DR
Creed is a single prompt that makes the model analyze code in five steps. First it describes what the code does. Then it writes down what the developer takes for granted ("assumptions"). Next it checks whether each assumption is reasonable and looks for conditions under which it breaks. The broken assumptions are assembled into a vulnerability report.
A plain "find vulnerabilities" request makes the model guess from familiar patterns: SQL injection, null pointer. Semantic holes don't turn up that way. Think of a forgotten check on who owns an order, or a difference in response time between "wrong username" and "wrong password." The code looks tidy and there's nothing to find in it until you ask what the author was counting on. Without that question, the model either stays silent or hands out generic advice.
The method turns an audit into a chain of concrete questions inside one prompt: action → assumption → is it reasonable → when does it break → verdict. An assumption is read from the code's behavior. For example, an identical error for two cases means the author wanted to hide which of them occurred. The model now checks whether that intent is actually fulfilled instead of hunting for a pattern.
Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.
Method Blueprint
ONE PROMPT, five steps in a row:
STEP 1: Identify the code's actions (small operations + the function's overall goal) → list of actions
STEP 2: For each action, infer the developer's assumptions → list of "believes that…"
STEP 3: Sanity check: is the assumption reasonable by security standards? → Reasonable / Unreasonable + why
STEP 4: Violation conditions: when does the assumption stop holding? → concrete conditions
STEP 5: Verdict: an unreasonable assumption OR a reachable violation = a potential vulnerability → report:
cause, symptom, exploitation conditions, reference to the assumptions
Example
Task: You're a team lead at a food delivery service. An intern wrote an order-cancellation function, and before release you need to quickly check it for logic holes. Classic scanners won't say a word: syntactically, everything is clean.
Prompt:
Task: Analyze the assumptions the developer makes when performing the actions in the code. Assess how reasonable they are, determine the conditions under which they are violated, and based on that identify all potential vulnerabilities.
Reasoning Steps:
(1) Action Identification: Identify the operations the code performs — both the small ones (checks, data access) and the function's overall goal.
(2) Belief Inference: For each action, infer the assumptions the developer may have made.
(3) Sanity Analysis: Assess how reasonable these assumptions are in light of accepted security practice. For each one — "Reasonable" or "Unreasonable" and why.
(4) Violation-Condition Derivation: For EACH assumption (including unreasonable ones), determine the conditions under which it is violated.
(5) Potential Vulnerability Identification: Based on the assumption analysis, name all potential vulnerabilities.
Definitions:
- Belief: a fact the developer considers true when performing an action.
Function:
def cancel_order(request, order_id):
order = Order.objects.get(id=order_id)
if order.restaurant_id != request.session["restaurant_id"]:
return error("forbidden")
if order.status != "PENDING":
return error("cannot_cancel")
order.status = "CANCELLED"
order.save()
refund(order.payment_id, order.total)
return ok()
Output Format: For each finding: name, cause, how it manifests, under what conditions it can be exploited, which assumptions it relies on. List the assumptions separately, each marked "Reasonable/Unreasonable". Remember: the check is at the level of a single function, so note what the calling code must guarantee.
Result: The model produces a structured analysis. First, a list of actions (look up the order, check the restaurant, check the status, cancel, refund). Then a list of assumptions, each with a "Reasonable/Unreasonable" verdict and an explanation. Then the violation conditions for each assumption. Finally, a report of findings, each with a cause, exploitation conditions and a reference to the assumptions. Expect the model to flag the assumption "belonging to the restaurant is enough to cancel" and discuss how that's not the same as the right to cancel this particular payment. It will also cover race conditions on repeated requests and the behavior when the order doesn't exist. You'll have to verify the findings yourself: some will be "potential," depending on the calling context.
Why It Works
The model's weakness. Asked to "find vulnerabilities," the model follows familiar patterns and produces a generic list of risks. Semantic holes require knowing why the code was written and what the author meant to protect with it. That isn't stated directly in the function's text.
Strength. The model understands well what code does and what accepted practice looks like in the domain: authorization, authentication, payments. It easily phrases "the author is counting on X here" and says whether that's reasonable.
How the method exploits this. It splits the task into two simple questions: "what is assumed here?" and "does that assumption hold?" A vulnerability arises in two cases: the assumption itself is bad (then any code built on it is vulnerable) or the assumption is good, but the implementation doesn't uphold it (as with the response-time difference). Step 4 runs for all assumptions, even unreasonable ones, so the picture is complete.
Control knobs:
- Definitions (Definitions) → add your own terms and "reasonableness" criteria: the OWASP standard, internal rules, GDPR requirements for personal data.
- Step 3 → replace "security standards" with a different yardstick: business rules, spec requirements, PCI DSS.
- Output Format → ask for JSON for automated parsing, or an "action — assumption — verdict — condition" table.
- Context → add the calling code or an architecture description to eliminate some of the "potential" findings.
Prompt Template
Task: Analyze the assumptions the developer makes when performing the actions in the code. Assess how reasonable they are, determine the conditions under which they are violated, and based on that identify all potential vulnerabilities.
Reasoning Steps:
(1) Action Identification: Identify the operations the code performs — both the small ones and the function's overall goal.
(2) Belief Inference: For each action, infer the assumptions the developer may have made.
(3) Sanity Analysis: Assess how reasonable these assumptions are relative to {yardstick: security standards / OWASP / internal rules}.
(4) Violation-Condition Derivation: For each assumption, determine the conditions under which it is violated.
(5) Potential Vulnerability Identification: Based on the assumption analysis, name all potential vulnerabilities.
Definitions:
- Belief: a fact the developer considers true when performing an action.
- {additional definitions for your domain}
Function:
{function_code}
Output Format: {output_format}
Fill in:
- {function_code} — one whole function, untrimmed;
- {yardstick} — which standard to judge the assumptions' reasonableness by;
- {output_format} — for example, "a list of findings: cause, exploitation conditions, related assumptions."
The paper shows a shortened version of the prompt. The full text and output schema are in the authors' artifact, and the definitions of "action," "reasonableness" and "violation" are omitted there. The step structure in the template is the original.
🚀 Quick start — paste into the chat:
Here is the Creed template (code auditing through the developer's assumptions). Adapt it to my task: [your task — what code, which language, which domain].
Ask me questions to fill in the fields.
[paste the template above]
The LLM will ask about the function's language and domain, the "reasonableness" yardstick (which standards or internal rules count as the norm) and the report format. It needs this so step 3 judges the assumptions by your rules rather than generic ones. The model will take the five-step structure from the template.
Limitations
⚠️ Single-function scope: The method looks only at the function, without the calling code. Many findings come out as "potential": protection may sit higher up the call chain. A human still has to verify them.
⚠️ Noise in the reports: To confirm one real vulnerability, you need to review about eight findings on average. That's better than competitors (about eleven), but manual verification remains mandatory.
⚠️ It doesn't find everything: The method didn't explain the cause for all known vulnerabilities: it missed roughly one in five. It's an auditor's assistant, not a replacement for tests, scanners and review.
⚠️ Small evaluation: The benchmark is 50 vulnerabilities. The result is convincing for comparing approaches, but it's no guarantee for your code. The available text has no full data on the contribution of individual steps, so you can't tell which step matters most.
⚠️ Automated scoring: Whether findings matched the real cause was judged by an LLM judge. The authors manually rechecked every counted match, but "extra" findings were checked only selectively.
How They Tested It
The researchers collected fresh vulnerabilities (CVEs) from September 2025 to March 2026. This was deliberate: the model couldn't have seen them during training. From 2,751 records they picked functions where the fix clearly concerns a single function. Then they manually verified that the function actually contains the cause of the flaw. Of 60 functions reviewed, 10 were discarded, leaving 50 functions in 10 languages. 40 of them are semantic vulnerabilities rather than classic memory errors.
The creative part was how to evaluate. A "vulnerable or not" verdict for an isolated function makes no sense: a lot depends on the calling code. So the authors introduced two metrics. Recall — the share of vulnerabilities for which at least one finding matched the real cause and conditions (based on the CVE description, the commit message and the patch). Overhead — how many findings you have to review to confirm one real one. Matches were decided by an LLM judge from a different model family so it wouldn't favor "its own." The authors rechecked all counted matches by hand. One more check: the method was also run on the fixed version of the function. A good result is when a finding appears on the vulnerable version and not on the fixed one.
Creed was compared with four approaches, including RepoAudit (classic static analysis with an LLM) and PrimeVul-CoTexp (a plain chain of thought: "you are a code analysis expert, find the vulnerabilities"). Creed achieved a recall of 0.78: 39 of 50 vulnerabilities were correctly explained. That's 10 percentage points above the strongest competitor, and overhead dropped from 11.3 to 7.9 findings. The method covered 15 of the 21 vulnerabilities that no static analysis pattern can describe. For practice: a prompt built around the author's assumptions beats a generic "find bugs," because it steers the model's attention to what the code means.
Adaptations and Extrapolations
🔧 Technique: swap "security" for "business rules" → catch logic bugs, not just vulnerabilities
Change step 3 and the definitions:
(3) Sanity Analysis: Assess whether each assumption complies with the business rules: {rules: e.g., "a discount cannot be combined with reward points", "refunds go only to the original payment card", "an order cannot be changed after it's handed to the courier"}.
...
Definitions:
- Belief: a fact the developer considers true...
- Violation: a situation where the code's actual behavior diverges from the rules above.
This carries the principle beyond security: the authors' method itself was tested only on vulnerabilities. The authors didn't measure the effect on business-logic bugs, so test it on your own code.
🔧 Extrapolation: bake it into an agent's code-review instructions
If you work with Claude Code or Cursor, put the five steps into an instructions file or a "security review" skill:
When reviewing a changed function, always:
1. Identify the function's actions (small ones and the overall goal).
2. Infer the developer's assumptions for each action.
3. Assess the reasonableness of each assumption by security standards.
4. For each assumption, write down the violation conditions.
5. Produce a list of potential vulnerabilities with references to the assumptions.
Don't conclude "safe" without step 4. If protection might live in the calling code, state exactly what the calling code must guarantee.
The paper tested only a single request; moving this into an agent's instructions is my extrapolation.
Resources
- Paper title: LLM-based Code Auditing by Inferring and Evaluating Developer Assumptions
- Authors: Junming Liu (MPI-SP, Germany), Marcel Böhme (CISPA, Germany)
- Works and data mentioned: the CVEfixes database (source of vulnerabilities), RepoAudit and PrimeVul (approaches compared), work [27] on why binary vulnerability verdicts for a single function are flawed. The full prompt text and output schema are published in the authors' artifact.