Responding to a CVE Filed Against Your Open Source Project
Someone just opened an issue, sent you a private email, or posted publicly that your open source project has a security vulnerability β and there's a CVE number attached to it. Your stomach drops. You have no patch, no comms plan, and a growing thread of confused users asking if they should stop using your library right now.
This guide cuts through the noise. It covers exactly what to do from the moment you hear about a CVE to the day you close the issue and ship the fix.
What You'll Learn
- How to verify whether a CVE is legitimate and actually affects your project
- How to communicate clearly with reporters, users, and downstream maintainers
- How to structure your patch and release so the fix ships cleanly
- What a public disclosure notice should contain
- How to reduce the blast radius of future CVEs before they happen
Prerequisites
This article assumes you maintain or co-maintain a public open source project hosted on a platform like GitHub or GitLab. You don't need prior security experience β but you do need write access to your repo and the ability to cut a release.
Step One: Don't Panic, Triage First
The first thing to do when a CVE lands on your doorstep is verify it before you do anything else. CVE IDs can be assigned by anyone with a CNA (CVE Numbering Authority) account, which means a CVE does not automatically mean your project has a confirmed exploitable bug.
Check the CVE entry on cve.mitre.org or the National Vulnerability Database. Look for: the affected version range, the attack vector (network, local, physical), the CVSS score, and the reference links. If the entry is thin or the references point to nothing concrete, that's a signal to investigate further before reacting publicly.
Ask yourself three questions:
- Does the described behavior actually exist in your codebase?
- Which versions are affected?
- Is there a realistic attack path, or is this theoretical?
If you can reproduce the issue in under an hour, move to the next step. If you can't reproduce it at all, reach out privately to the reporter and ask for a proof-of-concept before saying anything publicly.
Set Up a Private Working Space
Once you've confirmed the issue is real, resist the urge to discuss details in your public issue tracker. Any conversation about the specifics of an unpatched vulnerability is a roadmap for bad actors.
GitHub has a built-in Security Advisories feature (under the Security tab of your repo) that gives you a private fork and a draft advisory you can collaborate on before publishing. GitLab has a similar confidential issues mechanism. Use these.
If your project uses a mailing list or Slack workspace, create a temporary private channel for the response team only. Keep the affected-version list and reproduction steps out of any public channel until the patch is ready.
Communicate With the Reporter Early
If the CVE came through a responsible disclosure channel β someone emailed you privately before going public β acknowledge them within 24 hours. You don't need to have a fix yet. You just need to confirm you received it and give them a rough timeline.
A short reply goes a long way:
Hi [Name],
Thank you for reporting this privately. I've confirmed the issue
and I'm working on a fix. My goal is to have a patch ready within
[X days]. I'll keep you posted as things move forward.
If you plan to publish your own write-up, I'd appreciate the
opportunity to coordinate the timing so users have a patched
version available when the details go public.
Thanks again,
[Your name]If the CVE was filed publicly without prior contact, still reach out. Introduce yourself, thank them for the report even if the process was frustrating, and ask whether they'd be willing to coordinate on timing.
Write and Test the Fix
Work on the patch in your private fork or a branch that isn't yet publicly visible. The fix should be minimal and focused. Don't bundle unrelated refactors or features into a security release β reviewers need to audit the exact change that closes the vulnerability, and noise makes that harder.
For a concrete example, if the vulnerability is an unsanitized input being passed to a shell command in a Python utility:
# Vulnerable
import subprocess
def run_tool(user_input):
subprocess.run(f"mytool --flag {user_input}", shell=True)
# Fixed: pass arguments as a list, avoid shell=True
def run_tool(user_input):
subprocess.run(["mytool", "--flag", user_input], shell=False)Write a regression test that fails on the vulnerable code and passes on the fix. This does two things: it proves the fix works, and it prevents the bug from silently reappearing in a future refactor.
If you maintain multiple supported release branches (e.g., a stable 1.x and a development 2.x), backport the fix to each one. Users on older versions are often the most exposed.
Prepare Your Release and Advisory
Before you publish anything, line up:
- A patched release for every supported version branch
- A draft security advisory with the full details
- An update to your CHANGELOG or release notes
- Optional: a CVSSv3 score you've calculated yourself if the CVE database entry is missing one
Your security advisory should include:
- Summary: One sentence describing what the vulnerability is.
- Impact: What an attacker can do if they exploit it, and under what conditions.
- Affected versions: The exact version range. Be precise β "all versions before 2.4.1" is more useful than "older versions".
- Patched versions: Which release(s) contain the fix.
- Workarounds: If users can't upgrade immediately, tell them what configuration change or code pattern reduces the risk.
- Credit: Name the reporter if they want credit.
Avoid vague language like "a potential security issue has been addressed." Users need enough detail to assess their own risk. Some will be running your library in an environment that's already isolated; others won't be. Give them the information to make that call.
Publish Simultaneously
Push the patched releases and publish the advisory at the same time. Publishing the advisory before the fix is available gives attackers a window. Publishing the fix before the advisory leaves users confused about why they should upgrade.
After publishing, notify:
- Your package registry (PyPI, npm, RubyGems, crates.io, etc.) β most will pick up the advisory automatically if you've linked it to the package
- Any downstream projects that depend on yours and have a large user base
- The original CVE reporter, so they know the fix is live and they can publish their own write-up if they have one
Post a brief note in your main README or project website pointing users to the advisory. Not everyone watches release notes.
Common Pitfalls to Avoid
Disputing the CVE without engaging with the reporter
If you believe the CVE is invalid or the CVSS score is inflated, address it calmly and with specifics. Posting a dismissive "this is not a vulnerability" in a public thread without explanation erodes trust and often prolongs the controversy.
Delaying indefinitely
A reasonable coordinated disclosure window is 45 to 90 days. If you haven't shipped a fix by then, most reporters are within their rights to publish full details anyway. Communicate your progress. If you're blocked, say so and ask for help.
Forgetting transitive consumers
If your library is a dependency of other popular packages, those maintainers need to know so they can cut their own releases. A patched version of your library sitting in your registry doesn't help users whose package manager resolves the transitive dependency to the old version because a mid-stack package hasn't updated yet.
Treating the CVE as a PR problem rather than a technical one
The instinct to craft a PR-friendly message before you understand the technical scope is backwards. Fix it first. The communication follows the fix β not the other way around.
Reduce Blast Radius Before the Next One
Once you've shipped the fix and the dust settles, use the experience to harden your process for next time:
- Add a
SECURITY.mdfile to your repo that tells reporters how to submit vulnerabilities privately. GitHub surfaces this file prominently in the Security tab. - Enable GitHub's private vulnerability reporting if you're hosted there β it gives reporters a one-click way to send you a confidential report.
- Set up automated dependency scanning (Dependabot, Renovate, or similar) so you catch vulnerabilities in your own dependencies before your users do.
- Document your release process so a co-maintainer can ship a security patch even if you're unavailable.
A SECURITY.md doesn't need to be long:
# Security Policy
## Supported Versions
| Version | Supported |
|---------|-------------------|
| 2.x | Yes |
| 1.x | Critical fixes only |
| < 1.0 | No |
## Reporting a Vulnerability
Please report security issues by emailing security@yourproject.org
or using GitHub's private vulnerability reporting feature.
Do not open a public issue for security-related bugs.
We aim to acknowledge reports within 48 hours and ship a fix
within 45 days.Wrapping Up
A CVE is not the end of your project's credibility β a slow, defensive, or opaque response is. Users generally respect maintainers who handle security issues calmly and transparently.
Here are five concrete actions to take after reading this:
- Add a
SECURITY.mdto your repo today if you don't have one. It takes 15 minutes and immediately improves your disclosure surface. - Enable private vulnerability reporting on GitHub or your equivalent platform so reporters have a clear path to you.
- Identify your supported version branches and decide now which ones you'd backport a security fix to. Don't make that decision under pressure.
- Run through the GitHub Security Advisories UI on a test repo so you know how it works before you need it urgently.
- Reach out to one or two co-maintainers who could ship a release if you were unavailable during a critical window.
The projects that come out of CVEs with their reputation intact are the ones where maintainers treated the report as a collaboration, not an attack.
π€ Share this article
Sign in to saveRelated Articles
Comments (0)
No comments yet. Be the first!