In May 2026, OpenAI began testing an internal research model against a cybersecurity benchmark called ExploitGym. While the test environment was not supposed to have access to the open internet, there was, however, one narrow path out because the agents still needed a way to install software: an internally hosted Artifactory server that acted as a cache for package downloads. That pathway turned out to be enough for the model’s agents to eventually circumvent the test’s rules and escape confinement.
On May 26, according to details OpenAI later presented at Black Hat, one of the agents found a previously unknown way through Artifactory. After initially exploiting this vector, it left information about what it found behind for the next agent. Other agents found the note and began leaving their own, until the shared package repository had effectively become a message board where agents exchanged vulnerabilities and divided up work. In early July, they hit Artifactory hard enough to knock the service over, leading to OpenAI’s investigation. They cleared the board, fixed the path the agents had found, and resumed testing, but two days later, the agents rebuilt the message board using a different method and continued their escape plan.
The next stage of the process is what made headlines: the agents found a path to the internet and eventually reached Hugging Face, the largest public host of AI models and datasets. Hugging Face later reconstructed about 17,600 actions across a four-and-a-half-day campaign and determined that an agent found an outside code-running service it could use as a launch point. From this initial foothold, the agent exploited a data processing bug to read local files, leading it to discover a template injection bug to run Python inside a production worker to gain code execution. From there, it followed a fairly normal post-compromise sequence: steal credentials, map Kubernetes permissions, query cloud metadata, move laterally, and keep testing paths until enough of them worked.
The unusual part of the incident was the volume and persistence of the attempts, and the fact that the agents would keep trying different approaches until something worked. Most of the roughly 17,600 actions Hugging Face reconstructed were unsuccessful, but those failures did not slow the process down very much because an agent could simply move on to another approach, start again in a fresh environment, return to an earlier idea, or build on something another agent had already discovered.
The vulnerabilities themselves were mostly familiar types of security problems, but the agents were able to test far more possibilities and do it much faster than a human team realistically could. This speed and scale also helps explain why describing the incident as an AI that “escaped a sandbox” can be misleading. The sandbox itself did not have a direct connection to the internet, but it relied on a package service that did, and the agents were able to exploit a vulnerability in that service to get around the restriction. The security control was technically in place, but one of the systems allowed to cross its boundary still provided a path to the outside, showing that isolation only works when every service connected to the environment is treated as part of the same security boundary.
The capabilities of these models have continued advancing as well. On August 7, OpenAI announced that an upcoming model called Astra had become capable enough that the company could no longer rule out it reaching its “Critical” cybersecurity threshold. OpenAI defines that level as the ability to develop zero-day exploits against hardened real-world systems or carry out an unfamiliar attack from a high-level objective through completion without a person directing each step. GPT-5.6 Sol, which was one of the models used in the Hugging Face evaluation, is currently rated one level below that at “High.” Astra was not involved in the Hugging Face incident, but its capabilities show how quickly the technology has continued progressing since then.
Anthropic has been seeing the same trend from a different side of cybersecurity research. Through an initiative called Project Glasswing, the company gave access to its top model (at the time), Claude Mythos Preview, to roughly fifty organizations responsible for important consumer and business software for testing. Anthropic has reported that, as a result, the program identified more than 10,000 high or critical severity vulnerabilities during its initial phase. Access is now being expanded to roughly 150 additional organizations. Claude Mythos and Project Glasswing have marked an important shift, in that Anthropic says vulnerability discovery has become fast enough that triage and remediation are increasingly the bottleneck.
The experiment I ran operated on a much smaller scale than the research programs conducted by OpenAI and Anthropic, but that also helped define the methodology. I kept the investigation under human control and built a sealed offline lab. The rule throughout the project was that AI could flag suspicious code and suggest possible vulnerabilities, while my job was to independently reproduce anything that was flagged before treating it as a finding.
For the AI-assisted portion of the research, I used Claude Opus 4.8. Anthropic has since released more capable fifth-generation models, including Fable 5 and Opus 5, but those models also introduced stronger cybersecurity safeguards. Opus 5 can still perform source-code vulnerability analysis, although Anthropic blocks some categories of security work, including penetration testing and exploit generation, and automatically routes flagged requests back to Opus 4.8.
Fable 5 is even more restrictive, and refuses to work on anything related to cybersecurity. Opus 4.8 was therefore a good fit for this project because it could review plugins containing tens of thousands of lines of code, map important entry points and data flows, and help identify areas that deserved closer inspection without the newer rules interrupting legitimate parts of the research.
The research also focused on a part of the WordPress ecosystem that receives much less attention than major plugins such as Yoast or WooCommerce. Many sites rely on smaller plugins maintained by only one or a few developers. Some of these plugins are installed on thousands of sites, and sometimes left without significant updates for years. These plugins can still handle sensitive data and control important website functions while receiving far less time spent on security review.
I reviewed dozens of these plugins inside my isolated lab, looking specifically for vulnerabilities that had not already been reported. The most common failures involved ordinary security controls that looked correct in the source and broke under testing.
In some cases, a sanitizer simply returned the original input unchanged. In others, an authorization check confirmed that a user belonged to a group but never verified ownership of the specific object being requested. The illusion of a security control was there, but the protection itself was incomplete or not fully implemented.
This article focuses on those kinds of failures and on the process I used to identify and verify them. It explains how the lab was designed, how plugins were selected, how AI assisted with the analysis, and how suspicious code was separated from vulnerabilities that could actually be reproduced. The specific plugins and proof-of-concepts are reserved for Part 2, after maintainers have had an opportunity to fix the affected software.
The method depends on being able to separate behavior caused by the plugin from behavior that would have happened anyway. If I cannot make that distinction, then the result is not reliable enough to count as a finding.
To do that, I built two WordPress sites that are nearly identical except for one intentional difference: the control site stays clean and fully patched, while the research site is where I install the candidate plugin. Fake data was created as necessary for normal plugin functionality, and was treated as disposable throughout the testing process.
Both sites run on localhost without direct internet access and use separate databases on separate private networks. This prevents a plugin on the research site from affecting the control site’s data or environment. Because the tested plugin is the only intended difference between the two sites, behavior that appears only on the research site can be tied to that plugin with much greater confidence.
The OpenAI incident reinforced why this kind of isolation matters. The agents began without normal internet access, though they could still reach a package cache so the environment could obtain software. After finding a vulnerability in that service, the agents were able to use the exception as a route outside the sandbox, showing that an environment is only as isolated as the services allowed to cross its boundary.
My lab uses a more controlled network design. Claude still requires internet access to operate, but the WordPress environment itself is confined to an internal network and is not directly exposed to the internet. The research and control sites are bound to localhost, isolated from each other, and restored to a known state before each test. This allows Claude to assist with the analysis while keeping the systems under examination inside a controlled environment with no direct external access.
Snapshots provide the other part of that control process. Before installing a plugin, I save a named snapshot of the research site’s database and files. I then install the plugin, create another snapshot, perform the test, and restore the original baseline before moving to the next candidate. Every confirmed finding has to reproduce from a clean snapshot, which helps distinguish an actual vulnerability from behavior caused by leftover configuration, previous tests, or other environmental changes.
A note on reproducibility: A useful finding should be reproducible from a known, clean starting point so that someone else can verify the same behavior independently. The purpose of a properly built lab and well-run experiment is to determine whether that code produces a real, repeatable vulnerability under controlled conditions, and not to just identify suspicious code.
Since reviewing every WordPress plugin is not realistic, target selection became an important part of the process. Popular plugins with serious published CVEs tend to receive substantial attention and are often patched quickly, so I focused instead on smaller or less actively maintained plugins where an undiscovered vulnerability was more likely to remain.
To make that process easier, I created VulnPlugs, a WordPress plugin research dashboard that organizes plugin data so candidates can be compared by factors such as install count, maintenance history, known vulnerabilities, and overall risk. I originally built the site specifically for this experiment because manually comparing thousands of plugins across several different sources was inefficient. It remains live for anyone who wants to use the same information to help identify and prioritize plugins for similar research.
A few factors became particularly useful when choosing targets:
Each candidate was then scored based on potential severity, how easily the affected functionality could be reached, whether the issue existed in a default installation, whether it appeared to be previously unreported, and how clearly the root cause could be explained. VulnPlugs helped narrow the initial field, while the final decision to investigate a plugin still depended on reviewing its current state and source code.
Most of the vulnerabilities I found followed the same basic pattern:
A value the attacker controls reaches an operation that has consequences, while the security check that should exist between those two points is missing, incorrect, or ineffective.
An attacker-controlled value can be something as simple as a form field, URL parameter, or HTTP header. The operation it eventually reaches, often called the sink, might be a database query, file write, email send, or output rendered into a page. The security control between them is supposed to answer two questions: is this user allowed to perform the action, and is this input safe to use in this context?
My review process followed that path from both directions. From the outside, I tested the site as different types of users, documented available endpoints, and noted which roles could access them. From the source code, I identified entry points and followed attacker-controlled data until it reached a sensitive operation. The most interesting findings usually appeared when a security check existed, but did not actually enforce what the developer appeared to intend.
A nonce should not be treated as a permission check. A nonce helps prevent cross-site request forgery, but it does not prove who a user is or whether that user is authorized to perform an action. I found nonces exposed directly in public HTML, shared across an entire site, and even commented out in shipped code. A valid nonce only answers whether a request contains the expected token. The application still needs to determine who the user is and whether that user is allowed to perform the requested action.
Use context-appropriate sanitization. More than once, I found functions whose names suggested that they cleaned input but either returned the value unchanged or sanitized it for the wrong purpose. WordPress’s sanitize_text_field(), for example, is useful for cleaning text intended for display, but it does not make a value safe to insert directly into an SQL query.
Decoded input remains attacker-controlled. One plugin used a reversible cipher to protect a sensitive value and then treated the decoded result as trustworthy. If the attacker controls the original value, scrambling and later decoding it does not make that value any more reliable.
Establish identity from server-side state. I found cases where an X-Forwarded-For header was accepted as the visitor’s real IP address and where a user ID supplied in a request was treated as proof of ownership. In both cases, the application trusted information the client could modify. Identity and ownership decisions need to come from trusted server-side state rather than values supplied by the request itself.
Object access should require its own authorization check. This was one of the most common patterns I found. An endpoint might verify that a user is a subscriber or has permission to read courses, then allow that user to request an object belonging to someone else without checking ownership. The broad permission check is valid, but incomplete. Access to an individual record still needs to be tied to the user who is requesting it.
Access tokens require secure randomness. Some plugins protected private pages with supposedly secret links generated from predictable values. PHP’s uniqid(), for example, is largely based on time and should not be treated as a secure random token. A private link is only meaningful if the token behind it is generated with a cryptographically secure source of randomness.
None of these patterns require an especially unusual exploit technique. What makes them easy to miss is that the code often contains something that looks like a security control at first glance, so during review, I traced each check through the code to determine exactly what condition it enforced. This step went a long way to weed out false positives and helped separate code that seemed problematic at first from code that was actually vulnerable.
One of the most important parts of the project was separating vulnerable-looking code from something that’s actually exploitable when the software is running. If the goal is to produce findings that other people can trust, the suspected vulnerability has to survive direct testing.
The clearest example was a SQL injection that initially appeared straightforward: an unauthenticated handler accepted a value, passed it through a display-oriented sanitizer that left quotation marks intact, and inserted it into a database query without parameterization. Based on the source code alone, it looked like a serious vulnerability. In the lab, however, a time-based payload that should have delayed the response produced no delay at all, even though the equivalent query worked exactly as expected when run directly against the database.
The reason was WordPress’s handling of incoming request data. WordPress automatically adds backslashes to request values as a legacy behavior, and developers normally remove them with wp_unslash() before using the data. This plugin failed to remove those slashes, which meant the attacker’s quotation mark remained escaped and prevented the injection from working. The query was still constructed incorrectly, but one programming mistake happened to interfere with another. Ironically, adding the normally appropriate wp_unslash() without also parameterizing the query could make the vulnerability exploitable. The correct fix is to use a parameterized query.
I encountered the same distinction several more times during the research process:
These results were useful because they showed why the severity assigned during source review or in an advisory should not be treated as proof of actual impact. Sometimes another behavior in the application prevents an otherwise valid-looking exploit from working. Runtime testing settled each of those cases, so if a candidate failed to reproduce from a clean snapshot, I did not count it as exploitable.
Claude Opus 4.8 handled a significant portion of the initial source review, but the project also showed where AI-assisted analysis still needs careful verification. Its main advantage was breadth, and on a plugin with tens of thousands of lines of code, Claude could identify likely entry points, trace possible data flows from user-controlled input to sensitive operations, and help divide the codebase into smaller sections for manual review. That reduced the amount of time spent searching through files and allowed more attention to be spent validating the areas that appeared important.
The main weakness was confidence. Claude occasionally described security controls that were not actually present, including one handler it said was protected by a permission check that did not exist in the source. It also treated the SQL injection discussed earlier as highly likely to be exploitable, even though runtime testing showed otherwise. During a deserialization review, an AI-assisted scan identified what appeared to be a usable gadget in WordPress core, but manual review showed that the code path could never execute. In each case, the analysis was clear and convincing, but the conclusion was wrong.
A similar problem appeared during Hugging Face’s investigation of the OpenAI agent intrusion. Hugging Face used AI to investigate the large number of actions and encoded artifacts involved in the incident because reconstructing everything manually would have been difficult. The first Claude models used in that process refused portions of the reverse engineering work because their security safeguards interpreted the analysis as too close to performing the attack itself. Hugging Face eventually ran GLM-5.2 on its own infrastructure to assist with decoding and reconstructing the activity.
That example reflects two important limitations of AI-assisted security research. A model can make a large amount of code or log data much easier to analyze, but it can also produce incorrect conclusions or refuse legitimate parts of the investigation. Neither situation changes the standard of evidence required. A finding still needs to be supported by the source code, network traffic, database state, or reproducible runtime behavior.
For this project, the model’s output was treated as a starting point rather than a conclusion. Any security control Claude identified was checked directly in the source, and no suspected vulnerability became a finding until it could be reproduced in the lab. Claude was never given independent authority to act on findings or access to the systems being tested beyond the controlled review process. Used this way, AI substantially improved the speed and coverage of the analysis without replacing the verification needed to determine whether a vulnerability was actually real.
Every vulnerability I confirm goes through a coordinated disclosure process before the technical details are made public. The findings are reported through the appropriate channels so the affected developers and security teams have time to investigate, verify the issue, and release a fix before reproduction details are published.
That is why this article does not identify the affected plugins or include payloads and reproduction steps for vulnerabilities that remain unpatched. Several of these plugins are still installed on thousands of WordPress sites, and publishing enough information to reproduce an active vulnerability would be more immediately useful to attackers than to the people responsible for fixing it.
Once that process has run its course, a later article in this series will cover the individual findings, including the vulnerable code, how each issue was reproduced, what initially led me to investigate it, and how the issue was ultimately corrected.
Although the individual vulnerabilities are not ready to be published, several parts of the research are useful now for anyone who develops WordPress plugins or maintains a WordPress site.
The events that originally motivated this project also provide the clearest reason to continue it. OpenAI’s agents demonstrated that AI systems can already test large numbers of attack paths, preserve useful information between attempts, and continue working through failures at a scale that would be difficult for a person to match. OpenAI is now evaluating models approaching its highest cybersecurity capability category, while Anthropic is using its newest models to identify vulnerabilities across large software projects and reporting that the problem is increasingly shifting from finding possible vulnerabilities to verifying and fixing the volume of results.
My experiment explored a much smaller version of that same change. One researcher using Claude Code was able to review dozens of WordPress plugins, examine codebases containing tens of thousands of lines, trace large numbers of possible vulnerability paths, and narrow that work into findings that could then be tested manually. AI significantly increased how much software I could examine within the same amount of time, while human verification still remained an important part of the process.
The results also showed why human verification remains important. Some vulnerabilities Claude identified were real, while others disappeared as soon as the code was tested in a running environment. In several cases, small implementation details completely changed the practical impact. The model was extremely useful for finding places worth investigating, but the lab was still necessary to determine which findings survived contact with the actual software.
The next article in this series will focus on that workflow directly. It will be a practical guide to conducting a security review with Claude Code, including how to prepare a codebase, structure the initial analysis, identify entry points and sensitive operations, divide a large plugin into manageable review passes, validate Claude’s claims against the source, and move from a suspected vulnerability to a reproducible test.
A later article will cover the results of the experiment after the coordinated disclosure process is complete. The research currently includes dozens of plugins reviewed and sixteen confirmed vulnerabilities, with the majority of the bugs having been previously unreported. Those findings include unauthenticated data exposure, stored cross-site scripting capable of reaching an administrator, SQL injection accessible to a subscriber-level account, CSRF leading to account takeover, several object-level authorization failures, a contact form that can be abused as a spam relay, and a booking system whose supposedly secret reservation token is predictable.
The findings that failed testing will be included as well, because they are an important part of understanding why the confirmed results can be trusted. In security research, identifying suspicious code is relatively easy. Demonstrating exactly what that code allows someone to do is the harder and more important part.
The larger change happening in 2026 is the speed of the search phase. Models can scan more code and test more ideas than a researcher could reasonably examine by hand, so verification becomes the bottleneck as that search gets faster. A security control can look correct in the source and still fail in the running application. For this project, every confirmed finding had to reproduce from a clean snapshot before I counted it. As shown in this experiment, expanding how much code and how many possible failure paths can be examined, AI-assisted review can make the resulting security assessment far more comprehensive than manual analysis alone.