Handle a flood of AI-generated vulnerability reports by making every report prove itself before a human spends real time on it: require a working reproducer against a supported version, check whether the code ships and is reachable in your builds, and move low severity issues into a public workflow. Then spend the saved hours turning valid reports into tested fixes.
That is the short answer. The long answer matters because the problem changed shape in 2026. Two years ago the pain was hallucinated reports that took an hour to refute. Today many AI-assisted reports are real, and the pain is volume: dozens of correct but minor findings that each need triage, a fix, an advisory and sometimes a CVE. This guide is for PSIRT leads, open source maintainers and product security teams running a vulnerability disclosure program (VDP) or a bug bounty. It covers how volume and quality changed, a triage gate that takes minutes, when to go public, policy wording, scoring against shipped versions, the EU Cyber Resilience Act (CRA), and the path from valid report to merged fix.
Key takeaways
- The flood has two parts. Unverified "slop" that describes bugs that do not exist, and real findings that are mostly low severity. You need different handling for each, and a single gate that sorts them quickly.
- No reproducer, no triage. Projects as different as Django, the Linux kernel and GeoServer now say on their own policy pages that a report without a working, verified reproduction will be closed or treated as doubtful.
- Score against what you ship, not what exists in the repository. Version range, build configuration and reachability decide whether a report affects customers. Write the answer down as a VEX statement so you only answer it once.
- Low severity can go public. curl moves LOW and MEDIUM reports to public GitHub issues from 26 October 2026 and keeps only HIGH and CRITICAL private. Public handling spreads the review load and gets fixes out sooner.
- A report flood does not trigger CRA reporting by itself. Under the CRA, manufacturers report actively exploited vulnerabilities and severe incidents, with a 24 hour early warning. A report that includes evidence of exploitation in the wild starts that clock, so your gate must spot it.
- Spend the saved time on fixes. Make the reproducer a regression test, fix, run the suite, ship. Automate the dependency upgrades so humans work on the code only you can fix.
How has report volume and quality changed in 2026?
The best public record of this shift comes from curl, because its lead maintainer writes about it in detail and the project publishes every advisory. Other projects tell the same story in their policy pages.
From slop to real but minor
In July 2025, Daniel Stenberg wrote that about 20 percent of curl's security submissions that year were AI slop, and only about 5 percent were genuine vulnerabilities. curl's security team had seven members, and each report pulled in three or four of them for 30 minutes to an hour or more. Some of those people had about three hours a week for curl in total. His summary of the goal was blunt: "We need to reduce the amount of sand in the machine."
In January 2026, curl ended its bug bounty, effective 31 January. Stenberg's post says the program had confirmed 87 vulnerabilities and paid more than 100,000 USD since 2019, and that the confirmed share of submissions fell from more than 15 percent in earlier years to under 5 percent from 2025. He named AI-generated reports and money as drivers of the volume.
By October 2026 the picture had changed again. curl's security page lists 24 advisories published on 14 October 2026 alongside the 8.23.0 release. By our count of that page on 22 October, 23 of them are rated Low and one, an HTTP/2 upload use-after-free, is rated High. Cyberpress reports that an AI-assisted audit by an outside security research firm produced 18 of the fixes in 8.23.0, with human researchers reviewing submissions and curl deciding impact and CVE eligibility itself. These are not hallucinations. They are correct findings in unusual option combinations, protocol mixes and connection reuse edge cases.
That is the new shape of the flood. Stenberg's 20 October post says that over the last few years more than 90 percent of all submissions could quickly be judged as less than HIGH, and that volume shows no sign of slowing in the coming months.
Other projects saw the same thing
Seth Larson, who triages security reports for CPython, pip, urllib3, Requests and other projects, wrote in December 2024 about a rise in low quality, spammy and LLM hallucinated reports. His example: a report that flagged urllib3 for using SSLv2, which the project explicitly disables. The reports look plausible at first, so they take time to refute.
Django's security policy now has its own section for AI-assisted reports. It says the security team "has received a growing number of security reports generated partially or entirely" with LLMs, and it sets rules: disclose the tools, verify the bug, and do not include fabricated code.
The Linux kernel's security bug documentation goes further. It tells reporters who used AI assistance to find a bug that they "must treat it as public", asks for a tested reproducer and a tested fix, and warns that a report without a version range will not be processed.
Findings are cheap, fixes are not
The argument under all of this showed up on Hacker News in October, in the 176 comment thread on OpenAI's "Patch the Planet" announcement. Commenters made three points that any PSIRT will recognise. Getting a fix into use can mean backporting it to old releases that still run in production. Discovery now outpaces remediation. And the hard part is often downstream coordination: getting many dependents to upgrade once a fix exists. Some maintainers in the thread argued that AI programs hand out findings while the maintainers carry the cost of fixes. Others disputed who actually found a given bug. Whatever your view, the lesson for a vendor is plain: your bottleneck has moved from finding bugs to processing and fixing them.
| 2024 to early 2025 | 2026 | |
|---|---|---|
| Typical bad report | Hallucinated function, invented CVE, scanner dump | Real bug in a rare configuration, often low severity |
| Main cost | Time to refute a plausible fake | Time to triage, fix, write advisories and backport many valid lows |
| Main control | Close fast, ask for proof | Proof gate, plus a cheaper workflow for low severity, plus faster fixing |
| Where the bounty fits | Money drove volume | Several projects removed or reshaped rewards |
How do you triage fast?
The aim is a gate that a single person can run in ten minutes, which sorts every incoming report into one of four buckets: close, public low, private high, or needs more information. Everything else follows from the bucket.
Step one: is it real? Reproduction required
Make the reporter do the first hour of work, not you. Every policy that has adapted to AI reports converges on the same requirement.
- Django asks for a minimal, working proof of concept, as code or reproduction steps, plus the Django and Python versions tested, and says reports that appear to be unverified AI output will be closed without response.
- GeoServer requires a working reproduction, as code, a request or a config, against a supported series, and says reports that turn out to be hallucinated or unverifiable will be closed without further engagement.
- The Linux kernel says the AI tool should provide a reproducer and the reporter should test it thoroughly; if it does not work, the report's validity is seriously questioned. It also refuses binary only reproducers.
A reproducer is the cheapest filter you have, because hallucinated bugs cannot produce one. Run it yourself in a disposable environment, against the exact version the reporter names and then against your latest release. If it does not reproduce in either, ask once for the missing detail and close if the reply adds nothing. Larson's advice for maintainers is the same: respond briefly, ask for justification, and close if nothing substantive comes back.
Step two: does it affect a version you support?
Many AI-assisted reports target old code, development branches or configurations nobody ships. curl's policy closes LOW and MEDIUM reports against releases older than three years without action. The kernel requires a version range or a commit ID. Django asks for proofs of concept on supported dependency versions only.
Answer three questions quickly:
- Which commit introduced the code, and which of your supported releases contain it?
- Is the affected feature compiled in, enabled by default, or behind an option?
- Does the reproducer use realistic inputs? Django's policy, for example, sets size limits for proofs of concept and says the code must reflect realistic production use.
Step three: is it reachable in what customers run?
This is where vendors differ from library maintainers. A library maintainer asks "is the bug real in my code". A vendor that ships a product built from many components asks "can this code path run in the product customers have installed".
Reachability has layers. The vulnerable file may not be in the build at all. It may be in the build but not compiled with the affected option. It may be compiled in but never called from your code. It may be called, but only with inputs an attacker cannot control. Each layer lets you close the report, or downgrade it, with a written reason. The CISA minimum requirements for VEX turn those layers into standard justifications, covered in the scoring section below.
Step four: route by severity
Use your published severity scale, not the reporter's. curl explicitly does not use CVSS and grades on four levels; Django's policy asks reporters not to include CVSS scores at all, because the security team makes that call. Once you have a severity, the bucket is mechanical.
| Gate result | Bucket | What happens next |
|---|---|---|
| No working reproducer after one request | Close | Close with a short reason. Note the reporter if your policy allows bans for repeat offenders |
| Reproduces only on unsupported or very old releases | Close | Close with the supported version list. Optionally fix in main |
| Reproduces, Low or Medium, no evidence of exploitation | Public low | Move to the public tracker, fix in the open, credit the reporter |
| Reproduces, High or Critical | Private high | Private advisory, embargoed fix, coordinated release |
| Report mentions exploitation in the wild | Private high, plus the regulatory clock | Escalate now. See the CRA section |
| Plausible but missing key facts | Needs info | One templated request for version, config and reproducer |
Should low-severity issues be handled in public?
For many projects, yes. curl's decision is the clearest current example. From 26 October 2026, reports assessed as LOW or MEDIUM must be submitted as issues in curl's public GitHub repository. Only HIGH and CRITICAL stay private in the project's HackerOne tracker, and LOW or MEDIUM reports already filed there will be asked to move to GitHub, then closed as informative and disclosed. Stenberg calls it "our next step in a survival strategy."
His reasons are worth reading because they apply to most teams:
- More people can help assess reports, write advisories and check that fixes are complete.
- AI-equipped researchers already examine fixes right after CVEs are announced, so public review can catch gaps before the release rather than after.
- Distributions and other users may get fixes earlier.
- The project can decline reports about unrealistic option combinations more firmly, in public, where the reasoning is visible.
He also names the costs. Public handling gives attackers a slightly longer window before users can patch, which is why the line sits below HIGH. Someone might post a HIGH issue publicly by mistake, though he notes reporters understating severity is almost unheard of. And low issues still need care, because the CVE appeals process means someone else could assign a CVE to a real flaw you dismissed.
The Linux kernel reaches a similar place by a different route: it treats AI-found bugs as already public, because if one person's tool found it, another person's tool can.
When public handling is the wrong call
Public low severity handling suits open source projects and vendors whose customers patch quickly. Think twice when:
- Your customers run long support releases and upgrade slowly, so a public low may sit unpatched for months.
- Severity depends heavily on deployment, and a low in your lab could be higher for a customer with an unusual configuration.
- You are a hosted service, where the fix is yours to deploy and there is no benefit in publishing first.
- Several low findings chain together. Review clusters of related lows in the same component before you publish any of them.
| Question | Handle in public | Keep private |
|---|---|---|
| Severity on your published scale | Low or Medium | High or Critical |
| Evidence of exploitation | None | Any |
| Can users patch quickly? | Yes, frequent releases | No, long support branches |
| Could lows chain to something worse? | No | Yes, or not yet checked |
| Product type | Open source library or tool | Hosted service, or appliance with slow updates |
How do you write a VDP policy for AI-assisted reports?
Your policy is the cheapest triage tool you own, because it shapes reports before they arrive. The CISA VDP template, written for US federal agencies but widely copied, already contains the basics: a scope list, a safe harbor statement, a request for reproduction steps, a request not to submit high volumes of low quality reports, and a commitment to acknowledge receipt within three business days. Add an AI section on top. The projects above show what works.
What the AI section should say
- Disclosure. Ask reporters to say which AI tools they used and for what: finding the bug, writing the description, or writing the proof of concept. Django requires this.
- Verification. A human must have run the reproducer against a supported version before submitting. State that unverified output will be closed without response.
- Format. Ask for a short summary first, then affected versions, configuration, the reproducer and observed behavior. The kernel asks AI-assisted reporters for concise, plain text reports that stick to verifiable facts. curl asks reporters not to paste long AI-generated explanations.
- One at a time. Django asks reporters to wait for a triage result before submitting more, and may hold bulk submissions. This stops one tool run from becoming forty tickets.
- No severity claims. Ask reporters to leave CVSS out. You assign severity on your scale.
- Fixes welcome. Invite a proposed patch. The kernel asks AI-assisted reporters to have the tool propose a fix and test it, and treats an untestable fix as a sign the issue may not be a security bug.
- Consequences. Say that repeated low quality submissions may lead to a ban from reporting, as Django does.
- Routing. Say which severities go where, if you adopt a public low workflow.
Sample wording
Here is policy text you can adapt. It is ours, written for this post, not copied from any project.
AI-assisted reports
You may use AI tools to find or describe a vulnerability. If you do:
1. Tell us which tools you used and what for (finding, writing, proof of concept).
2. Confirm that a person ran your reproducer against a supported release
listed at https://example.com/security/supported and saw the behavior.
3. Send a short plain text summary first: affected versions, configuration,
reproduction steps, observed and expected behavior. No CVSS scores.
4. Send one report and wait for our triage reply before sending more,
unless the next report is closely related.
Reports that do not reproduce, cite code that does not exist, or appear to
be unedited AI output are closed without further reply. Repeated low quality
reports may lead to a ban from this program.
Severity and routing
Low and Medium: open a public issue using the "Low severity security" form.
High and Critical, or anything under active exploitation: use private
vulnerability reporting. If unsure, report privately and we will tell you
which route applies.
Rewards change behavior
Money increases volume. curl dropped its bounty partly for that reason, and Larson suggests platforms remove incentives such as visible credit counts and limit new accounts' ability to file reports. If you run a paid program, consider paying only for reports that reproduce on a supported release, and paying more for a tested fix than for a finding.
How do you score whether a report affects shipped versions?
A report is about code. Your customers run builds. Scoring means mapping one to the other, and then writing the result in a form you can reuse.
The four questions
- Version. Which supported releases contain the vulnerable code? Use the commit that introduced it, not the reporter's guess.
- Build. Is the vulnerable code compiled into each release, given its options, feature flags and target platforms? curl's severity factors explicitly include build configuration and platform.
- Reach. Does your product call the vulnerable code, and can an attacker control the inputs that reach it?
- Exposure. Is the reachable path exposed in a default deployment, or only in an unusual configuration?
The answers map neatly onto the VEX status and justification values in CISA's minimum requirements, and onto the CycloneDX format many SBOM tools emit.
| What you found | CISA VEX status and justification | CycloneDX analysis |
|---|---|---|
| Component not in this product at all | not_affected: Component_not_present | state not_affected, justification code_not_present |
| Component present, vulnerable code built out | not_affected: Vulnerable_code_not_present | not_affected, code_not_present or requires_configuration |
| Code present but never executed by the product | not_affected: Vulnerable_code_not_in_execute_path | not_affected, code_not_reachable |
| Code runs but attacker cannot control the input | not_affected: Vulnerable_code_cannot_be_controlled_by_adversary | not_affected, requires_environment or protected_by_mitigating_control |
| Product has a built in protection that stops it | not_affected: Inline_mitigations_already_exist | not_affected, protected_at_runtime or protected_by_compiler |
| Reproduces in the shipped product | affected, with an action statement | exploitable, with a response such as update |
| Fix shipped | fixed | resolved |
| Still checking | under_investigation | in_triage |
CISA's document says a not_affected statement should carry a justification, and must carry an impact statement if it does not. For affected, it must include an action statement describing what to do. That discipline is useful even if you never publish VEX: it forces a written reason for every downgrade.
Why SBOMs per release matter here
You cannot answer "which releases ship this" quickly without an inventory per release. Generate an SBOM at build time for every release and keep it. When a report names a component, you search the SBOMs, not the source tree, because the SBOM records what actually went into the artifact. For reports about your own first party code, the release tags and build configs do the same job.
How do CRA and other reporting duties interact with a report flood?
The CRA does not make you report every vulnerability someone sends you. It makes you report specific events quickly, which means your triage gate must catch those events inside the flood.
According to ENISA's factsheet on the CRA Single Reporting Platform, from 11 September 2026 manufacturers must report actively exploited vulnerabilities and severe incidents that affect the security of products with digital elements sold in the EU. Open source software stewards must report those events to the extent they are involved in developing such products. The clock starts when you become aware:
| Report | Deadline according to ENISA |
|---|---|
| Early warning | Within 24 hours of becoming aware of the actively exploited vulnerability or severe incident |
| Notification | Within 72 hours, with general information and an initial assessment |
| Final report, vulnerability | No later than 14 days after a corrective measure, such as a patch, is available |
| Final report, severe incident | Within one month after the 72 hour notification |
ENISA's factsheet defines an actively exploited vulnerability by reference to Article 3(42) of the CRA: one known to be currently exploited by a malicious actor. A researcher's proof of concept is not exploitation by a malicious actor. So a hundred valid low severity reports, none exploited, trigger no CRA notification. One report that says "we saw this used against a customer", or one customer incident ticket that matches a report in your queue, may start the 24 hour clock.
What this means in practice:
- Add one question to your gate. "Does the report or any linked evidence suggest exploitation in the wild?" A yes routes straight to the private high bucket and to whoever owns CRA reporting.
- Do not let the queue hide the signal. If your intake backlog is two weeks deep, a report with exploitation evidence can sit unread past every deadline. This is the strongest argument for a fast gate.
- Keep your triage records. Timestamps of receipt, reproduction and severity decisions show when you became aware.
- Remember upstream. If the exploited flaw is in an open source component you ship, you may still have a reporting duty as the manufacturer of the product that contains it. Our separate guide, CRA: do I report an exploited vulnerability in an open source component?, walks through that case.
How do you turn a valid report into a tested fix quickly?
Once a report passes the gate, speed comes from treating the fix like any other change, with the reproducer as its first test.
- Turn the reproducer into a failing test. Before changing code, add the reproducer to your test suite and watch it fail. This proves you understood the bug and stops it from returning.
- Find the introducing commit.
git bisectwith the new test gives you the exact commit and therefore the affected version range for the advisory. The kernel asks AI-assisted reporters for a Fixes tag pointing at that commit for the same reason. - Fix the smallest thing. Read any patch the reporter proposed, but test it as untrusted input. AI-proposed fixes often silence the symptom in the reproducer without fixing the root cause.
- Run the whole suite, then the fuzzers. Low severity bugs in parsing and connection handling often have siblings. curl's October batch had several connection reuse issues in one release.
- Backport deliberately. Decide per supported branch, write it down, and give each backport its own test run.
- Write the advisory while the fix is in review. Versions, configuration, severity, workaround, credit. For public lows, the issue thread is most of the advisory already.
- Ship and update your VEX or advisory record. Move affected releases to fixed.
Split your time between your code and everyone else's
Many reports that reach vendors are not about first party code at all. They say your product ships an old library with a known CVE. Those are the reports you should automate, because the fix is usually a version bump that a tool can propose and your CI can test. Saving your engineers for first party bugs is the single biggest lever on a report flood.
Step by step: a working intake and triage pipeline
This walkthrough assumes a GitHub hosted project and a product that ships releases. Adapt the commands for your stack.
1. Turn on private reporting and publish the policy
GitHub's documentation describes enabling private vulnerability reporting from the repository's Settings, under Advanced Security. You can also call the REST endpoint with the GitHub CLI:
# Enable private vulnerability reporting on a repository
gh api -X PUT repos/OWNER/REPO/private-vulnerability-reporting
# Confirm it is on
gh api repos/OWNER/REPO/private-vulnerability-reporting
GitHub's docs also describe a custom private report form, placed at .github/VULNERABILITY_REPORT.yml, and an option to require a CWE on new reports. Use the form to ask for the same fields your policy requires: versions, configuration, reproducer and AI tool disclosure. Check GitHub's documentation for the fields it supports.
Put your policy in SECURITY.md at the repository root so it appears on the Security tab.
2. Add a public form for low severity reports
If you adopt public handling for Low and Medium, give reporters a structured issue form so public reports arrive triage ready:
# .github/ISSUE_TEMPLATE/low-severity-security.yml
name: Low severity security report
description: For issues you assess as Low or Medium. High or Critical? Use private reporting.
labels: ["security", "triage"]
body:
- type: input
id: versions
attributes:
label: Affected versions tested
placeholder: "e.g. 4.2.1 and main at commit abc1234"
validations:
required: true
- type: textarea
id: config
attributes:
label: Build options and configuration needed to trigger it
validations:
required: true
- type: textarea
id: repro
attributes:
label: Reproduction steps (text, no binaries)
render: shell
validations:
required: true
- type: dropdown
id: ai
attributes:
label: Did you use AI tools?
options:
- "No"
- "Yes, to find the issue"
- "Yes, to write the report"
- "Yes, to write the reproducer"
validations:
required: true
- type: checkboxes
id: verified
attributes:
label: Verification
options:
- label: A person ran these steps on a supported release and saw the behavior
required: true
3. Reproduce in a throwaway container
Never run a reporter's reproducer on a workstation with credentials. Build the named version and run the steps with no network unless the bug needs one:
# Build the exact version from the report
git fetch --tags
git worktree add ../triage-4.2.1 v4.2.1
cd ../triage-4.2.1
docker build -t triage:4.2.1 .
# Run the reproducer read only, no network, limited resources
docker run --rm --network none --memory 1g --cpus 1 \
-v "$PWD/../repro:/repro:ro" triage:4.2.1 /repro/run.sh
Then repeat against your latest release and main. Record the result in the ticket.
4. Find which releases contain the bug
When the reproducer works, turn it into a test and let git find the range:
# Which commit introduced the vulnerable function?
git log -S 'parse_header_continuation' --oneline -- src/
# Which release tags contain that commit?
git tag --contains 1a2b3c4 --list 'v*'
# Or bisect with the reproducer as the test
git bisect start v4.2.1 v3.0.0
git bisect run ./repro/test.sh
For a feature that depends on build options, check what each release actually enabled. For example, curl prints its compiled features and protocols:
curl -V
curl-config --features
curl-config --protocols
5. Check shipped components with release SBOMs
For reports about a bundled component, search the SBOMs you generated at release time:
# Generate a CycloneDX SBOM for a Node.js release (recent npm versions include npm sbom)
npm sbom --sbom-format cyclonedx > sbom-4.2.1.cdx.json
# Find a component and its version
jq -r '.components[] | select(.name=="libxyz") | "\(.name) \(.version)"' sbom-4.2.1.cdx.json
# Scan the release SBOM and container image with Safeguard (results as JSON under ./output)
safeguard scan --sbom sbom-4.2.1.cdx.json
safeguard scan --image registry.example.com/product:4.2.1
Keep one SBOM per release in the same place as the release artifacts, so the answer for an old release is a file lookup, not a rebuild.
6. Record the decision as VEX
Write the result down once. A CycloneDX VEX entry for a component present but not reachable looks like this:
{
"vulnerabilities": [
{
"id": "CVE-2026-00000",
"source": { "name": "NVD" },
"analysis": {
"state": "not_affected",
"justification": "code_not_reachable",
"detail": "Product 4.2.x bundles libxyz 2.1 but never calls the affected parser; verified by call graph review on 2026-10-22."
},
"affects": [
{ "ref": "urn:cdx:product-4.2.1#pkg:generic/libxyz@2.1" }
]
}
]
}
The CVE number above is a placeholder. When the same component comes up in the next report, the answer is already on file.
7. Gate CI so a fixed version stays fixed
Run your tests and a dependency check on every pull request, so the fix you just shipped cannot be undone by a later merge:
# .github/workflows/security-regression.yml
name: security-regression
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run unit tests including security reproducers
run: make test
- name: Run security regression suite
run: make test-security
Add a dependency gate on top. The "Fix it without waiting for upstream" section below covers a free GitHub Action that can fail a build on known vulnerable versions.
Where Safeguard fits
Safeguard does not read your inbox or triage reports for you, and it does not decide whether a report about your own code is real. That still takes a person with a reproducer. Where it helps is the part of the flood that is about components and versions, and the part that is about fixing.
- Which shipped builds contain it. Safeguard scans repositories, container images and SBOM files, and the platform shows which projects contain a given component and version. That answers "does this report affect any release we ship" in minutes instead of a search across teams.
- Reachability. Reachability analysis, combined with EPSS and CISA KEV signals, helps separate "affects customers" from "theoretical" for vulnerabilities in your dependencies, which feeds the not_affected justifications above.
- CSAF and VEX. Safeguard accepts CSAF and VEX uploads, so the decisions you record in step 6 can live alongside the scan results.
- Fix pull requests. For valid reports where the fix is a dependency upgrade, Griffin can open a tested, policy gated pull request, in one repository or in bulk. Autonomous remediation ships switched off; you choose what runs on its own.
- First party fixes with a human in the loop. The Safeguard CLI's assistant can read a finding, edit code and run your tests, asking before each command under the permission mode you choose.
It does not help with the human parts: judging a reporter's intent, deciding severity on your published scale, or meeting your CRA deadlines. It will not stop slop arriving. It shortens the time from "valid" to "fixed".
Common mistakes
- Triaging in arrival order. A report with exploitation evidence can sit behind fifty lows. Run the ten minute gate on every new report the day it arrives, then work the buckets.
- Arguing instead of asking for a reproducer. Long debates with a reporter about whether a function is vulnerable cost more than one templated request for a working reproduction.
- Accepting the reporter's CVSS score. Severity belongs to your published scale and your build configuration. Projects such as curl and Django explicitly ask reporters not to score.
- Scoring against the repository instead of the release. A bug in
mainthat never shipped is a code fix, not an advisory. A bug only in an option you do not enable is a downgrade with a written reason. - Downgrading without writing it down. If you close a report as not affected, record the justification. The same component will come up again, and the CVE appeals process means someone else may assign a CVE you declined.
- Merging the reporter's patch untested. AI-proposed patches often make the reproducer pass without fixing the cause. Write your own test first.
- Publishing a cluster of lows one by one. Check whether several low findings in one component chain together before any go public.
- Running reproducers on a workstation. Use a disposable container or VM with no credentials and no network by default.
- Ignoring the old releases question. State your supported versions in the policy so reports against ten year old releases can be closed by rule.
FAQ
How can you tell if a vulnerability report was written by AI?
You often cannot, and it matters less than whether the report is true. Common signs are long generic impact sections, references to functions or options that do not exist, confident claims with no reproducer, and severity scores attached by default. Instead of guessing authorship, require disclosure of AI use in your policy and require a reproducer that a person has run.
Should we ban AI-assisted vulnerability reports?
Most projects that have written policies do not ban them. Django, GeoServer and the Linux kernel accept AI-assisted reports but require verification, and curl's October 2026 change was driven by valid reports at volume, many of them AI-assisted. A ban would turn away real bugs. Ban repeat senders of unverified output instead, as Django's policy allows.
What should a vulnerability disclosure policy require for AI-generated reports?
Disclosure of the tools used and what for, a working reproducer run by a person against a supported release, affected versions and configuration, a short plain text format, no CVSS scores, one report at a time, and a stated consequence for repeated low quality submissions.
Is it safe to disclose low-severity vulnerabilities publicly?
For many open source projects, yes, if the line is drawn at High. curl handles LOW and MEDIUM publicly from 26 October 2026 and accepts a slightly longer exposure window in exchange for faster review and fixes. Keep lows private when your users patch slowly, when severity varies widely by deployment, or when several lows might chain.
How long should it take to triage a vulnerability report?
Acknowledge quickly and triage in stages. The CISA VDP template commits to acknowledging receipt within three business days, and Django commits to acknowledging within three working days, with analysis that can take weeks. The first gate (reproduces, supported version, severity bucket) should take minutes, so that reports with exploitation evidence never wait.
Does the Cyber Resilience Act require reporting every vulnerability we receive?
No. According to ENISA, the CRA requires manufacturers to report actively exploited vulnerabilities and severe incidents, with an early warning within 24 hours of becoming aware. A valid report with no sign of exploitation by a malicious actor does not trigger that duty, but a report with exploitation evidence may.
What is VEX and how does it help with report volume?
VEX (Vulnerability Exploitability eXchange) is a standard way to state whether a product is affected by a vulnerability, with statuses such as not_affected, affected, fixed and under_investigation, and justifications such as Vulnerable_code_not_in_execute_path. Writing a VEX statement once means you do not re-triage the same component every time it is reported.
How do we handle many valid low-severity bugs found by an AI audit?
Batch them. Group findings by component, check for chaining, fix them in one release with one test per bug, and publish the advisories together. curl did this with 24 advisories in a single release on 14 October 2026.
Can AI tools fix the vulnerabilities they find?
Sometimes. The kernel's policy asks AI-assisted reporters to have the tool propose and test a fix, and treats an untestable fix as a warning sign. Treat any proposed fix as a draft: write your own failing test from the reproducer, then review the patch against the root cause.
Fix it without waiting for upstream
A report flood often lands on vendors as "your product ships a vulnerable version of a library". For those reports, the fix belongs upstream, and the faster you can apply it, the fewer reports you have to answer twice.
In incidents like this one, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.
3. Gold Registry: start from components that are already fixed
registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | The Gold scan GitHub Action in CI, plus Safeguard policies and gates |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch (early access) |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
These demos show the fixing side of a report flood. They do not show report intake or triage, which stays with your team.
This is a real Safeguard CLI session. Asked to fix the lodash CVE in a repository, it reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with approval, prints a summary and pushes nothing. That is the same flow for a valid report that says your product ships a vulnerable dependency: the safe version, applied and tested, with a person approving each step.
Click through it at your own pace, or open it full screen.
This demo sets up the Safeguard runner on your own machine, approves it with its device code, then scans from the terminal. Use the same flow to scan a release SBOM or image when a report names a component, and get the answer for the exact build customers run.
Click through it at your own pace, or open it full screen.
This demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. Once connected, a triager can ask Claude about the projects, findings and vulnerabilities in their Safeguard account while reading a report, for example whether a named component shows up in any project.
Click through it at your own pace, or open it full screen.
To try it on your own releases, download Safeguard at https://safeguard.sh/download and read the CLI docs at https://docs.safeguard.sh/docs/cli .
Quick check
A report arrives with a convincing write up, a CVSS 9.8 score and no reproducer. What is the first step?
Send one templated request for a working reproducer against a supported release, plus versions and configuration. Ignore the reporter's score; severity is set on your own published scale. Close the report if the reply adds nothing.
Your queue has forty valid Low reports and one that mentions attacks seen against a customer. Does the CRA change the order?
Yes. The report with exploitation evidence may be an actively exploited vulnerability, which under the CRA needs an early warning within 24 hours of becoming aware, according to ENISA. Route it to the private high bucket and your CRA owner now. The forty Low reports trigger no CRA notification.
Sources
- Daniel Stenberg: Do minor curl vulnerabilities in the open (20 October 2026)
- Daniel Stenberg: The end of the curl bug bounty (26 January 2026)
- Daniel Stenberg: Death by a thousand slops (14 July 2025)
- curl: Vulnerability disclosure policy
- curl: Security advisories
- Cyberpress: AI security audit uncovers 24 curl vulnerabilities
- Hacker News: Patch the Planet discussion
- Django: Security policies, including AI-assisted reports
- Linux kernel: Security bugs
- GeoServer: AI policy
- Seth Larson: New era of slop security reports for open source (3 December 2024)
- CISA: Vulnerability disclosure policy template
- CISA: Minimum requirements for VEX
- ENISA: CRA Single Reporting Platform factsheet
- GitHub Docs: Configuring private vulnerability reporting for a repository
- CycloneDX 1.6 JSON reference
Last reviewed: 22 October 2026. Project policies on AI-assisted reports are changing quickly; check each project's own policy page for the current wording.