On the clock most people mean, npm ships security fixes fastest and Maven slowest: in a study of 2,001 advisories across seven ecosystems, the median npm fix was released the same day it was committed, against 13 days for Maven. But the slowest clock everywhere is downstream adoption, which runs to months, and that is the clock your own team controls.
That one sentence hides a measurement problem. Research papers that report "time to fix" measure at least four different intervals, start them from different dates, and draw on different years and databases. Put their medians in one column and you get a chart that looks precise and means nothing. This post separates the clocks, puts each study's numbers on the clock it actually measured, and ends with an SLA model per ecosystem that a security team can defend to an auditor.
Key takeaways
- Fix commit to release is fast almost everywhere. Across Composer, Go, Maven, npm, NuGet, pip and RubyGems, the median security release came within 4 days of the fix commit (Imtiaz, Khanom and Williams, data as of March 2021). npm had a median of 0 days; Maven had 13.
- Most fixes exist before the advisory does. In Maven, 81.6% of CVEs were patched before public disclosure (Yang-Smith and Abdellatif, 2025). In npm, 83.1% of fixed vulnerabilities were fixed before publication, with a median offset of about 19 days early (Robinson et al., 2026).
- PyPI is the outlier on disclosure order. 40.86% of PyPI vulnerabilities were only fixed after they were made public, and the median time from discovery to a fixed release was about two months (Alfadel, Costa and Shihab).
- Advisories trail releases by weeks. For 69.1% of advisories published after the fix shipped, the median lag from release to advisory was 25 days, from 2 days for NuGet to 167 days for RubyGems (Imtiaz et al.).
- Review queues add more time. GitHub reported in June 2026 that advisory processing stretched to "multiple weeks for a meaningful share" of advisories during a record surge, and its own alerting only uses reviewed advisories.
- Downstream adoption is the longest clock. Direct Maven dependents took a median of 151 days to adopt a fix that already existed. Python projects took a median of 7 months. Transitive Maven exposure grew from a median of 65 days at the direct level to 1,822 days ten levels deep.
- You do not have to wait for any of the upstream clocks. You can measure and shorten adoption, and for the cases where upstream has no fix yet, you can patch a fork.
The four clocks in a vulnerability's life
Every vulnerability in an open source package passes through a sequence of dates. Not every vulnerability hits every date, and the order is not fixed, which is exactly why studies disagree.
- Introduction. The first release that contains the vulnerable code.
- Discovery or report. Someone finds the flaw and tells the maintainer, or files it publicly.
- Fix commit. The patch lands in the source repository.
- Fixed release. A version containing the patch is published to the registry.
- Advisory publication. A CVE record or a database advisory goes public.
- Tool awareness. Your scanner's data source picks the advisory up, which can be later than publication if the source reviews entries first.
- Downstream adoption. Your project, and every project between you and the vulnerable package, moves to a fixed version and ships it.
Grouping those dates gives four clocks that matter for a security programme.
| Clock | Starts | Ends | Who controls it | Typical study that measures it |
|---|---|---|---|---|
| A. Fix creation | Report or discovery | Fix commit | Upstream maintainer | Alfadel et al. (PyPI, discovery to fixed release) |
| B. Release | Fix commit | Fixed version on the registry | Upstream maintainer | Imtiaz et al. (seven ecosystems) |
| C. Advisory | Fixed release, or fix | Advisory published and visible to tools | Maintainer, CNA, database curators | Imtiaz et al. (release to advisory); GitHub (review queue) |
| D. Adoption | Fixed version available | Your shipped software uses it | You, and every intermediate maintainer | Yang-Smith and Abdellatif (Maven direct); Przymus et al. (Maven transitive); Alfadel et al. (Python projects) |
There is also a fifth interval that some papers report as their headline: total exposure, from the first vulnerable release to the fix. The 2026 npm study does this. It is a real and useful number, but it starts years before anyone knew the flaw existed, so it cannot be compared with a release clock measured in days.
Which clock do most studies measure?
Most of the academic literature measures clock B, the publication versus fix order, or total exposure, because those are the dates that can be pulled automatically from registries and vulnerability databases. Clock A needs a reliable discovery or report date, which public records rarely contain. The Maven lifecycle paper says so directly: the absence of CVE discovery dates means its mitigation times are "a proxy metric" and a lower bound. Clock D is the least studied and, as the numbers below show, the longest.
When you read a vendor report or a conference talk that says "ecosystem X takes N days to fix", the first question is which of these clocks N measures. The five questions for reading a time to patch report walk through the rest.
The studies and what each one measured
Eight sources carry the numbers in this post. Here is what each one did, in plain terms, before we look at the results.
| Study | Ecosystems | Sample | Data as of | Clock measured | Statistic |
|---|---|---|---|---|---|
| Imtiaz, Khanom, Williams, "Open or Sneaky? Fast or Slow? Light or Heavy?" (arXiv 2112.06804, Dec 2021) | Composer, Go, Maven, npm, NuGet, pip, RubyGems | 4,377 advisories, 2,001 with fix commits for the release analysis | Advisory database snapshot of 5 March 2021 | B (fix commit to release) and C (release to advisory) | Medians |
| Yang-Smith, Abdellatif, "Tracing Vulnerabilities in Maven" (arXiv 2502.04621, Feb 2025) | Maven | 3,362 CVEs, 1,470 artifacts, 190,945 releases | MSR 2025 challenge dataset with OSV data | Publication versus patch order; D for direct dependents | Means by severity; medians for adoption |
| Przymus et al., "Out of Sight, Still at Risk" (arXiv 2504.04803, Apr 2025) | Maven | 2,676 CVEs, 132,235 projects, 3.38 million artifacts | August 2005 to August 2024 | D, cumulative through transitive levels | Kaplan Meier, mean and quartiles |
| Robinson et al., "Original Sin of npm" (arXiv 2604.17668, Apr 2026, accepted to ACM ASIA CCS 2026) | npm | 1,077,946 sampled packages, about 1,500 unique vulnerabilities | npm snapshot of 5 September 2023; publications 2015 to 2023 | Total exposure (introduction to fix); publication versus fix offset | Kaplan Meier medians |
| Alfadel, Costa, Shihab, "Empirical Analysis of Security Vulnerabilities in Python Packages" | PyPI | 1,396 reports, 698 packages, 2,224 GitHub projects | Reports published 2006 to June 2021 | A (discovery to fixed release); disclosure order; D for projects | Kaplan Meier medians |
| Zerouali, Mens, Decan, De Roover, npm and RubyGems dependency networks (arXiv 2106.06747, v2 Mar 2022) | npm, RubyGems | Commercial advisory database | 2021 | Disclosure time trends; fixability within same major version | Medians, shares |
| Sridharkumar et al., "Detecting Protracted Vulnerabilities" (arXiv 2603.27067, Mar 2026) | NVD CVEs with GitHub artifacts | 20,951 CVEs | 1999 to July 2024 | Long gaps between fix and disclosure | Medians on a sample |
| GitHub blog, "Inside the Advisory Database" (29 June 2026) | All GitHub reviewed ecosystems | Operational figures | January to May 2026 | C (review queue) | Counts, processing time |
Two of these datasets came from a commercial vulnerability database run by a security vendor. We name the papers, not the vendor, and note where that origin matters.
Clock B: how quickly a fix commit becomes a release
This is the clock that answers the headline question most directly, and it has the cleanest cross ecosystem study.
Method
Imtiaz, Khanom and Williams started from 4,377 advisories covering 4,812 security releases in 2,217 packages across seven ecosystems. For the release timing question they kept the 2,001 advisories where they could identify the fix commit, then measured the days between that commit and the first release that contained it. They checked a sample of the data by hand and report about 96% accuracy for this subset. Release dates came from each registry's API, except for Maven (crawled from Maven Central) and Go (repository tags, since Go has no central upload registry).
Results by ecosystem
Here is the ranked table this post is named for. It ranks ecosystems by median days from fix commit to release.
| Rank | Ecosystem | Advisories with fix commit | Median days, fix to release | Advisory published before the fix was committed | Advisory published before the fix was released |
|---|---|---|---|---|---|
| 1 | npm | 553 | 0 | 13.0% | 20.4% |
| 2 | Composer (PHP) | 183 | 1 | 7.1% | 14.8% |
| 3 (tie) | NuGet (.NET) | 70 | 3 | 11.4% | 20.0% |
| 3 (tie) | RubyGems | 113 | 3 | 8.0% | 13.3% |
| 5 (tie) | Go | 184 | 6 | 11.4% | 26.1% |
| 5 (tie) | pip (PyPI) | 324 | 6 | 12.0% | 24.4% |
| 7 | Maven (Java) | 574 | 13 | 7.0% | 26.7% |
| All seven | 2,001 | 4 | 10.1% | 22.4% |
Source: Imtiaz, Khanom and Williams, arXiv 2112.06804, Table 3. Data reflects the advisory database as of 5 March 2021.
The paper adds detail behind the medians. In npm, 50.3% of security releases came within 24 hours of the fix. In Maven, only 14.9% did, and Maven also showed the widest spread. Across all ecosystems the first quartile was 0 days and the third quartile was 20 days, so a quarter of releases still came at least 20 days after the fix. High severity advisories were released faster than medium ones (median 3 days against 5).
Why npm is fast and Maven is slow on this clock
The paper does not test causes, so treat these as reasonable readings rather than findings. Publishing to npm is a single command by a single maintainer, and many npm packages are small with one maintained branch. Maven artifacts are often parts of larger multi module projects with release trains, staging repositories and signing steps. The paper's manual review of 44 slow releases found that the most common pattern (27 cases) was maintainers waiting until the release to publish the advisory, which removes the pressure to release quickly. It also found 5 cases where the fix shipped fast on the latest branch but was slow to reach an older maintained branch. If you run an older major version, your clock B can be much longer than the ecosystem median.
What this clock tells you, and what it does not
Clock B is short. For most ecosystems it is measured in days, not weeks. That means that once a fix is committed upstream, waiting for "the release" is rarely what keeps you exposed for months. The paper also makes a sharper point: during those days the fix is public in the repository while the advisory is not, so an attentive attacker can read the commit before your scanner knows anything is wrong.
Clock C: from release to a published advisory, and then to your tools
Release to advisory publication
The same paper measured how long advisories took to appear after the fixed release. Of 3,655 advisories with both dates, 2,527 (69.1%) were published after the security release. For those, the median gap was 25 days.
| Ecosystem | Advisories published after the fixed release | Median days from release to advisory |
|---|---|---|
| NuGet | 150 of 241 (62.2%) | 2 |
| Go | 145 of 211 (68.7%) | 15 |
| pip | 367 of 569 (64.5%) | 19 |
| Composer | 509 of 751 (67.8%) | 21 |
| npm | 540 of 735 (73.5%) | 24 |
| Maven | 693 of 937 (74.0%) | 43 |
| RubyGems | 123 of 211 (58.3%) | 167 |
| All | 2,527 of 3,655 (69.1%) | 25 |
Source: Imtiaz et al., arXiv 2112.06804, Table 8. Advisory date is the earlier of NVD and one commercial advisory database.
The RubyGems number is driven by advisories that never received a CVE. The authors found that RubyGems advisories without a CVE had a median delay of 948 days, against 42 days for those with a CVE. Their explanation is that some security fixes were found years later by people scanning repositories for unannounced fixes. Across all ecosystems, CVE advisories had a median delay of 21 days and non CVE advisories 55 days. High severity advisories appeared faster than medium ones (20 days against 33).
So the ranking flips. npm, first on clock B, sits in the middle on clock C. Maven is slow on both. RubyGems, joint third on clock B, is far behind on clock C. Any single "fastest ecosystem" claim has to say which clock it ranks.
How much a review backlog adds to the "known" date
An advisory being published somewhere is not the same as your tooling acting on it. GitHub's Advisory Database is a good public example because GitHub documents how it works.
According to GitHub's documentation, advisories come in three kinds. Reviewed advisories are checked for validity before publication. Unreviewed advisories are published automatically from the NVD feed. Malware advisories cover malicious packages. GitHub's own alerting does not raise alerts for unreviewed advisories, because that type of advisory "isn't checked for validity or completion". Reviewed advisories cover Composer, Erlang, Go, GitHub Actions, Maven, npm, NuGet, pip, Pub, RubyGems, Rust and Swift.
In a post dated 29 June 2026, GitHub described what happened when inbound volume broke records:
- May 2026 saw 1,560 reviewed advisories, the most in the database's history and more than five times the typical month.
- From March to May GitHub made more than 6,000 advisory decisions a month.
- Private vulnerability reports rose from about 550 a week in January to more than 3,000 a week for most of May. Repository advisories rose from about 650 a week to more than 5,000.
- Starting in mid April, processing times stretched first to about a week and then to "multiple weeks for a meaningful share" of advisories.
- Critical issues were prioritised for review.
The post does not give a backlog size or a per ecosystem breakdown, so we cannot put a precise number on it. What it does show is that clock C has a second stage that grows when volume spikes, and that the stage is invisible if you only look at the advisory's "published" timestamp. The OSV schema, for example, defines published only as "the time the entry should be considered to have been published", which is the database entry's date, not the date the flaw became known.
For a team, the practical consequence is simple. If your scanner relies on a reviewed feed, its "known" date can trail the CVE record by days to weeks in a busy month. That is one more reason not to start your SLA clock only when a ticket appears.
Clock A and the disclosure order: fixed before or after the world knows?
Maven: most fixes predate disclosure
Yang-Smith and Abdellatif enriched the MSR 2025 Maven dependency graph with OSV data for 3,362 CVEs. They classified each by the order of two dates: the CVE publication date and the date of the first patched release.
- 81.6% of CVEs were patched before public disclosure.
- The paper's results section says 12.8% had no patch in the dataset and 5.6% were published before the patch. Its introduction states the reverse (12.8% disclosed before a patch, 5.6% unresolved). We could not resolve this from the paper, so read those two numbers as "together about 18%".
- For CVEs published before a patch, the mean time to a patched release fell with severity: 151 days for low, 123 for moderate, 84 for high and 78 for critical. The abstract presents this as a 48.3% faster response for critical issues.
Note that those severity figures are means from the paper's Table II, not medians. The abstract describes the trend as "response time", which is easy to confuse with the 151 day median in the adoption analysis below. They are different measurements that happen to share a number.
The authors list their own limits. CVE records often lack a lower bound for affected versions, and there are no discovery dates, so mitigation time is a lower bound on how long maintainers actually knew.
npm: fixes typically land about 19 days before publication
Robinson and colleagues sampled 1,077,946 npm packages from a September 2023 snapshot, built dependency networks with the deps.dev API, and matched vulnerabilities through OSV and NVD. For each vulnerability they compared the fix release date with the publication date.
- 83.1% of vulnerabilities were fixed before publication, 9.7% after publication, and 7.1% remained unfixed. (The paper's findings paragraph gives slightly different figures, 83.4% and 6.9%.)
- The Kaplan Meier median of the publication to fix offset was minus 0.62 months, about minus 19 days. A negative offset means the fix shipped first. Half of the fixed vulnerabilities had a fix at least about 19 days before the advisory appeared.
The authors read this as maintainers publishing advisories once a fix exists, which fits coordinated disclosure, but they note they did not verify it.
What the 59 month npm figure actually measures
The same paper reports that it takes about 59 months for 50% of npm vulnerabilities to be fixed. This number has been quoted as if npm maintainers take five years to respond. They do not, and the paper does not say so. Here is what it measures:
- Start: the date the first vulnerable version was uploaded to npm, not the report or advisory date.
- End: the date a fixed version became available.
- Statistic: a Kaplan Meier median with unfixed vulnerabilities treated as censored, not an average.
- Companion figure: the median from introduction to publication was 71 months.
Read together, the two numbers say that npm vulnerabilities typically sat undiscovered in released code for years, and that the fix usually arrived shortly before the advisory. That is a statement about how long bugs hide, not about how slowly maintainers fix them. If you use the 59 month figure in a slide, label it "first vulnerable release to fix".
PyPI: four in ten fixed only after disclosure
Alfadel, Costa and Shihab studied 1,396 vulnerability reports affecting 698 PyPI packages, drawn from a commercial advisory database, covering reports published up to June 2021. Their journal version extends a 2021 conference paper.
- Vulnerabilities took a median of 39 months to be discovered after the vulnerable code was introduced, against 26 months for npm in the comparison study they cite.
- 40.86% of vulnerabilities received their first fixed release only after public disclosure. 37.77% were fixed between discovery and publication, and 18.82% were fixed before the discovery date was recorded.
- For vulnerabilities fixed after discovery, the median time from discovery to fixed release was about 2 months. 7.37% took more than a year. Severity made no statistically significant difference.
- The npm comparison they cite found a median of 11 days from discovery to fix and 82% fixed before publication.
The 40.86% figure is the key contrast. In npm and Maven the large majority of fixes predate disclosure. In PyPI, in this sample, a large minority did not, which means a meaningful share of PyPI advisories arrived with no fixed version to move to. The authors attribute the difference to community practices and reporting policies rather than to anything inherent in Python.
Protracted vulnerabilities: the long tail of all clocks
Sridharkumar and colleagues looked at the opposite end. From 20,951 NVD CVEs with GitHub artifacts (1999 to July 2024), they classified 3,228 (15.4%) as protracted, meaning they had a long gap, more than a year in their selection, between report and patch or between patch and public disclosure. In a sample of 94 such CVEs, the median gap from fix to patched release was 9 days, but the median from patch to public disclosure was 619 days. The most common cause in that sample was delayed reporting to NVD (65 of 94). Their detector evaluation covers C, C++ and Java only, and the paper's counts are not fully consistent across sections.
The lesson is that a vulnerability can be fixed upstream and silently sit in your dependency tree for well over a year before any advisory tells your scanner to look. Keeping dependencies reasonably current is the only defence against fixes nobody announced.
Clock D: downstream adoption, the longest clock
Every study that measured adoption found it to be longer than every upstream clock. This is also the clock that a security team can actually change.
Maven direct dependents
Yang-Smith and Abdellatif classified how direct dependents adopted fixes, by the order of three events: patch release, CVE publication and dependent adoption.
| Adoption pattern | Order of events | Cases | Share | Median days |
|---|---|---|---|---|
| Available patch adoption | Patch, then CVE, then dependent adopts | 46,536 | 62.9% | 151 |
| Reactive adoption | CVE, then patch, then dependent adopts | 3,313 | 4.5% | 249 |
| Proactive adoption | Patch, then dependent adopts, then CVE | 24,144 | 32.6% | Not reported (wide spread) |
Source: Yang-Smith and Abdellatif, arXiv 2502.04621, section III C. Response time is measured from the earliest patch date to the latest affected date in the dependent.
An earlier summary of this paper described 151 days as the maintainer response "where a fix was already available" and 249 days "where no patch existed at disclosure". The second half is close: reactive adoption covers CVEs disclosed before a patch existed. The first half needs a correction. 151 days is how long direct dependents took to stop shipping the vulnerable version when the fix was already out before the CVE was published. It is downstream adoption, not upstream response. In other words, most of the delay sat with consumers who had a fix available.
Maven transitive dependents
Przymus and colleagues extended the same Maven graph to transitive dependencies across 132,235 projects and 2,676 CVEs (August 2005 to August 2024) and ran a Kaplan Meier survival analysis by dependency depth.
| Dependency level | Median cumulative days to fix | Mean cumulative days | Median days for that single level | Dependencies at that level |
|---|---|---|---|---|
| 0 (the vulnerable artifact) | 65 | 215 | 62 | 3,046 |
| 1 | 140 | 429 | 40 | 184,579 |
| 2 | 334 | 597 | 40 | 417,797 |
| 3 | 355 | 792 | 41 | 439,878 |
| 4 | 584 | 1,104 | 44 | 455,303 |
| 5 | 676 | 1,145 | 39 | 482,524 |
| 6 | 888 | 1,364 | 41 | 428,033 |
| 8 | 1,617 | 1,900 | 37 | 248,152 |
| 10 | 1,822 | 2,075 | 41 | 149,685 |
Source: Przymus et al., arXiv 2504.04803, Table II (levels 7 and 9 omitted for space).
Two things stand out. First, each individual hop is quick and stable: about 40 days at the median from a vulnerable version to the next clean release, at every level. Second, those hops add up. A vulnerability five levels down took a median of 676 days, nearly two years, to clear, and the busiest levels are exactly the middle ones. The authors fit a rough rule of thumb for the mean: about six months per level plus eight months. They are careful to call that model hypothesised rather than validated.
The paper has one wording inconsistency worth knowing: it describes the cumulative clock as starting at CVE introduction, while its figure axis and its limitations section refer to CVE publication. It also tracks only the most recent affected version of each artifact and ignores embargo periods, both of which make the figures a lower bound.
Python projects
Alfadel and colleagues followed 2,224 GitHub Python projects. 55.62% depended on at least one vulnerable package at some point. The median time for a project to move from a vulnerable dependency version to a fixed one was 7 months, three and a half times the upstream median of 2 months. Part of this is release cadence: the median project needed 2 releases to make the update, and the median gap between releases was 3 months.
npm and RubyGems
The 2026 npm paper does not measure adoption itself; it quotes external estimates instead. The Zerouali study of npm and RubyGems found that 33% of the vulnerable dependencies projects were exposed to, and 40% of those packages were exposed to, already had a fix within the same major version range. That means a large share of exposure needed no breaking upgrade at all, only an update that nobody had made.
Putting the clocks side by side
This table puts every headline figure on its own clock. Read across a row only. Do not compare numbers in different rows.
| Clock | npm | Maven | PyPI | RubyGems | Source and data date |
|---|---|---|---|---|---|
| Introduction to discovery, median | 26 months | Not measured | 39 months | Not measured | Alfadel et al. (PyPI to June 2021), citing Zerouali et al. for npm |
| Discovery to fixed release, median | 11 days | Not measured | About 2 months | Not measured | Alfadel et al., same |
| Fixed before publication | 83.1% | 81.6% | 18.82% before discovery plus 37.77% before publication | Not measured | Robinson et al. (2023 snapshot); Yang-Smith and Abdellatif (2025); Alfadel et al. |
| Fix commit to release, median | 0 days | 13 days | 6 days | 3 days | Imtiaz et al. (March 2021) |
| Release to advisory, median (if advisory came after) | 24 days | 43 days | 19 days | 167 days | Imtiaz et al. (March 2021) |
| First vulnerable release to fix, KM median | 59 months | Not measured | Not measured | Not measured | Robinson et al. (2023 snapshot) |
| Downstream adoption, median | Not measured directly | 151 days (direct, fix already out); 65 to 1,822 days cumulative by depth | 7 months (GitHub projects) | Not measured | Yang-Smith and Abdellatif; Przymus et al.; Alfadel et al. |
The pattern is consistent even though the samples are not. Upstream clocks are measured in days to weeks once a vulnerability is known. Adoption clocks are measured in months to years.
Why survivorship and censoring bias move the medians
Time to fix studies are survival problems: you watch a population until an event happens, and some members never reach the event before the study ends. How a study handles that changes the median, sometimes a lot. Our post on survivorship bias in time to patch statistics covers the general case; here is how it plays out in these papers.
Dropping unfixed items makes medians look faster. If a study only measures vulnerabilities that have a fix, the slow tail that never got fixed vanishes from the sample. The 2026 npm paper avoids this by treating the 7.1% of unfixed vulnerabilities as censored in a Kaplan Meier estimate. The Maven adoption analysis excludes "No Patch" cases entirely, so its 151 and 249 day medians describe only vulnerabilities that were eventually patched.
Snapshot timing truncates long tails. A study that ends in March 2021 cannot observe a fix that arrives in 2023. Kaplan Meier handles this correctly only if the censoring is unrelated to how slow the item is, which is rarely true for abandoned packages.
Removing dead packages biases toward active ones. The npm study dropped about 400,000 sampled entries that were unavailable or deprecated. That makes the remaining sample more actively maintained than npm as a whole, which probably shortens its fix times.
Lower bounds everywhere. The Maven transitive study tracks only the most recent affected version and ignores embargoes. The Maven lifecycle study has no discovery dates. Both say their numbers are lower bounds. The real clocks are longer.
Database dates are not event dates. The npm study found that OSV and NVD publication dates for the same vulnerability differed by about 5 days on average, with outliers over five years. Imtiaz and colleagues took the earlier of two databases. A study that used only one would get a different clock C.
Old data, changing ecosystems. The release and advisory study reflects March 2021. Since then registries have added provenance, private vulnerability reporting has grown (GitHub reports more than 1.7 million repositories have it enabled), and CVE volume has climbed. The direction of the findings is likely still right; the exact medians should be treated as historical.
How we measured
We did not run new measurements for this post. We read each paper's methods and results sections in full where we could fetch them, took the figures from the paper's own tables rather than from summaries, and recorded for each figure:
- The clock. Which two dates bound the interval.
- The statistic. Median, mean, Kaplan Meier median, or share.
- The sample. Ecosystems, counts and data date.
- The source of dates. Registry APIs, OSV, NVD, a commercial database, or repository tags.
Every table above carries its clock and source. We never mixed clocks in one column. Where a paper reported different numbers for the same thing in two places, we report both and say so. Where a figure came from a paper citing another paper (the npm 11 day and 26 month figures, cited by the PyPI study), we say so. Two of the datasets came from a commercial vulnerability database; we name the papers and describe the database generically.
We also checked one earlier internal summary against the source. It described the Maven 151 and 249 day figures as maintainer response times. The paper defines them as direct dependent adoption times, and we use that definition here.
If you want the same discipline in your own reporting, the post on two clocks for OS and dependency time to fix shows how to separate them in a dashboard, and why time to fix beats vulnerability count explains why the metric is worth the effort. The data notes on median time to fix by ecosystem and median time to fix vulnerabilities by ecosystem cover advisory database figures we do not repeat here.
Measure your own four clocks: a walkthrough
Published medians tell you what is normal. Your own clocks tell you where your time goes. Here is how to measure each one for a single vulnerability, using public APIs and the tools each ecosystem ships.
Step 1: get the advisory's published date and fixed version
The OSV API returns the database entry with published, modified and the fixed event for each affected range.
# Replace with the advisory ID you care about
curl -s https://api.osv.dev/v1/vulns/GHSA-xxxx-xxxx-xxxx \
| jq '{id, published, modified, fixed: [.affected[].ranges[].events[] | select(.fixed) | .fixed]}'
Remember that published is the entry's date in that database, not necessarily the CVE date. Record both if you have them.
Step 2: get the fixed release date from the registry
# npm: every version's publish time
npm view lodash time --json | jq '."4.17.21"'
# PyPI: upload time of a version
curl -s https://pypi.org/pypi/requests/2.32.0/json | jq -r '.urls[0].upload_time_iso_8601'
# Go: module version time from the module proxy
curl -s https://proxy.golang.org/golang.org/x/net/@v/v0.23.0.info | jq -r .Time
# RubyGems: version created_at
curl -s https://rubygems.org/api/v1/versions/rack.json | jq -r '.[] | select(.number=="3.0.9.1") | .created_at'
For Maven, check the release date on Maven Central for the artifact version. Imtiaz and colleagues found one case where Maven Central's listed date was later than the repository tag, so cross check against the project's git tag if the number matters.
Step 3: find the fix commit date
git clone --filter=blob:none https://github.com/OWNER/REPO.git && cd REPO
git log -1 --format='%H %cI %s' FIX_COMMIT_SHA
Fix commit to registry release is your clock B for that vulnerability.
Step 4: find when your project adopted the fix
# npm: first commit where the lockfile resolved the fixed version
git log --reverse --format='%h %cs' -S'"version": "4.17.21"' -- package-lock.json | head -1
# Python with a requirements file
git log --reverse --format='%h %cs' -S'requests==2.32.0' -- requirements.txt | head -1
# Maven: confirm the resolved version today, including transitive paths
mvn -q dependency:tree -Dincludes=org.apache.commons:commons-text
# Go: which module versions are in the build
go list -m all | grep golang.org/x/net
Adoption is the gap between the fixed release date and that commit, and then the gap to the deploy that shipped it. That second part is the one most teams never measure.
Step 5: see what is still exposed right now
npm audit --omit=dev
pip-audit -r requirements.txt
govulncheck ./...
mvn versions:display-dependency-updates
Or run one scan across all of them and keep the JSON:
safeguard scan --dir .
# results are written as JSON under ./output
Do this for your last ten high or critical findings and you will have your own clock D median, which is a far better basis for an SLA than any study.
What SLA should you set per ecosystem?
The research supports a few defensible principles. It does not support a single universal number, and you should be wary of anyone who quotes one as "the industry standard".
Start the clock at fix availability, not at ticket creation
Because most fixes in npm and Maven exist before the advisory, and because review queues can add weeks, an SLA that starts when your scanner raises a ticket hides real exposure. Start it at the later of two dates: the fixed release date, or the advisory publication date. Record the scanner alert date separately so you can see feed lag.
Use ecosystem only where it changes the clock you control
Upstream ecosystem differences mostly affect clocks A to C. Your SLA governs clock D. The ecosystem matters to clock D in two ways: how hard upgrades are (Maven's deep transitive graphs and BOM pinned versions make upgrades slower), and how often a fix does not exist yet (PyPI's 40.86% fixed after disclosure means more cases with no version to move to).
A model to adapt
| Situation | Suggested target from fix availability | Why |
|---|---|---|
| Known exploited, any ecosystem, direct dependency | Days, not weeks | Exploitation removes the time you thought you had |
| Critical or high, fix in the same major version | 14 to 30 days | Zerouali et al. found a third or more of exposure had a same major fix; these updates are usually low risk |
| Critical or high, fix needs a major upgrade | 30 to 60 days with a tracked exception | Breaking changes need testing; track the exception rather than miss silently |
| Transitive only, deep in a Maven graph | Same target, but measured on an override or managed version | Waiting for each intermediate maintainer adds about 40 days per level at the median |
| No upstream fix exists (common in PyPI, about 18% of Maven CVEs) | Compensating control within days; patched fork or replacement on a dated plan | There is nothing to upgrade to, so the SLA has to name a different action |
| Medium and low | Next routine dependency update cycle | Keeping current also catches fixes nobody announced |
As a historical reference point, CISA's BOD 19-02 required US federal agencies to remediate critical findings on internet facing systems within 15 calendar days and high within 30, counted from initial detection. CISA's page now marks that directive as revoked and superseded by BOD 26-04, so cite it as precedent, not as current federal policy. These are suggestions to adapt to your risk appetite, not requirements.
Report the clock you measured
When you report against the SLA, report the clock: "median days from fixed release to production deploy, high and critical, direct and transitive". That one phrase prevents most arguments with auditors and leadership about whether 30 days is good or bad.
Common mistakes
- Comparing medians from different clocks. A 59 month npm exposure figure and a 4 day release figure are not fast and slow versions of the same thing.
- Treating "fixed before publication" as "safe". In the release study, fixes sat public in repositories for days to weeks before advisories, and 22.4% of advisories came out before the fix was released. Attackers can read commits.
- Starting the SLA at the scanner alert. Feed review queues and advisory lags mean the alert can arrive weeks after the fix. Start at fix availability.
- Ignoring transitive depth. A direct dependency SLA says nothing about a vulnerability five levels down, which took a median of 676 days to clear in Maven.
- Assuming no CVE means no fix. RubyGems advisories without a CVE took a median of 948 days to be published after the fix shipped. Routine updates pick up fixes nobody announced.
- Quoting old medians as current. The cross ecosystem release study reflects March 2021. Label the data date every time.
- Waiting for upstream when no fix exists. About four in ten PyPI vulnerabilities in one study had no fix at disclosure. Waiting is a choice, not the only option.
- Mixing means and medians. The Maven severity figures are means; the adoption figures are medians. Long tails make means much larger.
Fix it without waiting for upstream
The research is clear that the slowest clock in this post is downstream adoption, and that is the clock you own. The second worst case is the one where clock A never finishes, because upstream has not shipped a fix.
Whatever the vulnerability, 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.
FAQ
Which programming ecosystem releases security fixes the fastest?
On the fix commit to release clock, npm, with a median of 0 days and half of releases within 24 hours, in a study of advisories as of March 2021. Composer was next at 1 day. Maven was slowest at 13 days. On other clocks the order changes.
Which ecosystem is slowest to patch vulnerabilities?
Maven was slowest on both release (13 days) and advisory publication (43 days) in the same study. RubyGems was slowest on advisory publication overall at 167 days, driven by advisories without CVEs. On downstream adoption, every ecosystem studied takes months.
How long does it take open source maintainers to fix a vulnerability?
Once a vulnerability is reported, studies find a median of about 11 days for npm and about 2 months for PyPI from discovery to a fixed release. Once the fix is committed, the median release follows within about 4 days across seven ecosystems. Data dates are 2021 and earlier.
What does it mean when a vulnerability is fixed before it is published?
It means a fixed version was on the registry before the CVE or advisory went public, usually through coordinated disclosure. It happened for 83.1% of npm and 81.6% of Maven vulnerabilities in recent studies. It also means the fix was visible in public code before your scanner knew about it.
Is it true that npm vulnerabilities take five years to fix?
No. The 59 month figure from a 2026 npm study measures from the first vulnerable release, often years before anyone knew of the flaw, to the fix. Once known, npm fixes usually arrive before or shortly after publication.
How long do projects take to update vulnerable dependencies?
Longer than upstream takes to fix them. Direct Maven dependents took a median of 151 days to adopt a fix that already existed. Python projects took a median of 7 months. Transitive Maven exposure five levels deep took a median of 676 days to clear.
Why do GitHub advisories sometimes appear weeks after a CVE?
GitHub reviews advisories before its alerting uses them. In a June 2026 post GitHub said record volume stretched processing to multiple weeks for a meaningful share of advisories from mid April. Unreviewed advisories are visible but do not trigger GitHub's alerts.
What is a good SLA for fixing vulnerable dependencies?
There is no single standard. Start the clock at fix availability, use days for known exploited issues, roughly 14 to 30 days for critical and high fixes within the same major version, and a dated plan with compensating controls where no upstream fix exists.
Should my SLA differ by programming language?
Only where the ecosystem changes the work. Deep Maven graphs make transitive fixes slower, and PyPI more often has no fix at disclosure. The SLA itself should apply to adoption, which you control, rather than to upstream speed.
What can I do when upstream has not released a fix?
Apply a compensating control, check whether a fixed fork or hardened build exists, and plan a replacement if the package is unmaintained. Safeguard's fork and patch flow covers this case and is in early access.
See how Safeguard would help
Measuring adoption is only half the job; shortening it is the other half. These demos show the parts of Safeguard that act on clock D.
The first demo is a real Safeguard CLI session. You install it, open the interactive terminal and ask it to fix the lodash CVE in a repository. It reads the finding and the advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with your approval, prints a summary and pushes nothing. That is the adoption clock collapsed to minutes for a direct dependency where a fix already exists, the most common case in every study above.
Click through it at your own pace, or open it full screen.
The second demo sets up the Safeguard runner on your own machine, approves it with its device code and then scans from the terminal. Running scans close to the code is how you measure your own adoption clock on every repository, rather than relying on a feed that may trail the fix by weeks.
Click through it at your own pace, or open it full screen.
The third demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. For a metrics owner, that means asking for findings, fixed versions and project lists in plain language while you build the per ecosystem SLA report described above.
Click through it at your own pace, or open it full screen.
To try it on your own repositories, download Safeguard and follow the CLI documentation.
Quick check
A report says Maven takes 151 days to fix vulnerabilities. Which clock is that?
In the 2025 Maven lifecycle study, 151 days is the median time for direct dependents to adopt a fix that was already released before the CVE was published. It is downstream adoption, not maintainer response. The paper also reports a 151 day mean for low severity CVEs published before a patch, a separate measurement.
Why should an SLA start at fix availability rather than at the scanner alert?
Because most npm and Maven fixes exist before the advisory, advisories trail releases by a median of 25 days in one study, and review queues can add weeks. Starting at the alert hides that exposure.
Sources
- Imtiaz, Khanom, Williams: Open or Sneaky? Fast or Slow? Light or Heavy? Investigating Security Releases of Open Source Packages (arXiv 2112.06804)
- Imtiaz et al., full text PDF
- Yang-Smith, Abdellatif: Tracing Vulnerabilities in Maven, A Study of CVE lifecycles and Dependency Networks (arXiv 2502.04621)
- Yang-Smith and Abdellatif, full text PDF
- Przymus et al.: Out of Sight, Still at Risk, The Lifecycle of Transitive Vulnerabilities in Maven (arXiv 2504.04803)
- Robinson et al.: Original Sin of npm, A Study on Vulnerability Propagation in JavaScript Dependency Networks (arXiv 2604.17668)
- Alfadel, Costa, Shihab: Empirical Analysis of Security Vulnerabilities in Python Packages
- Zerouali, Mens, Decan, De Roover: On the Impact of Security Vulnerabilities in the npm and RubyGems Dependency Networks (arXiv 2106.06747)
- Sridharkumar et al.: Detecting Protracted Vulnerabilities in Open Source Projects (arXiv 2603.27067)
- GitHub Blog: Inside the Advisory Database and what happens when vulnerability volume breaks records (29 June 2026)
- GitHub Docs: About the GitHub Advisory Database
- OpenSSF: OSV schema
- CISA: BOD 19-02, Vulnerability Remediation Requirements for Internet-Accessible Systems
Last reviewed: 23 October 2026. Study figures are as published; check the linked papers for later revisions.