On October 21, 2026, PHP released fixes for two critical remote code execution vulnerabilities, CVE-2026-109618 and CVE-2026-109619, both rated 9.2 out of 10 for severity. Details about the flaws, however, had already leaked the day before, undermining the coordinated disclosure process. The two vulnerabilities, collectively known as PHP2Shell, affected the PHP engine itself rather than any specific application. Researchers had demonstrated that code could be executed remotely, without authentication, on WordPress, Drupal and Joomla installations, under the configurations required for exploitation.

The case is particularly significant because of its timeline. AWS retrospectively identified exploitation attempts dating back to October 17, four days before the patches were released. The detections came from MadPot honeypots and did not show successful compromises of real systems, but they confirmed that the vulnerability was already the target of hostile activity before public disclosure. The problem, then, was not only how quickly systems get updated: part of the risk had materialized while administrators still had no official fix. The account published by Akamai shows how much an early disclosure can shrink the time available to respond.

That same week, Node.js shipped fixes for Node2Shell, tracked as CVE-2026-111497, a memory corruption vulnerability in the Brotli decoder developed by Google. The issue extended well beyond Node.js, affecting components used by .NET, Python, Java and other software environments. The vulnerability had been found by OpenAI researchers using Codex Security, an AI-based code analysis system.

These episodes have brought back to the center a question that has accompanied the cybersecurity debate for decades: does the public availability of source code benefit security, or does it make attackers' work easier? The recent evolution of artificial intelligence makes the question especially timely, because it significantly changes the cost and time required to find vulnerabilities.

Answering it, however, requires distinguishing the ability to discover a flaw from the ability to exploit it and, above all, from the ability to fix it. The thesis I intend to defend is that artificial intelligence has not made the open source model obsolete, but is putting a strain on the timelines and processes by which software is kept secure.

Vulnerability discovery is accelerating

Vulnerability research has historically been an activity demanding considerable expertise and time. Analyzing a complex application meant understanding its architecture, identifying attack surfaces, reconstructing execution flows and verifying the conditions needed to exploit a flaw. Even with automated tools, a substantial part of the work remained manual.

AI models are steadily lowering this cost. In 2026, for example, Anthropic's Mythos model was used to find numerous vulnerabilities in the systems of several American financial institutions, helping speed up analysis and remediation work that previously took longer. A particularly interesting aspect is the ability to correlate seemingly unrelated flaws, reconstructing attack chains that can have more serious consequences than the individual vulnerabilities considered in isolation.

This does not mean vulnerability discovery is now a solved problem. Models still produce false positives and are not always able to correctly assess the operational conditions needed to exploit a flaw. Even so, automation is making economically viable analyses that would previously have cost too much relative to the expected benefit.

This shift has particular consequences for the open source ecosystem. According to a Cloud Security Alliance study, over the course of 2026 several projects limited or suspended some vulnerability reporting channels because of the growing volume of submissions. The curl project, for instance, ended its paid bug bounty program in January, while keeping the channel for reporting security issues open. The decision was also motivated by the need to reduce the incentive to submit low-quality automated reports.

The situation is made more complex by the steady improvement of the tools. Greg Kroah-Hartman, one of the main maintainers of the Linux kernel, has observed that reports produced with the assistance of artificial intelligence are increasingly well founded. As a result, it is no longer possible to dismiss the whole phenomenon as mere automatically generated noise.

A technically correct report still requires a process of verification, fixing, testing and distribution. Every change has to be evaluated for possible regressions and compatibility with the maintained versions. In projects run by small teams of developers, often volunteers, the capacity to handle this work can become the main operational bottleneck.

An imbalance is therefore emerging between the speed at which new flaws are found and the resources available to fix them. AI can help with the latter as well, but it does not remove the need to verify that changes are correct and to take responsibility for releasing them.

Security through obscurity

The acceleration of automated research has reopened the debate on so-called security by obscurity, that is, the usefulness of restricting access to information about how a system is implemented. According to this approach, keeping the source code confidential raises the cost of finding and exploiting any vulnerabilities.

The argument is not without merit. Having the source lets a researcher directly analyze data structures, functions and execution flows, whereas software distributed only in compiled form normally requires preliminary reverse engineering. The question is how much this difference still matters for actual security.

A recent case is the vulnerability found by Wiz in GitHub's proprietary binaries using an AI-based reverse engineering assistant. The researcher explained that he had studied that target for about two years without being able to justify the investment needed to complete the analysis manually. Using AI changed the ratio between the time required and the likelihood of obtaining useful results.

An experiment published by Thales showed that, in a specific evaluation scenario, a model equipped with analysis tools managed to find eight out of ten vulnerabilities in a compiled binary in about three minutes. The result cannot be generalized to every proprietary program, but it shows how the cost of reverse engineering can fall significantly when the analysis is assisted by sufficiently capable models.

The picture is different for web applications that run their logic on the server. In these systems the attacker normally has neither the source nor the backend binaries and must reconstruct the application's behavior through the exposed interfaces. Keeping the implementation confidential can therefore be a real obstacle, especially when looking for vulnerabilities tied to business logic or authorization checks.

Even here, however, the capabilities of automated tools are growing. A study reported by Stingrai highlighted that penetration testing agents still have significant limitations compared with human researchers, while the results achieved by XBOW on HackerOne showed that automated systems can reach competitive levels in finding real vulnerabilities. The two results are not directly comparable, but they indicate that the effectiveness of automated analysis depends on the context and on the type of flaw being sought.

Moreover, some security problems in web applications require no knowledge of the source code at all. Misconfigurations, insufficient access controls and vulnerabilities in shared components can be found by observing the system's behavior. Then there are the cases where the source is accidentally exposed, such as web installations that leave .git directories, configuration files or deployment information accessible.

Keeping code confidential can therefore raise the cost of some analyses, but it is no guarantee of security. Its value depends on the type of vulnerability and on how much information an attacker can still gather by interacting with the system.

The role of shared components

The opposition between open and proprietary software becomes even less meaningful when we consider the architecture of modern applications. Code written in-house is often only a part of the software actually running in production. Runtimes, frameworks, libraries and system components form a common foundation on which different applications are built.

A vulnerability in a shared component can affect a large number of products, regardless of the license under which they are distributed. For an attacker, finding a flaw that can be reused across different systems may be more attractive than analyzing a single application.

PHP2Shell is a particularly clear example. The vulnerabilities directly affected the PHP engine and, in configurations based on mod_php, it had been shown that remote code execution could be achieved before the application logic was even processed. The problem did not stem from mistakes made by the developers of individual CMSs, but from a flaw in the underlying component, albeit under specific conditions required for exploitation.

The same problem surfaced in commercial products. In October 2026, a campaign was documented that had compromised 25 servers, exploiting PHP2Shell also through the management panels of proprietary products. Researchers suggested a link to a China-based group, though this attribution was not a definitive conclusion. The case shows that keeping application code confidential does not eliminate vulnerabilities in the components a product is built on.

Node2Shell offers a second example, particularly interesting for .NET environments. The vulnerability concerned the Brotli decoder, a native library developed by Google and embedded in several runtimes. The vulnerable component could therefore affect applications written in different languages, including those normally considered memory-safe.

It is necessary, though, to distinguish the presence of a vulnerable library from the actual possibility of exploiting it. In the case of .NET, Microsoft clarified that exposure depended on processing untrusted Brotli data through specific application paths, including ASP.NET Core request decompression, automatic decompression of HTTP responses and the System.IO.Compression APIs. The first two features are not enabled by default. Risk analysis must therefore check not only the installed version, but also whether and how the component is used.

The distinction is essential. A vulnerability may be present in software without being reachable by an attacker under the existing operating conditions. Conversely, a seemingly minor component can become a critical attack surface when it is used to process untrusted external input.

From discovery to remediation: the exposure window problem

The October cases show that publishing a patch promptly does not necessarily mean an immediate reduction in risk. The remediation process involves at least two distinct phases: the vendor's work, which must develop and distribute the update, and that of whoever runs the software, who must identify the affected systems, verify the change's compatibility and actually apply it.

A system's exposure window does not necessarily coincide with the period between the disclosure of a vulnerability and the installation of the corresponding patch. The flaw may in fact be exploited before public disclosure, as the attempts observed by AWS in the PHP2Shell case suggest. It is therefore more accurate to distinguish the overall exposure period from the unpatched window, that is, the interval during which a fix is already available but has not yet been applied.

This second window depends directly on the organization's maintenance processes. Node2Shell offers a concrete example. Node.js published its fixes on October 21, and Microsoft released out-of-band updates for .NET 8, 9 and 10 on October 25, in versions 8.0.33, 9.0.22 and 10.0.14 respectively. On October 27, CISA added the vulnerability to the Known Exploited Vulnerabilities catalog, in light of evidence of active exploitation. The vendors' work was relatively quick, but getting the fixes onto the systems actually in production required separate interventions.

The way applications are deployed can make this process more complex. In .NET, for example, applications published in self-contained mode bundle the runtime needed to run them. Updating the runtime installed on the server does not automatically change the copy included in the application, which must be rebuilt and redeployed. A similar problem affects containers and executables that directly embed specific versions of their dependencies.

Without a reliable inventory of components and their versions, an organization may consider an update complete while still running vulnerable applications. The problem is not purely technological: it concerns knowing your software estate, organizing maintenance activities and having repeatable procedures for building, verifying and deploying.

The case of out-of-support versions

The situation becomes more critical when a vulnerability affects a version that has already reached end of support. .NET 6 is a significant example. Microsoft ended support on November 12, 2024, with 6.0.36 as the last official release. According to the analysis published by HeroDevs, the Brotli vulnerability also affects this line, for which Microsoft has not issued an official fix. The later maintenance versions offered by the vendor belong to a commercial extended support service and not to Microsoft's regular update cycle.

For organizations still on .NET 6, the standard solution is to migrate to a supported version. Alternatively, extended maintenance services or temporary mitigation measures can be considered, taking the actual exposure conditions into account. Without an upgrade path, however, a vulnerability can remain unresolved indefinitely.

The issue is not limited to particularly old software. Support for .NET 8 and .NET 9 will end on November 10, 2026, even though both versions are still widely used. The length of support should therefore be factored in during development planning and not only when a critical vulnerability emerges.

In the public administration and in small organizations, it is common to find applications kept in production for many years, sometimes without significant updates because their operation is considered satisfactory. Operational continuity, however, is not the same as security. An application can keep performing its functions correctly even when the framework, runtime or libraries it depends on no longer receive fixes.

Maintenance thus takes on a structural dimension: it is not just about how quickly a single patch is applied, but about the organization's ability to keep the entire system within a sustainable technology lifecycle.

Languages, memory and dependencies: which factors affect security?

Comparisons between programming languages are often framed as rankings that try to identify the most secure platform. This approach has obvious limits, because the number of published vulnerabilities also depends on how widespread a technology is, how intense the research activity around it is and how transparent its disclosure processes are. A heavily scrutinized ecosystem can show more known vulnerabilities without necessarily being less secure.

There are, however, architectural characteristics that affect the likelihood of introducing certain categories of flaws. One of the most relevant is memory safety. Historically, a high share of Android's serious vulnerabilities has been associated with memory management errors, especially in components implemented in C and C++. Google has gradually adopted Rust for new code and in 2025 recorded a drop in vulnerabilities of this category to below 20% of the total, compared with historical values close to 70%.

The result does not allow every improvement to be attributed solely to Rust, but it provides important evidence in favor of strategies that prevent certain classes of errors through the properties of the language itself. PHP2Shell and Node2Shell concern precisely memory corruption vulnerabilities in components implemented in C. Reducing the use of memory-unsafe code can therefore structurally shrink part of the risk surface.

Choosing a memory-safe language, however, does not guarantee that the whole system has the same characteristics. PHP and Node.js use engines written mainly in C and C++, while Java and .NET normally run managed code but integrate native runtimes and libraries. Rust and Go make it possible to build most software without necessarily relying on C or C++ components, while still allowing integration with native code when needed.

Platform Memory management Native components Dependencies
Rust Memory safety in safe code Generally limited, but possible Large ecosystem of external libraries
Go Safe memory management Generally limited, but possible Rich standard library
.NET / C# Managed code, unless unsafe features are used Native runtime and libraries Rich standard library
Java Managed code JVM and native libraries Large ecosystem
Node.js Managed JavaScript code C/C++ engine and modules Very large ecosystem
PHP Managed PHP code Engine and extensions in C Variable, particularly extensive in CMSs

Qualitative comparison of architectural characteristics. The table is not a security ranking.

The table describes architectural differences and is not a security ranking. Security also depends on the quality of the implementations, on configuration, on how services are exposed and on the ability to keep dependencies up to date.

The number of packages used is not, on its own, a reliable measure of risk. A properly maintained third-party library can be more secure than an in-house function. Conversely, relying on numerous unmaintained dependencies can complicate updates and introduce vulnerabilities that are hard to identify. The main point is therefore not to indiscriminately eliminate external libraries, but to understand their role, assess their reliability and control their lifecycle.

The runtime deployment model also affects operational security. In fully managed services, some of the updates are handled by the provider, whereas in self-hosted systems the responsibility falls on the organization. Applications deployed in containers or with embedded runtimes also require specific procedures to ensure that the fix actually reaches every environment.

Technology choices can help prevent certain vulnerabilities, but they do not replace proper maintenance. An application written in Rust and abandoned for years is not necessarily more secure than a PHP application that is regularly checked and updated.

Rethinking software maintenance

The acceleration of vulnerability discovery requires us to treat maintenance as a structural component of security, rather than an activity that comes after development. The goal cannot be just to reduce the number of flaws introduced; it must include the ability to quickly assess their impact, limit the conditions for exploitation and apply fixes without compromising service continuity.

The first requirement is a reliable understanding of the components actually used in production. An inventory of dependencies, possibly backed by a Software Bill of Materials, makes it possible to identify the affected applications when a new vulnerability is published. To be useful, though, it must describe the versions actually deployed and not just those in the development repository. The difference matters most with containers, embedded runtimes and applications that are not updated together with system libraries.

On this basis, update processes must be organized so that they are verifiable and fast enough. Tools such as Dependabot and Renovate can automate the detection of new versions, but their value depends on having pipelines capable of building, testing and deploying the applications. Automation should not result in changes being applied indiscriminately, but in less manual work to produce and deploy an already verified fix.

Update speed is not, however, the only relevant factor. Reducing the attack surface, by disabling unused features and removing unnecessary services, can limit exposure even when vulnerable components are present. Node2Shell shows why this distinction matters: the presence of the Brotli decoder did not automatically mean it could be exploited, which depended on whether attacker-controlled data was actually being processed.

We must also consider the consequences of a compromise. Least privilege, service isolation, network segmentation and credential protection can prevent code execution in a single process from giving control over other systems. These measures do not eliminate the initial vulnerability, but they reduce the potential impact of the attack and the risk of lateral movement within the infrastructure.

Temporary protections can play a role during the time needed to deploy a patch, as long as they are evaluated against how the vulnerability works. A WAF can block recognizable requests, but it cannot guarantee that it will intercept content that is decompressed or processed only inside the application. In the case of Node2Shell, Datadog pointed out precisely this limitation, identifying the decoder update as the real fix. Blocking Brotli traffic may be a specific mitigation, but it is not equivalent to fixing the component.

Finally, artificial intelligence can be used to improve the defensive process itself. Continuous code analysis, dependency checks and support for verifying patches are activities where models can significantly reduce the work required. Integrating them into development processes must, however, include checks on the quality of the results, since a reported vulnerability is not necessarily exploitable and a suggested fix is not automatically correct.

In this scenario, security through obscurity also keeps a role, but a limited and complementary one. Avoiding the exposure of configurations, unnecessary versions, repositories and implementation details can raise the cost of an attack. It cannot, however, make up for the use of vulnerable components or the lack of a reliable maintenance process.

Conclusions

Artificial intelligence is changing the relationship between discovering and fixing vulnerabilities. The availability of tools capable of analyzing large amounts of code and assisting reverse engineering reduces some of the costs that historically limited the search for flaws. This change affects both open and proprietary software, albeit in different ways.

Access to the source can make it easier to analyze an open source project, but it also enables independent verification and contributions to fixes that do not depend solely on the vendor. Proprietary software can maintain an informational barrier, especially in server-side applications, but this protection loses effectiveness when the attack targets shared components or vulnerabilities that can be found by observing the system's behavior.

The PHP2Shell and Node2Shell cases also show that risk does not depend only on the publication of information. Exploitation attempts can precede official disclosure, while fixes can reach production environments with significant delays. In out-of-support systems, the lack of a regular upgrade path can make this problem permanent.

It follows that the ability to keep software up to date carries growing weight compared with the mere confidentiality of the implementation. Security depends on knowing which components are in use, reducing the attack surface, isolating systems and being able to deploy fixes quickly. Choosing the language and adopting memory-safe technologies can reduce certain categories of vulnerabilities, but they do not eliminate the need for continuous maintenance.

So it is not open source that has become unsustainable. What is being called into question is a management model in which updating software can be put off indefinitely as long as the application keeps working. Artificial intelligence is shortening the time needed to find and exploit some flaws; maintenance processes must evolve accordingly.

The decisive distinction is not between open and closed code, but between systems for which there is a real capacity to control and update them and systems that remain in service without proper management of their dependencies. In this sense, AI has not killed open source: it has drastically reduced the time we can afford to spend on updates.


Sources and further reading