As a result of this research, we launched greprules.io. Check out the post below.
Launching greprules.io and greprules Plugin: Free SAST Rules for the AI Coding Era
CVE to SAST rule generation is the process of turning real vulnerability evidence into static analysis rules that can detect similar code patterns. At Provally, we built a pipeline that starts with public CVEs, traces them to open-source repositories and security patches, and generates OpenGrep-compatible SAST rules with validation evidence.
This post explains how the pipeline works, what we learned while building it, and why patch attribution, root-cause analysis, and real-commit validation are essential for generating useful SAST rules.
TL;DR
Public CVE data can be a strong source for SAST rule generation, but only when it is connected to real code evidence. Our pipeline does not simply send a CVE description to an AI model and ask for a rule. It discovers the affected repository, verifies the security patch, analyzes the vulnerable and fixed code, extracts the root cause, generates an OpenGrep-compatible rule, and validates that rule against both the vulnerable and patched commits.
CVE
↓
Advisory and vulnerability references
↓
Repository and patch attribution
↓
Vulnerable commit and fixed commit
↓
Root-cause analysis
↓
OpenGrep-compatible SAST rule
↓
Validation against real commits
↓
Rule evidence package
Key Takeaways
- CVE descriptions are useful context, but they are rarely enough to generate precise SAST rules.
- The most valuable evidence usually comes from the patch that fixed the vulnerability.
- Patch attribution must be verified against git history and code-level evidence.
- Root-cause analysis must identify the vulnerability mechanism, not just the visible shape of the patch.
- Generated SAST rules should be validated against the real vulnerable and fixed revisions.
- Rule metadata should preserve CVE ID, CWE, repository, patch reference, vulnerable snippet, fixed snippet, and validation result.
Table of Contents
- Why We Built a CVE-to-SAST Rule Generation Pipeline
- Why CVE Data Alone Is Not Enough
- The Pipeline: From Public CVE to OpenGrep Rule
- What We Had to Solve While Building It
- How We Validate Generated SAST Rules
- How This Connects to AutoProof
- What Comes Next
- FAQ
Why We Built a CVE-to-SAST Rule Generation Pipeline
Static Application Security Testing, or SAST, depends heavily on rule quality and rule coverage. A scanner can be fast, easy to run, and well integrated into CI, but if its rules do not cover the vulnerability patterns that appear in real projects, it will miss important issues before deeper analysis can begin.
This matters for our work on AutoProof.
AutoProof analyzes SAST findings with AI agents, project structure, Code Property Graphs, vulnerability context, proof-of-concept behavior, and runtime evidence. The goal is to help security engineers distinguish false positives from real threats and help developers understand which issues deserve priority.
But AutoProof starts from candidate findings. If the SAST engine does not detect a relevant issue, AutoProof has nothing to verify.
That created a practical question for us:
How can we expand SAST rule coverage in a grounded, evidence-based way?
Our answer was to build a pipeline that turns public vulnerability information into OpenGrep-compatible rules. Public vulnerability sources such as CVE, NVD, and CWE provide useful starting points, but the pipeline must go beyond metadata and connect each vulnerability to real source code evidence.
Why CVE Data Alone Is Not Enough
A public CVE often contains an identifier, a summary, severity information, references, and sometimes a CWE category. That information is useful, but a strong SAST rule needs more than a description.
A useful SAST rule needs to understand code shape.
It needs to know what vulnerable behavior looks like, what safe behavior looks like, and which static pattern can reasonably distinguish between the two. CVE text alone rarely gives that level of detail.
For open-source projects, the most valuable evidence is often the security patch.
The patch shows what maintainers changed to fix the vulnerability. It may show that validation was added, unsafe input handling was constrained, a dangerous API was removed, a sanitizer was introduced, or a security-sensitive condition was enforced.
That patch becomes the bridge between vulnerability intelligence and static analysis.
Public CVE
↓
Advisory and references
↓
Open-source repository
↓
Patch commit or pull request
↓
Vulnerable code and fixed code
↓
Root-cause pattern
↓
OpenGrep-compatible SAST rule
The goal is not to ask an AI model to invent a rule from a vulnerability summary. The goal is to ground SAST rule generation in the actual code change that fixed a real vulnerability.
The Pipeline: From Public CVE to OpenGrep Rule
Our CVE-to-SAST rule generation pipeline is organized around one principle: every generated rule should have traceable evidence.
At a high level, the pipeline has seven stages.
1. Select candidate CVEs
2. Collect vulnerability context
3. Discover and verify repository and patch evidence
4. Analyze vulnerable and fixed code
5. Build a structured rule-generation context
6. Generate an OpenGrep-compatible SAST rule
7. Validate the rule and package evidence
Each stage reduces uncertainty before a rule is produced. Instead of treating the generated rule as the output of a single prompt, we treat it as the final artifact of a multi-step analysis process.
1. Selecting Candidate CVEs
The first step is deciding which CVEs are likely to produce useful SAST rules.
A good candidate usually has several properties:
- It affects an open-source project.
- The vulnerable code is available.
- The fix is available as a commit, pull request, release diff, or patch file.
- The vulnerability has a source-level pattern that static analysis can reasonably detect.
- The issue maps to a recognizable weakness class such as injection, path traversal, unsafe deserialization, insecure file handling, missing authorization checks, or unsafe API usage.
A poor candidate may have none of these properties. A vulnerability caused only by deployment configuration may not produce a useful source-level rule. A dependency version CVE may be better handled by SCA than SAST. A vulnerability that depends entirely on runtime state may require dynamic testing or proof-of-concept validation rather than static pattern matching.
This filtering step matters because the objective is not to generate as many rules as possible. The objective is to generate SAST rules that are useful, explainable, and testable.
2. Collecting Vulnerability Context
For each candidate CVE, the pipeline collects context from public vulnerability data and project references.
The context package may include:
cve_id: CVE identifier
summary: vulnerability description
cwe: weakness category
severity: severity information when available
affected_project: project or package name
affected_versions: vulnerable versions when available
fixed_versions: patched versions when available
references:
- advisories
- repository links
- pull requests
- commits
- changelogs
- release notes
This context helps determine whether the CVE is suitable for SAST rule generation. It also provides semantic guidance for later stages. A path traversal rule, a command injection rule, and an unsafe deserialization rule should not be generated with the same pattern strategy.
3. Discovering and Verifying the Repository Patch
Patch discovery is one of the most important parts of the pipeline.
A CVE may link to multiple references, and not all of them point directly to the security fix. Some references point to advisories. Some point to release notes. Some point to issues. Some point to pull requests. Some point to nearby commits that are related to the release but not to the actual vulnerability.
The pipeline therefore treats patch discovery as an attribution problem.
CVE references
↓
Repository candidates
↓
Patch candidates
↓
Git-history verification
↓
Security-relevant diff evidence
The output of this stage is not just a URL. It is an evidence-backed mapping between a vulnerability and the code change that likely fixed it.
4. Analyzing Vulnerable and Fixed Code
Once a patch candidate is verified, the pipeline analyzes the difference between the vulnerable and fixed code.
It looks for signals such as:
- Removed vulnerable code
- Added validation logic
- Added sanitization
- New boundary checks
- Replaced unsafe APIs
- Changed authorization logic
- Modified data flow into sensitive sinks
- Tests added to reproduce or prevent the issue
The central question is:
What condition made the vulnerable code unsafe, and how did the patch neutralize that condition?
This question prevents the pipeline from generating rules that simply recognize the patch. The generated rule should detect the vulnerability pattern, not the remediation pattern.
5. Building the Rule-Generation Context
Before rule generation, the pipeline builds a structured context package that describes the vulnerability, the patch, and the intended rule behavior.
A simplified context package may look like this:
cve_id: CVE identifier
cwe: weakness category
language: target language
repository: affected repository
vulnerable_commit: revision before the fix
fixed_commit: revision containing the fix
affected_files: files changed by the security patch
vulnerable_snippets: code patterns removed or modified by the patch
fixed_snippets: validation, sanitization, or safe usage added by the patch
root_cause: why the vulnerable code was unsafe
rule_goal: what the SAST rule should detect
negative_conditions: what safe or patched code should avoid matching
This context turns rule generation into a translation task: from vulnerability evidence to static analysis semantics.
6. Generating an OpenGrep-Compatible SAST Rule
With the structured context in place, AI agents assist in generating an OpenGrep-compatible rule.
The model is not asked to write a rule from scratch. It receives evidence from the CVE, the repository, the patch, vulnerable snippets, fixed snippets, and root-cause analysis. Its task is to propose a rule that is precise enough to detect the vulnerable pattern and constrained enough to avoid obvious false positives.
A simplified reasoning flow looks like this:
Patch evidence:
User-controlled input was passed into a filesystem operation.
Security interpretation:
The vulnerable code may allow path traversal when input is not normalized and constrained.
Rule objective:
Detect filesystem access using user-controlled path input without normalization or boundary checks.
Negative conditions:
Avoid matching code that performs canonicalization, normalization, or explicit base-directory enforcement.
The output is a candidate SAST rule, not a final rule. The candidate still needs validation.
What We Had to Solve While Building It
Building this pipeline was not just a matter of connecting CVE data to an LLM and asking for a rule. The hardest parts were about preventing the system from being confidently wrong.
A generated SAST rule is only useful if the evidence behind it is correct. That forced us to solve engineering problems around patch attribution, validation, and rule precision before we could treat any generated rule as usable.
Patch Attribution Had to Be Evidence-Driven
One of the first problems we ran into was patch attribution.
Public CVE references are noisy. A CVE may point to an advisory, a pull request, a release note, a branch, a changelog, or a nearby commit that is not actually the security fix. In some cases, the most obvious repository link is not even the affected project. In others, a pull request contains multiple commits, and the final PR head is not the commit that introduced the security-relevant change.
If the pipeline selects the wrong patch, everything downstream becomes unreliable. The root-cause analysis explains the wrong code, the SAST rule captures the wrong pattern, and validation may still appear to pass against irrelevant evidence.
To address this, we stopped treating patch discovery as a single best-effort lookup.
Instead, the pipeline collects multiple unverified patch seeds from research results, advisory references, pull requests, commits, and local git history. Those candidates are verified against repository evidence and ranked using code-level signals. Weak fallback results are blocked before root-cause analysis and SAST generation can proceed.
Research and advisory references
↓
Unverified patch seeds
↓
Repository and git-history verification
↓
Code-level evidence ranking
↓
Patch attribution gate
↓
Root-cause analysis and rule generation
This made patch attribution a gate, not just a hint. Research can suggest candidates, but git evidence must verify them.
Root-Cause Analysis Had to Come Before Rule Generation
Finding the patch commit was only half of the problem.
Even when the pipeline identified the correct patch, the generated rule could still be wrong if the root-cause analysis was too shallow. The model would sometimes focus on the code that changed in the patch rather than the vulnerability mechanism that made the old code unsafe.
That distinction matters.
A patch often contains more than the minimal security fix. It may include refactoring, helper extraction, tests, renamed functions, added wrappers, or defensive code around the vulnerable path. If the analysis does not clearly separate the actual root cause from surrounding patch-related changes, the generated SAST rule can end up detecting the patch shape instead of the vulnerability.
In other words, the rule may become a pattern for “code related to this fix” rather than “code that exhibits this class of vulnerable behavior.”
We saw that this could produce rules that were technically valid but semantically misaligned. They matched code near the patch, a project-specific helper, or a surface-level API change, while missing the deeper issue: unsafe input flow, missing validation, missing boundary enforcement, improper authorization logic, or another root-cause pattern.
To address this, we made root-cause analysis an explicit prerequisite for rule generation.
The pipeline first asks the model to explain why the vulnerable code was unsafe, what condition made exploitation possible, and which part of the patch actually neutralized that condition. Only after that does it generate an OpenGrep rule.
The patched code is still important, but it is not treated as the rule objective. Instead, it is used to define negative conditions: what safe code looks like, and what the rule should avoid matching.
The goal is not to generate a rule that recognizes the patch. The goal is to generate a rule that recognizes the vulnerability.
Validation Had to Run Against Real Commits
Early validation approaches often use extracted snippets or synthetic fixtures. That is convenient, but it can create false confidence.
A rule may match a small vulnerable snippet while failing on the actual vulnerable repository state. It may also ignore surrounding control flow, framework conventions, imports, configuration, or patched safe behavior that only appear in the real project tree.
For CVE-derived SAST rules, that was not good enough.
We changed validation to use the actual vulnerable and fixed revisions whenever possible. The pipeline materializes the vulnerable commit and the patched commit, runs the generated OpenGrep rule against both, and stores the validation evidence with the rule candidate.
A rule is not considered ready just because it is syntactically valid. It must detect the vulnerable revision and avoid detecting the fixed revision.
Generated rule
↓
OpenGrep syntax/schema validation
↓
Scan vulnerable commit
↓
Scan fixed commit
↓
Compare findings
↓
Store validation evidence
That check turned validation from “does this rule run?” into “does this rule distinguish vulnerable code from patched code?”
How We Validate Generated SAST Rules
Generated rules are treated as hypotheses until they are tested.
A strong CVE-derived SAST rule should satisfy a simple expectation:
Vulnerable revision → finding exists
Fixed revision → finding disappears
This validation step helps catch several common failure modes:
- The rule is syntactically invalid.
- The rule is too narrow and misses the vulnerable code.
- The rule is too broad and still matches the fixed code.
- The rule detects a refactor rather than the vulnerability.
- The rule depends too heavily on project-specific names.
- The rule produces unrelated findings.
For AutoProof, this validation loop is especially important. AutoProof is designed to reason about whether findings are real and provide evidence for confirmed risk. Feeding it low-quality rules would only shift the burden downstream.
That is why the CVE-to-SAST pipeline produces not only rules, but also validation artifacts.
Evidence Packaging: Why Rule Metadata Matters
Every generated rule should preserve its origin story.
For each rule, we store metadata such as:
rule_id:
cve_id:
cwe:
repository:
affected_project:
vulnerable_commit:
fixed_commit:
patch_reference:
language:
severity:
vulnerable_snippet:
fixed_snippet:
root_cause:
validation_result:
generated_at:
This metadata helps security engineers and developers understand why the rule exists.
It also makes the rule more useful inside AutoProof. When a finding is produced by one of these rules, AutoProof can use the attached evidence to explain:
- Which CVE inspired the rule
- What vulnerable code pattern it was designed to detect
- What patch fixed the original vulnerability
- Whether the rule was validated against vulnerable and fixed revisions
- Why the finding may deserve attention
Security tools should not only say, “This looks dangerous.” They should explain, “This resembles a real vulnerability that was fixed here, and this is the evidence.”
How This Connects to AutoProof
This CVE-to-SAST rule generation pipeline is upstream of AutoProof.
The relationship is straightforward:
CVE-derived SAST rules
↓
OpenGrep scan results
↓
AutoProof verification
↓
False-positive filtering and evidence generation
More SAST rules can increase detection coverage, but more findings can also create more noise. AutoProof is designed to handle that second part: verifying findings, filtering false positives, and presenting evidence for confirmed threats.
Together, rule generation and AutoProof create a more complete workflow:
- CVE-derived rules expand the set of candidate findings.
- OpenGrep runs the rules against real codebases.
- AutoProof verifies which findings are likely real.
- Security engineers can focus on validated risk.
- Developers can prioritize fixes with clearer evidence.
What Comes Next
We are preparing a free community hub where security engineers and developers can download and use SAST rules. The goal is to make practical detection content easier to access, inspect, evaluate, and reuse.
In parallel, we are developing plugins that allow AI coding tools such as Claude Code and Codex to use these rules directly during development and security review. This would make SAST rules more useful not only in CI pipelines, but also inside the coding workflows where developers already work.
The long-term goal is to connect rule generation, rule sharing, AI-assisted development, and vulnerability validation into a practical workflow for application security teams.
Conclusion
CVE-to-SAST rule generation is powerful, but only when it is grounded in evidence.
The most important lesson we learned is that AI should not be used to guess what a SAST rule should look like from a vulnerability summary alone. It should be used to reason over structured evidence: CVE metadata, repository history, patch diffs, vulnerable snippets, fixed snippets, root-cause analysis, and validation results.
That evidence-driven approach helps prevent generated rules from being confidently wrong.
For Provally, this work supports a broader mission: helping security teams find real vulnerabilities, reduce false positives, and give developers clear evidence for what to fix first.
FAQ
What is CVE-to-SAST rule generation?
CVE-to-SAST rule generation is the process of turning public vulnerability information into static analysis rules. In our pipeline, a CVE is traced to an open-source repository, a security patch, vulnerable code, fixed code, and root-cause evidence before an OpenGrep-compatible SAST rule is generated.
Why is a CVE description not enough to generate a SAST rule?
A CVE description usually explains the vulnerability at a high level, but a SAST rule needs code-level detail. It must know what vulnerable behavior looks like, what safe behavior looks like, and which static pattern can distinguish between the two.
Why does patch attribution matter for SAST rule generation?
Patch attribution matters because the rule is only as reliable as the evidence behind it. If the pipeline selects the wrong patch, the generated rule may detect unrelated code, miss the real vulnerability, or produce misleading validation results.
Why validate a SAST rule against vulnerable and fixed commits?
Validating against real commits tests whether the rule distinguishes vulnerable code from patched code. A good rule should detect the vulnerable revision and avoid detecting the fixed revision whenever the patch fully removes the vulnerable pattern.
How does this pipeline reduce SAST false positives?
The pipeline reduces noise by grounding each rule in real vulnerability evidence and validating it before use. AutoProof then adds another verification layer by analyzing SAST findings with project context, code structure, proof-of-concept behavior, and runtime evidence.
Will these generated SAST rules be available to download?
We are preparing a free community hub where security engineers and developers can download and use SAST rules. We are also developing plugins so AI coding tools such as Claude Code and Codex can use these rules directly during development and security review.