Open Reach Tech Inc.

Is PHP Really the Most Vulnerable Language? What the Correlation Between Vulnerability Counts and Adoption Says

Portrait of Jiro Yamamoto
Jiro YamamotoBackend Developer

The claim that PHP has a lot of vulnerabilities is common, but discovery counts grow with adoption. We counted the GitHub Advisory Database ourselves, regressed the counts on package counts and developer usage, added severity (critical share), the CVEs of each language's own runtime, nine years of history, and WordPress as a second denominator, to find out what really drives the gap between languages.

Banner of Is PHP Really the Most Vulnerable Language? What the Correlation Between Vulnerability Counts and Adoption Says

Is PHP Really the Most Vulnerable Language? What the Correlation Between Vulnerability Counts and Adoption Says

"PHP is a language with a lot of vulnerabilities" comes up in almost every technology-selection discussion. But the number of vulnerabilities discovered grows with how much code exists in a language and how many people are looking at it. Does a high discovery count really mean "dangerous as a language"? We correlated the counts with adoption, looked at where the residual (the part adoption cannot explain) lands, and then asked what changes when we weigh severity instead of counts and look at the runtimes themselves.

The figures in this article were collected from data published as of 28 October 2026. Vulnerability databases grow every day, so read the rankings, ratios and correlations rather than the absolute numbers. The counting method is summarized at the end.

1. There is no official statistic for "vulnerabilities by language"

The first thing to know is that a CVE (Common Vulnerabilities and Exposures record) has no "language" field. About 48,000 CVEs were published in 2025, a record, but no official statistic assigns them to languages. Talking about languages means choosing a proxy, and the choice decides the conclusion.

When Mend (formerly WhiteSource) tallied ten years of open source vulnerabilities in its own database, C accounted for more than 50% of the total and PHP ranked second of the seven languages studied. The 2019 breakdown was C 47%, PHP 17%, Java 11%, JavaScript 10%, Python and C++ 5% each, and Ruby 4%. C stands out because the huge, long-lived projects, operating systems, browsers and runtimes, are almost all written in C. Vulnerabilities in the PHP interpreter itself are counted as C memory-safety bugs. "Vulnerabilities in PHP" and "vulnerabilities in applications written in PHP" are already two different things. This article covers the former in Section 4 and the latter everywhere else.

The most direct way to compare languages is per package registry. Figure 1 counts the reviewed advisories in the GitHub Advisory Database (those whose content and affected range GitHub staff have confirmed) directly from its public repository and lines them up by ecosystem.

Cumulatively, npm (JavaScript) leads with 7,992 advisories, followed by Maven (Java), pip (Python) and Composer (PHP) in the 6,500 to 7,200 range. In this view PHP is fourth. Cut out the single year 2025, though, and GitHub's own figures put Maven at 22.2%, Composer 19.4%, Go 17.3%, pip 17.2% and npm 14.9%. Go sits six points above its all-time share (10.9%) because GitHub ran a campaign to backfill missing Go advisories. Even with the same counting method, a single year's ranking moves depending on who reviewed what intensively.

2. Correlating counts with adoption

2.1 Why correlation rather than division

Discovery counts grow with the denominator. The usual move is to divide by adoption and report "per package" or "per percent of developers," but that assumes counts are directly proportional to adoption. A log-log regression lets the data answer whether that is true (whether the slope is 1).

The regression line is a prediction: "with this much adoption, expect about this many advisories." The amount by which the actual count departs from that prediction is the residual, which this article expresses as a ratio ("how many times the prediction"). The larger the residual, the more is going on that adoption cannot explain.

2.2 Against registered packages

Figure 2 plots the Figure 1 counts against the number of packages in each registry as counted by ecosyste.ms (npm about 6.02 million, Go about 2.54 million, pip about 950,000, NuGet about 870,000, Maven about 740,000, Composer about 530,000, crates.io about 370,000, RubyGems about 210,000), both on log scales.

The slope of the regression is 0.48, well below 1. Ten times the packages brings only about three times the advisories. Most of npm's six million packages are small utilities, and the density of vulnerabilities per package thins out as a registry grows. R² is 0.36, so package count explains only about a third of the variation.

The rest is residual. Composer (PHP) sits at 2.4 times the regression line, Maven (Java) at 2.2 times and pip (Python) at 1.8 times, while NuGet (C#) is at 0.3 times and RubyGems at 0.6 times.

2.3 Against developer usage

Figure 3 swaps the denominator for the share of developers who used each language in the past year, from the Stack Overflow Developer Survey 2025 (31,771 respondents): JavaScript 66.0%, Python 57.9%, Java 29.4%, C# 27.8%, PHP 18.9%, Go 16.4%, Rust 14.8%, Ruby 6.4%.

The slope is 0.73 and R² is 0.42, a slightly better fit than package count. Here too Composer (PHP) is the highest point at 2.1 times the line, followed by Go at 1.8 and Maven (Java) at 1.7. npm and pip sit on the line (1.0), and NuGet is at 0.3.

2.4 Residuals under both denominators

EcosystemRatio to line (packages)Ratio to line (usage)Reading
Composer (PHP)×2.4×2.1Highest under both denominators
Maven (Java)×2.2×1.7Right next to PHP
pip (Python)×1.8×1.0High for its package count, in line with its developer count
Go×0.8×1.8Verdict depends on the denominator
npm (JavaScript)×0.9×1.0As adoption predicts
RubyGems (Ruby)×0.6×0.8Slightly low
crates.io (Rust)×0.7×0.6Low
NuGet (C#)×0.3×0.3Lowest under both denominators

The first half of the conclusion is this. After removing the correlation with adoption, PHP (Composer) keeps the largest residual under both denominators. "It only looks high because it is popular" does not hold. But PHP is not alone at the top: Java (Maven) is always right next to it. Conversely, JavaScript, which had the most raw advisories, lands exactly where adoption predicts under both denominators.

With only eight points, read these correlations as descriptive guides, not statistical tests. Change the denominator and the ratios move (Go is the textbook case). Still, the same two ecosystems staying on top under two independent denominators is hard to put down to chance.

2.5 Adding severity as an axis

So far every advisory has counted as one. But an XSS and an arbitrary code execution mean very different things. The GitHub Advisory Database rates each advisory as Critical, High, Moderate or Low (based on CVSS), and Figure 6 shows the mix.

Composer (PHP) has 10.0% critical and 38.9% critical plus high, the lowest of the eight ecosystems. npm has the highest critical share at 18.3%, followed by Maven and crates.io at 13.3% and pip at 12.4%. XSS, which makes up a third of PHP's count, is mostly rated Moderate, so PHP has many advisories but a low proportion of severe ones.

Re-running the regressions of Sections 2.2 and 2.3 on critical advisories alone changes the order.

EcosystemCritical advisoriesRatio to line (packages)Ratio to line (usage)
Maven (Java)960×2.6×1.9
Composer (PHP)657×2.1×1.9
pip (Python)834×1.9×0.9
npm (JavaScript)1,464×1.2×1.5
Go570×0.7×1.9
crates.io (Rust)215×0.9×0.8
RubyGems (Ruby)133×0.7×1.0
NuGet (C#)72×0.2×0.2

Restricted to critical advisories, the residual against package count puts Maven (Java) first at 2.6 times and PHP second at 2.1. Against developer usage, Maven, PHP and Go tie at 1.9. npm had one year, 2020, with 549 critical advisories (advisories originating from npm at the time tended to carry high CVSS scores), which lifts it slightly above the line on critical counts.

So "PHP has a lot of vulnerabilities" is right on counts, and on severe ones PHP ties with or trails Java. PHP's residual is "many, but mostly minor"; Java's is "slightly fewer, but heavier." If risk is measured as severity times count rather than count alone, the case for singling out PHP weakens.

3. Over time: usage falls, counts rise

Cross-sectional comparison keeps one bias: older ecosystems have larger cumulative counts. So Figure 4 takes each ecosystem's advisories per year (by CVE-id year) and each year's usage share from the Stack Overflow survey, and indexes both to 2017 = 100.

PHP's usage share fell by a third, from 28.1% in 2017 to 18.9% in 2025, while its advisories rose 2.6 times, from 214 to 561 (989 in 2024). The correlation between the two is −0.89, a strong inverse correlation. Java is the same: usage keeps falling and counts keep rising (r = −0.66). Python and Go, on the other hand, grow on both axes, so their correlation is positive (r = 0.89 and 0.95).

What the four languages share is that counts rise whichever way usage moves. If usage drove counts, PHP's and Java's would have fallen. They did not, so the main force behind counts lies elsewhere: the accumulated stock of existing code, the activity of reporters, and the improving tools used to hunt for bugs.

Supporting that reading, by the end of October 2026 every one of the eight ecosystems we counted had already set an all-time annual record (npm 3,535, pip 2,439, Go 2,163, Composer 1,432, Maven 943). The same holds for critical advisories alone: npm 404, pip 273 and Go 267 are all records. Developer usage did not double for every language in one year. The natural explanation is change on the reporting side, such as GitHub's re-review work and the spread of AI-assisted vulnerability hunting. Separating those causes needs its own analysis, but the yearly trend confirms the point: counts strongly reflect the activity of the people reporting.

4. Vulnerabilities in the language itself: runtime CVEs

Everything so far has been about libraries written in each language. To answer whether the language itself is vulnerable, we need the CVEs of the runtime: the interpreter, compiler, standard library and virtual machine. The table below pulls from the NVD (the US National Vulnerability Database) every CVE whose affected product is one of these runtimes.

RuntimeCumulative CVEsFirst yearCritical shareCritical + High sharePer year, 2021 to 2023
PHP760199717.6%54.2%7.7
Java (Oracle JDK + OpenJDK)83320074.8%39.6%26.0
.NET (.NET / .NET Core / .NET Framework / ASP.NET Core)33820023.3%77.8%21.3
Node.js18820139.6%66.0%18.0
Go174201410.9%69.5%28.0
Python (CPython)145200211.7%50.3%10.3
Ruby112200712.5%57.1%4.7
Rust24201829.2%75.0%5.0

Cumulatively, PHP's 760 stands out alongside Java's 833: five times Python and four times Node.js. But that number reflects the length of the history as much as anything. Figure 7 shows the PHP interpreter's CVEs by year.

The PHP interpreter's CVEs peak in 2007 (114) and 2016 (120). 2007 was the year of the "Month of PHP Bugs," when researchers published PHP vulnerabilities daily for a month. 2016 was when fuzzing (automated input generation) spread and out-of-bounds reads and writes in C-written parsers such as unserialize and image handling were found in bulk. In the PHP 7 and 8 era, 2021 to 2023 saw seven to eight CVEs a year, fewer than Node.js (18), Go (28), Java (26) or .NET (21) over the same period. Judged by the runtime alone, recent PHP is not "the language with many vulnerabilities"; it is among the quieter ones.

The severity distribution runs the other way. 17.6% of the PHP interpreter's CVEs are critical, the highest share of any runtime with more than 100 CVEs, and the top weakness classes are out-of-bounds write (CWE-119) and out-of-bounds read (CWE-125). Because the PHP interpreter is written in C, what gets found are memory-safety bugs, each far heavier than a library's XSS. Java and .NET have critical shares under 5% for two reasons: large parts of their runtimes are written in memory-safe languages, and their quarterly patch cycles issue many low- and medium-severity CVEs.

Three caveats apply to this table. First, the NVD's product tagging (CPE) has fallen behind since 2024 because of processing delays on the NVD side, so counts for 2024 onward are understated for every runtime; that is why the per-year average uses 2021 to 2023. Second, Java's 833 includes the many low-severity CVEs that Oracle's quarterly patches generate, and Rust's 24 covers only the compiler and standard library (in Rust, memory-safety issues are mostly reported against crates). Third, runtime CVEs are vulnerabilities in the C and C++ code that runs the language, not in code written in the language, which is exactly the distinction from Section 1.

5. WordPress, the other denominator

Figures 1 to 4 are about libraries registered on Composer (Packagist). Yet most of the PHP vulnerabilities that make the news are WordPress plugins and themes, and those barely appear on Packagist or in the GitHub Advisory Database.

W3Techs finds that about 70% of websites with a detectable server-side language run PHP, and that WordPress runs 39.5% of all websites and 58.3% of sites with a detectable CMS (as of 28 October 2026). More than half of "PHP sites in the world" are WordPress.

According to the annual report from Patchstack, a WordPress security company, 11,334 new vulnerabilities were reported in the WordPress ecosystem in 2025, up 42% from 7,966 the year before. 91% were in plugins and 9% in themes; WordPress core had six, all low risk. 46% had no fix from the developer at the time of disclosure.

Figure 5 puts this on the same footing as Figure 2: vulnerabilities reported in the single year 2025 per 1,000 registered packages (for WordPress, the roughly 76,000 plugins in the official directory).

Composer has 1.07 per 1,000 packages, Maven 0.93, npm 0.11. WordPress plugins have 135.7, about 127 times Composer and more than 1,000 times npm. The gap is so large that the other ecosystems vanish without a log axis.

The mix of weaknesses also differs from Composer. In Patchstack's first-half 2025 tally, XSS was 34.7%, CSRF 19.0%, local file inclusion 12.6%, broken access control 10.9% and SQL injection 7.2%, with the top five making up about 85%. 57.6% could be exploited without authentication and 20.6% with contributor-level access. On severity, 17% of the 2025 total were rated High by Patchstack, meaning likely to be used in mass automated attacks. CSRF and broken access control ranking that high shows how many extensions skip permission checks on top of WordPress's own capability model and hook system.

Most of the impression that "PHP has a lot of vulnerabilities" comes not from the language, nor from WordPress core, but from this one enormous plugin economy. The gap between Composer's residual in Figures 2 and 3 (a little over 2×) and the 100×-plus of WordPress plugins is the difference in who writes the code and under what mechanism, on the same language.

6. Four factors behind the residual

From the data so far, we group the causes of the gap that adoption cannot explain into four factors.

6.1 The kind of vulnerability differs by language

These are the weakness classifications (CWE) attached to GitHub advisories, from our own count.

EcosystemMost common weaknessShareSecond most commonShare
Composer (PHP)Cross-site scripting (XSS)31.2%SQL injection5.6%
RubyGems (Ruby)XSS17.3%Uncontrolled resource consumption6.6%
Maven (Java)XSS13.5%Unsafe deserialization5.8%
npm (JavaScript)XSS11.8%Prototype pollution7.1%
pip (Python)Path traversal8.1%XSS7.6%
GoIncorrect authorization7.4%Path traversal7.3%
NuGet (C#)Out-of-bounds write17.8%XSS9.4%
crates.io (Rust)Race condition5.3%Use after free4.5%

In PHP, XSS makes up almost a third of advisories, higher than any other ecosystem. XSS and SQL injection are first and second in MITRE's 2025 Top 25 Most Dangerous Software Weaknesses, so PHP's vulnerabilities are heavily skewed toward "classic web weaknesses." The finding in Section 2.5 that PHP has the lowest critical share is the flip side of this XSS dominance.

This is not unrelated to language design. PHP was born as a language embedded in HTML, and echo prints a variable as-is. A structure that leaves output escaping to developer discipline produces more XSS as more people write in it. Template engines such as Laravel's Blade and Symfony's Twig escape by default, so the same accidents are much harder to have on a modern framework. The problem is that the WordPress plugin culture exists outside those rails.

NuGet's top weakness being out-of-bounds write shows that vulnerabilities in native code bundled with C# libraries are being counted, a reminder that "the package's language" and "the vulnerability's language" do not always match.

6.2 The ecosystems have different kinds of authors

Packagist and WordPress have low barriers to entry, and extensions written by individuals or small vendors run on sites around the world as-is. Patchstack reports that premium (paid) components are less scrutinized because researchers cannot easily obtain the code, and that they had three times as many actively exploited vulnerabilities as free ones. Vulnerabilities survive where review does not reach, and one day they are found all at once.

The same reasoning explains why Java's Maven is always next to PHP, and ahead of it on critical advisories. Maven concentrates large enterprise frameworks and middleware (application servers, build tools, logging libraries), and its advisories per package are among the highest of any ecosystem. Many are deserialization flaws that lead straight to code execution, so each one weighs more. This is the opposite of npm's "millions of one-function packages," and one reason the slope in Figure 2 stops at 0.48.

6.3 How many people are looking, and how they report

A vulnerability only gets counted when someone finds it. WordPress has several companies, such as Patchstack and Wordfence, running bug bounties, and researchers scan plugins mechanically. Patchstack itself says that AI-generated low-quality reports surged in 2025 and raised the triage burden. Add the six-point swing in Go's 2025 share from GitHub's backfill, the all-time records in every ecosystem in 2026 (Section 3), and the 120 PHP interpreter CVEs found in a single year when fuzzing spread in 2016 (Section 4), and report counts reflect the activity of the reporters about as much as the amount of vulnerabilities.

6.4 How fast things get fixed

Veracode's "State of Software Security 2025" gives, per language, the time from discovery until half of the flaws are fixed (the half-life).

Language20% fixed50% fixed (half-life)80% fixed
Python9 days116 days640 days
JavaScript14 days163 days730 days
.NET22 days198 days849 days
PHP31 days227 days800 days
C++39 days245 days891 days
Java30 days276 days1,111 days

PHP's half-life of 227 days is mid-table: faster than Java and C++, slower than Python and JavaScript. Java, which matches PHP in residual, is also the slowest to fix, consistent with the view in 6.2 that Maven holds a lot of large enterprise software.

On memory safety, C and C++ taking half of Mend's tally is the one clear case where language design itself is the cause. Google reports that after steering new Android code toward memory-safe languages, the share of memory-safety issues among vulnerabilities fell from 76% in 2019 to 24% in 2024. PHP, Java, Python and JavaScript are all memory-safe, so for library vulnerabilities this axis is level. Where memory safety does bite is the runtime story of Section 4, which is where the weight of the PHP interpreter's CVEs comes from.

7. What to change on the ground

These are the three implications we draw from the data.

1. Change the rails, not the language. Writing in PHP is not dangerous in itself. What is dangerous is leaving escaping and query construction to manual work. On a template engine that escapes by default and an ORM that enforces prepared statements, most of the XSS and SQL injection that make up over a third of PHP advisories disappear structurally. This is the same defense-in-depth idea we wrote about in our SQL injection article.

2. Look at the number of dependencies and who wrote them. 91% of WordPress vulnerabilities are in plugins, and 46% have no fix at disclosure. Installing a plugin means running unreviewed code with the site's privileges. Taking inventory of plugins and removing the ones that have stopped receiving updates comes before any language decision.

3. Measure severity times fix speed, not counts. As Section 2.5 showed, having many advisories and having many severe ones are not the same. In Veracode's data, high severity shortens the fix time by only about a month. As Section 3 showed, report counts will keep rising with reporter activity. Critical vulnerabilities left open after discovery decide risk more than the discovery count does. We recommend tracking, per severity, the number of days from a dependency vulnerability notification to the fix reaching production.

Summary

  • There is no official statistic for "vulnerabilities by language," and the ranking changes with the proxy you choose. In raw cumulative counts npm (JavaScript) leads and PHP is fourth.
  • Counts are not proportional to adoption. In log-log regression the slope is 0.48 against package count and 0.73 against developer usage; adoption explains less than 40% of the variation.
  • After removing the correlation, PHP (Composer) keeps the largest residual under both denominators (2.1 to 2.4×), with Java (Maven) always beside it. JavaScript is where adoption predicts, and C# is the lowest.
  • Severity changes the order. PHP has the lowest critical share of the eight ecosystems (10.0%), and on critical counts Java's residual exceeds PHP's. PHP is "many, mostly minor"; Java is "slightly fewer, heavier."
  • For the runtime itself, the PHP interpreter's cumulative 760 CVEs are among the most, but in 2021 to 2023 it had seven to eight a year, fewer than Node.js, Go, Java or .NET. Its critical share (17.6%) is the highest among runtimes, driven by memory-safety bugs in C-written parsers.
  • Over time, PHP's usage fell by a third while its counts rose 2.6× (r = −0.89). Counts rose in every language regardless of usage, so the main driver is reporter activity.
  • WordPress plugins had 136 vulnerabilities per 1,000 plugins in 2025 alone, about 127 times Composer. Most of the impression that "PHP has a lot of vulnerabilities" comes from here.
  • The residual is explained less by the language than by (1) a weakness mix skewed toward XSS, (2) a plugin economy with a low barrier to entry, (3) the activity of reporters, and (4) fix speed.

Method and references

  • Advisory counts were taken from the public repository of the GitHub Advisory Database (github/advisory-database, commit 45f4266, 28 October 2026): the 37,293 files under github-reviewed, counted by affected[].package.ecosystem. An advisory spanning several ecosystems is counted once in each. Yearly counts use the CVE-id year (or the publication year when there is no CVE id) rather than GitHub's publication date, to avoid the year shifts caused by GitHub's bulk reviews. Weakness types are counted from database_specific.cwe_ids and severity from database_specific.severity (Critical / High / Moderate / Low).
  • Package counts are from packages.ecosyste.ms per registry (28 October 2026). Developer usage is the "all respondents" value of the Stack Overflow Developer Survey, 2017 to 2025. Regressions are least-squares on log10 values; correlations are Pearson's r.
  • Runtime CVEs were fetched from the NVD API (virtualMatchString set to each product's CPE, such as cpe:2.3:a:php:php, on 28 October 2026), deduplicated by CVE id, and tallied by publication year and CVSS severity (NVD's primary rating, preferring v4.0, then v3.1, v3.0, v2). Java combines oracle:jdk and oracle:openjdk; .NET combines microsoft:.net, .net_core, .net_framework and asp.net_core. NVD's CPE tagging has lagged since 2024, so counts from 2024 onward are understated.
  • WordPress counts come from Patchstack's annual and mid-year reports; the plugin count (about 76,000) is a third-party tally of the official directory as of October 2026. Premium plugins are not in that denominator, so WordPress's density is slightly overstated.

References (all retrieved in late October 2026):

Message Sent!

Thank you for reaching out! Our team will contact you within 24-72 hours.