Apply to my task
arXiv:2610.15729 ★ 81 Oct 11, 2026

Creed: Finding Code Vulnerabilities by Surfacing the Developer's Hidden Assumptions

Key result

A "find vulnerabilities" request makes the model guess from familiar patterns, so it misses semantic holes. The Creed method lets you find logic vulnerabilities in a single function: a forgotten check on who owns an order, a leak through the difference in responses to "wrong username" and "wrong password." The trick: don't hunt for the hole — write down what the author takes for granted and check whether it holds. The model works with the developer's assumptions and checks intent against the actual code. As a result, there are about 8 findings per confirmed vulnerability versus about 11 for competitors.

01

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.

02

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
03

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.

04

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.

05

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.

06

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.

07

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.

08

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.

09

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.

Research digest

Key result

A "find vulnerabilities" request makes the model guess from familiar patterns, so it misses semantic holes. The Creed method lets you find logic vulnerabilities in a single function: a forgotten check on who owns an order, a leak through the difference in responses to "wrong username" and "wrong password." The trick: don't hunt for the hole — write down what the author takes for granted and check whether it holds. The model works with the developer's assumptions and checks intent against the actual code. As a result, there are about 8 findings per confirmed vulnerability versus about 11 for competitors.

Principle

Everything happens in one prompt, as a chain: action → assumption → is it reasonable → when does it break → verdict. First the model describes what the code does. Then, for each action, it writes: "the author believes here that...". An assumption is read from the code's behavior. An identical error for two different cases means the author wanted to hide which one occurred. Next come two questions for each assumption. Is it reasonable by security standards? Under what conditions does it stop holding? The model no longer looks for a "SQL injection" pattern; it checks whether the author's intent is fulfilled. It's like checking an alibi. You don't ask "who's the culprit?" — you compare each witness's story with the facts.

Why it works

Given a generic request, the model produces a list of typical risks. A function's meaning isn't written directly in its text: what the author wanted to protect isn't visible from the code. But the model understands well what code does. It knows how authorization, authentication and payments are usually done. It easily phrases "the author is counting on X here." The method splits one hard task into two simple questions: "what is assumed?" and "does it hold?" A vulnerability appears in two cases. Either the assumption is bad in itself. Or it's good, but the code doesn't uphold it. Step 4 looks for violation conditions for all assumptions, even unreasonable ones, so the picture is complete. No illusions, though. The method fails to find the cause for roughly one in five known vulnerabilities. It was tested on 50 vulnerabilities, and the matches were also scored by a judge model. The paper doesn't break down the contribution of individual steps, so it's unknown which of the five matters most.

When to apply

Security review of code → the logic of a single function: authorization, authentication, payments, cancellations and refunds. Especially when scanners stay silent because the syntax is clean but the logic limps. Expect lots of "potential" findings. Protection may sit higher up the call chain, so you'll have to verify them by hand. NOT a fit for analyzing a whole project or chains across functions. Doesn't replace tests, scanners and review. It's the auditor's assistant, not the auditor.

Mini recipe

1. Take one whole function: untrimmed, with its checks and data access. 2. Set five steps in a row: actions → the author's assumptions → reasonable or unreasonable → violation conditions → list of vulnerabilities. 3. Explain what an assumption is: "a fact the developer considers true when performing an action." 4. Choose a reasonableness yardstick: OWASP, internal rules, PCI DSS, GDPR requirements for personal data. 5. Require a format: for each finding, the cause, how it manifests, exploitation conditions, reference to the assumptions. For automated parsing, ask for JSON or a table. 6. Remind it of the boundaries: the check is at the level of a single function, so have the model note what the calling code must guarantee. 7. Verify the findings yourself: some will be "potential." Add the calling code or an architecture description and the noise goes down.

Examples

[BAD]: `Find vulnerabilities in this order-cancellation function: [code]` [GOOD]: `Analyze the developer's assumptions in the order-cancellation function. Steps: (1) list the code's actions and overall goal; (2) for each action, infer assumptions of the form "the author believes that..."; (3) assess each assumption against security practice: Reasonable or Unreasonable, and why; (4) for EACH assumption, including unreasonable ones, name the violation conditions; (5) on that basis, name the potential vulnerabilities. An assumption is a fact the developer considers true. Finding format: name, cause, how it manifests, exploitation conditions, related assumptions. The check is at the level of a single function; note what the calling code must guarantee. Function: [code]` In the second case, the model will notice the assumption "belonging to the restaurant is enough to cancel." Then it will work out that this isn't the same as the right to cancel this particular payment. Along the way it will catch race conditions on repeated requests and the behavior when the order doesn't exist.

In plain words

Ordinary scanners and lazy prompts hunt for typos but are blind to architectural screwups. Ask a model a basic "find vulnerabilities" and it just spits out textbook boilerplate. The Creed method hits closer to the mark: it makes the model drag out the developer's implicit assumptions — the things the author took for granted but never wrote down. That's usually where critical logic holes hide.

It's like inspecting a bridge before handover. A standard audit checks that the piers are standing and the asphalt is smooth — technically, nothing to complain about. But the engineer was operating on a naive belief that heavy trucks would never drive across. Creed works like a relentless detective: it doesn't stare at the bricks, it goes straight to "what makes you think the world is perfect?" — and deliberately models the scenario where the fragile logic cracks.

All the magic is packed into one structured prompt with a strict algorithm of 5 sequential steps. The model first describes the function's behavior, then writes out the author's guesses, sanity-checks them and works out the conditions for failure. No fluff: what comes out is a concrete report on why the intern's code will fall over if a user hits cancel order at the exact second the bag is handed to the courier.

The example was food delivery, but the principle is completely universal. The approach saves the day anywhere there are complex rules: fintech transactions, smart contracts or distributed billing. Compilers and linters catch broken syntax but are powerless against failures of meaning. Analyzing the author's assumptions closes holes where classic static analysis is guaranteed to stay silent.

Bottom line: stop asking the model to "find bugs" — that's a waste of tokens and a guaranteed watery brush-off. Make it test not the lines of code but the limits of the programmer's thinking. A sequence of 5 deconstruction steps exposes logic failures before release, before they turn into a 3 a.m. call from the founder and a blown budget.

AI lab assistant

Apply this study to your task

Describe what you're working on. AI takes the method and the measured results from this paper and adapts them to your case, or writes a ready prompt built on them.

Based on Creed: Finding Code Vulnerabilities by Surfacing the Developer's Hidden Assumptions arXiv:2610.15729

Sign in to apply this study New accounts get 50 free credits.