<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog</title>
	<atom:link href="https://www.imperva.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.imperva.com/blog/</link>
	<description>Imperva Cybersecurity Blog</description>
	<lastBuildDate>Mon, 05 Oct 2026 13:25:48 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.5</generator>

<image>
	<url>https://www.imperva.com/wp-content/themes/impv/icons/favicon-32.png</url>
	<title>Blog</title>
	<link>https://www.imperva.com/blog/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>47-Day Certificates Are Coming: Five Things to Do Before They Arrive</title>
		<link>https://www.imperva.com/blog/47-day-certificates-five-steps-to-prepare/</link>
					<comments>https://www.imperva.com/blog/47-day-certificates-five-steps-to-prepare/#respond</comments>
		
		<dc:creator><![CDATA[Michael Wright]]></dc:creator>
		<pubDate>Mon, 05 Oct 2026 13:25:48 +0000</pubDate>
				<category><![CDATA[Application Security]]></category>
		<guid isPermaLink="false">https://www.imperva.com/blog/?p=21350</guid>

					<description><![CDATA[<p>Somewhere in your organization is a spreadsheet of certificate expiry dates, and someone who owns it. That is not a caricature. DigiCert&#8217;s 2026 research with Omdia surveyed more than 400 senior IT leaders and found that 47% still rely on manual tracking methods such as spreadsheets, and only 34% have a complete, current view of [&#8230;]</p>
<p>The post <a href="https://www.imperva.com/blog/47-day-certificates-five-steps-to-prepare/">47-Day Certificates Are Coming: Five Things to Do Before They Arrive</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Somewhere in your organization is a spreadsheet of certificate expiry dates, and someone who owns it. That is not a caricature. <a href="https://www.digicert.com/news/research-reveals-major-certificate-visibility-blind-spot" target="_blank" rel="noopener">DigiCert&#8217;s 2026 research with Omdia</a> surveyed more than 400 senior IT leaders and found that 47% still rely on manual tracking methods such as spreadsheets, and only 34% have a complete, current view of what they hold. The spreadsheet works because renewals come around once a year, and one person with a calendar can keep the whole estate in their head.</p>
<p>The industry has decided to take that away. <a href="https://cabforum.org/2025/04/11/ballot-sc081v3-introduce-schedule-of-reducing-validity-and-data-reuse-periods/" target="_blank" rel="noopener">The CA/Browser Forum voted</a> in April 2025 to bring the maximum TLS certificate lifespan down in steps: <a href="https://www.digicert.com/blog/tls-certificate-lifetimes-will-officially-reduce-to-47-days" target="_blank" rel="noopener">200 days from March 2026, 100 days from March 2027, and 47 days from March 2029</a>, with domain validation reuse dropping to 10 days. The first step is already live: since March 15, 2026, no publicly trusted TLS certificate can be valid for more than 200 days. By 2029 you will be proving ownership of your domains roughly every month, for every certificate, forever. The spreadsheet does not survive that. Neither does the person.</p>
<h2>Why TLS certificate lifespans are shrinking to 47 days</h2>
<p>Shorter lifespans shrink the window in which a stolen key or a mis-issued certificate is useful, and they push the whole ecosystem onto automation, which is where the reliability actually comes from. The destination is better. The journey is where outages live. Every manual step in your renewal process is a place where a 47-day cycle breaks something a 365-day cycle never stressed. We covered <a href="https://www.imperva.com/blog/the-future-of-ssl-certificate-management-adapting-to-shortened-renewal-periods/">what the vote means for Imperva customers</a> when it passed; this post is the checklist.</p>
<h2>How to prepare for 47-day certificates: five things to do, in order</h2>
<ol>
<li><strong>Inventory what you actually have</strong>. Every certificate, every domain, every site, and who renews it. <a href="https://docs-cybersec.thalesgroup.com/bundle/cloud-application-security/page/certificates.htm" target="_blank" rel="noopener">Cloud WAF reports SSL coverage status</a> for each protected site, so start with your public-facing estate. It is the part with a deadline attached and the part your customers meet first.</li>
<li><strong>Automate domain validation now</strong>. Manual validation at a 10-day reuse window is not a process, it is a permanent job for somebody. <a href="https://docs-cybersec.thalesgroup.com/bundle/cloud-application-security/page/cname-account.htm" target="_blank" rel="noopener">Automatic CNAME validation</a> makes ownership proof continuous, and it is the single change that turns the 2029 schedule from alarming to routine. The payoff starts now, not in 2029: Imperva already requires domain revalidation every 99 days for its managed certificates. We walked through the setup in <a href="https://www.imperva.com/blog/how-to-do-effortless-certificate-management-with-automated-cname-validation/" target="_blank" rel="noopener">Effortless certificate management with automated CNAME validation</a>.</li>
<li><strong>Find your non-SNI traffic before it finds you</strong>. Server Name Indication (SNI) is the TLS extension that tells the server which hostname a client is asking for. Clients that do not send it, usually older HTTP libraries, outdated monitoring tools and misconfigured internal services, cannot be served a site certificate (a site with non-SNI connections is not eligible for one), and they are rejected outright once a site moves to <a href="https://www.imperva.com/blog/sni-only-mode-in-imperva-cloud-waf/">SNI-only mode</a>. That is why this step comes before the next one. Non-SNI clients are also invisible unless you go looking. One custom rule with the filter <code>hasSNI == false</code>, set to Alert, logs every non-SNI request as a security event without blocking anything. Leave it running for a week or two, since some of this traffic is periodic, then decide. <a href="https://community-cybersec.thalesgroup.com/blogs/seana-murray-external/2026/09/14/imperva-cloud-waf-technical-guide-how-to-identify" target="_blank" rel="noopener">Imperva Cloud WAF Technical Guide: How to Identify Non-SNI Traffic Before Enabling SNI-Only Mode</a> walks through it step by step.</li>
<li><strong>Isolate the blast radius</strong>. A certificate shared across your whole estate means one renewal problem is everyone&#8217;s problem. <a href="https://docs-cybersec.thalesgroup.com/bundle/cloud-application-security/page/website-certificate.htm" target="_blank" rel="noopener">Imperva site certificates</a> give each site its own certificate, its own coverage status and up to 50 domains, so one team&#8217;s missed renewal does not become another team&#8217;s outage. New SNI-only sites have required site certificates since September 13, 2026, and Imperva recommends <a href="https://docs-cybersec.thalesgroup.com/bundle/cloud-application-security/page/account-certificate-deprecation.htm" target="_blank" rel="noopener">migrating existing SNI sites off shared account certificates</a> by December 31, 2026, before automatic migration begins in Q1 2027.</li>
<li><strong>Connect the certificate system you already run</strong>. If your certificates are governed in a Certificate Lifecycle Management (CLM) platform, the system that issues, tracks and renews certificates centrally, or in your own PKI, those renewals should reach your WAF without a person in between. <a href="https://www.imperva.com/blog/ssl-integration-center-digicert-trust-lifecycle-manage/">The SSL Integration Center</a> connects that workflow directly to Imperva Cloud WAF. <a href="https://www.digicert.com/trust-lifecycle-manager" target="_blank" rel="noopener">DigiCert Trust Lifecycle Manager</a> and <a href="https://www.keyfactor.com/products/command/" target="_blank" rel="noopener">Keyfactor Command</a> are on the supported vendor list, with further CLM integrations in progress.</li>
</ol>
<h2>What Imperva is already doing: 90-day certificates and the R46 root</h2>
<p>Imperva-managed certificates have already moved to 90-day validity (with domain validation every 99 days), ahead of the industry deadlines, with renewal and deployment automated end to end. Root trust is moving too: <a href="https://support.globalsign.com/ssl/upcoming-changes-tls-roots-and-certificate-profiles" target="_blank" rel="noopener">the GlobalSign root transition (R3 to R46)</a> is covered by a cross certificate that Imperva includes by default until the R3 root expires in March 2029, so legacy clients keep working, and <a href="https://docs-cybersec.thalesgroup.com/bundle/cloud-application-security/page/more/root-cert-change.htm" target="_blank" rel="noopener">action is needed only if you pin to a specific root certificate</a>. The direction of travel is simple. Certificate work becomes something you configure once, not something you do monthly.</p>
<p>The detail lives in the <a href="https://docs-cybersec.thalesgroup.com/bundle/cloud-application-security/page/introducing/cloud-waf.htm" target="_blank" rel="noopener">Cloud WAF documentation</a>, and walks the site-certificate path step by step.</p>
<p>Back to that spreadsheet. If it is yours, the right time to retire it is while it still works. If you retired it years ago, the question is whether your automation reaches all the way to your applications, or stops at the CA.</p>
<h2>Frequently asked questions about 47-day certificates</h2>
<p><strong>When do 47-day TLS certificates take effect?</strong><br />
From March 15, 2029, publicly trusted TLS certificates can be valid for no more than 47 days. The CA/Browser Forum schedule gets there in steps: 200 days from March 15, 2026 (already in force) and 100 days from March 15, 2027.</p>
<p><strong>How often will I need to validate domain ownership?</strong><br />
The period for reusing domain validation follows the same schedule: 200 days from March 2026, 100 days from March 2027 and 10 days from March 2029. In practice that means validating for almost every renewal, which is why an automated method such as CNAME delegation matters.</p>
<p><strong>Do I need to do anything for Imperva-managed certificates?</strong><br />
Imperva renews and deploys its managed certificates automatically, and they already have 90-day validity. What stays with you is domain validation (automatic CNAME validation removes it), moving SNI sites from shared account certificates to site certificates, and updating your trust store if you pin to a root certificate.</p>
<p><strong>What happens to clients that don&#8217;t support SNI?</strong><br />
A client that doesn&#8217;t send SNI can&#8217;t be served a site certificate, and once a site moves to SNI-only mode those connections are rejected. A custom rule with the filter <code>hasSNI == false</code>, set to Alert, shows whether you have any before you switch.</p>
<p>The post <a href="https://www.imperva.com/blog/47-day-certificates-five-steps-to-prepare/">47-Day Certificates Are Coming: Five Things to Do Before They Arrive</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.imperva.com/blog/47-day-certificates-five-steps-to-prepare/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<enclosure type="image/jpg" url="https://www.imperva.com/blog/wp-content/uploads/sites/9/2025/06/abstract-architecture-building.jpg" length="845" />	</item>
		<item>
		<title>Harvest Now, Decrypt Later: The Attack You Defend Against by Doing Nothing</title>
		<link>https://www.imperva.com/blog/harvest-now-decrypt-later-post-quantum-tls/</link>
					<comments>https://www.imperva.com/blog/harvest-now-decrypt-later-post-quantum-tls/#respond</comments>
		
		<dc:creator><![CDATA[Michael Wright]]></dc:creator>
		<pubDate>Mon, 05 Oct 2026 12:05:40 +0000</pubDate>
				<category><![CDATA[Application Security]]></category>
		<guid isPermaLink="false">https://www.imperva.com/blog/?p=21371</guid>

					<description><![CDATA[<p>Somewhere, an attacker is recording your encrypted traffic. Not breaking it. Recording it. The bet is patient and simple: store ciphertext today, wait for quantum computers to mature, decrypt at leisure. The industry calls it harvest now, decrypt later (HNDL), and it is the rare security threat with a believable deadline attached: data with a [&#8230;]</p>
<p>The post <a href="https://www.imperva.com/blog/harvest-now-decrypt-later-post-quantum-tls/">Harvest Now, Decrypt Later: The Attack You Defend Against by Doing Nothing</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Somewhere, an attacker is recording your encrypted traffic. Not breaking it. Recording it. The bet is patient and simple: store ciphertext today, wait for quantum computers to mature, decrypt at leisure. The industry calls it harvest now, decrypt later (HNDL), and it is the rare security threat with a believable deadline attached: data with a ten-year shelf life, encrypted with algorithms on a countdown.</p>
<p>Most quantum-readiness advice hands you a project: audit your cryptography, plan your migration, stand up a working group. Here is what Cloud WAF customers had to do to get quantum-safe TLS on every connection between their users and the Imperva network: nothing.</p>
<h2>What shipped: hybrid post-quantum TLS on every Cloud WAF site</h2>
<p>Every TLS 1.3 connection from a PQC-capable client to Imperva now negotiates hybrid TLS key agreement: X25519MLKEM768, which runs classical X25519 and quantum-safe ML-KEM-768 together. ML-KEM is the key-encapsulation mechanism NIST standardized as <a href="https://csrc.nist.gov/pubs/fips/203/final" target="_blank">FIPS 203</a> in August 2024. It is enabled by default on all Imperva sites, with zero configuration and no measurable performance trade-off. If a client supports it, it is on. Your users&#8217; sessions are already protected against the recording attack, and nobody on your team filed a ticket to make that happen. You can see it for yourself: open Chrome DevTools, go to the Security panel, and the connection to any Imperva-protected site lists X25519MLKEM768 as its key exchange. We explained earlier this year why <a href="https://www.imperva.com/blog/post-quantum-cryptography/">post-quantum cryptography can&#8217;t wait</a>; this post is the update now that both legs are covered.</p>
<h2>The second leg: post-quantum TLS from Imperva to your origin</h2>
<p>A proxy architecture has two connections per request: client to edge, and edge to origin. As of the <a href="https://docs-cybersec.thalesgroup.com/bundle/cloud-application-security/page/release-notes/2026-10-04.htm" target="_blank">October 4, 2026 release</a>, Imperva also supports PQC on the Imperva-to-origin leg, so customers whose origin servers support post-quantum key agreement get quantum-safe encryption end to end: from the user&#8217;s browser, through the Imperva network, to their own infrastructure. The requirement on your side is one sentence long: an origin that can negotiate the hybrid handshake. In practice, that means <a href="https://openssl-library.org/news/openssl-3.5-notes/" target="_blank">OpenSSL 3.5 or later</a>, which offers X25519MLKEM768 by default. Sites created on or after October 4, 2026 get PQC to origin automatically. Existing sites keep their current behavior until you switch it on under SSL/TLS Configuration > Origin connection security, or with the /v3/sites/origin-pqc API. If an origin can&#8217;t negotiate the hybrid handshake, the connection falls back to classical TLS without disruption.</p>
<h2>The honest scope: what hybrid key agreement covers</h2>
<p>Post-quantum TLS is arriving across the industry, and that is a good thing; no vendor should claim the category. What differs is the operational bill. Here the answer is: defaults. No premium SKU, no per-site enablement, no migration project for the edge leg, and, for end to end, an origin-side capability check plus one switch on sites created before October 4, 2026. For regulated sectors already fielding quantum questions from auditors and boards (finance, healthcare, defense), that turns a program into a paragraph in your next review. Behind it sits the Thales portfolio, where post-quantum work spans well beyond the WAF. One limit worth stating plainly: hybrid key agreement protects the confidentiality of each session, which is exactly what a harvest now, decrypt later attack targets. Certificate signatures are a separate, later migration (NIST&#8217;s ML-DSA, FIPS 204), because forging a signature needs a quantum computer at the moment of the handshake. Recorded traffic gives an attacker nothing to work with there.</p>
<h2>What to do about harvest now, decrypt later</h2>
<ul>
<li>Nothing, for the client leg. It is already on.</li>
<li>Check your origin stack for hybrid key-agreement support, and switch on the second leg when it does. That means OpenSSL 3.5 or later. New sites have PQC to origin on by default; existing sites need it switched on once, in the Cloud Security Console or through the API.</li>
<li>Put one line in your next security review: sessions through Cloud WAF are quantum-safe by default. Boards like sentences that end.</li>
</ul>
<p>Detail, including how to test PQC and how to switch it on for your origin, is in the <a href="https://docs-cybersec.thalesgroup.com/bundle/cloud-application-security/page/pqc-support.htm" target="_blank">Post-Quantum Cryptography (PQC) Support documentation</a>.</p>
<p>The recording attacker is patient. As of now, what they are recording from your traffic is noise with no future.</p>
<h2>Harvest now, decrypt later: FAQ</h2>
<h3>What is a harvest now, decrypt later (HNDL) attack?</h3>
<p>An attacker records encrypted traffic today and stores it until a cryptographically relevant quantum computer can break the classical key exchange that protected it. Data that must stay confidential for years is at risk now, even though that quantum computer does not exist yet.</p>
<h3>Is Imperva Cloud WAF traffic protected against harvest now, decrypt later?</h3>
<p>Yes, for the key exchange. TLS 1.3 connections from PQC-capable clients to Imperva use hybrid X25519MLKEM768 by default on all sites. Connections from Imperva to your origin use it when the origin supports it (OpenSSL 3.5 or later) and PQC to origin is on: by default for sites created on or after October 4, 2026, and opt-in for existing sites.</p>
<h3>What is X25519MLKEM768?</h3>
<p>It is the hybrid TLS 1.3 key-exchange group that combines classical X25519 elliptic-curve key agreement with ML-KEM-768 (FIPS 203). An attacker has to break both to recover the session key. It follows the hybrid model adopted by Google Chrome and other major browsers, and it is what Chrome DevTools shows when a connection is post-quantum protected.</p>
<h3>What happens if a client or origin doesn&#8217;t support post-quantum TLS?</h3>
<p>The connection falls back to classical TLS key exchange without disruption. PQC is used only when both sides support it, and it requires TLS 1.3. See the <a href="https://docs-cybersec.thalesgroup.com/bundle/cloud-application-security/page/pqc-support.htm" target="_blank">Imperva PQC documentation</a> for the handshake scenarios.</p>
<p>The post <a href="https://www.imperva.com/blog/harvest-now-decrypt-later-post-quantum-tls/">Harvest Now, Decrypt Later: The Attack You Defend Against by Doing Nothing</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.imperva.com/blog/harvest-now-decrypt-later-post-quantum-tls/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<enclosure type="image/jpg" url="https://www.imperva.com/blog/wp-content/uploads/sites/9/2024/02/shutterstock_1071270287-14-1.jpg" length="845" />	</item>
		<item>
		<title>New Remote DoS Attacks Against GraphQL Java</title>
		<link>https://www.imperva.com/blog/new-remote-dos-attacks-against-graphql-java/</link>
					<comments>https://www.imperva.com/blog/new-remote-dos-attacks-against-graphql-java/#respond</comments>
		
		<dc:creator><![CDATA[Yohann Sillam]]></dc:creator>
		<pubDate>Mon, 28 Sep 2026 16:24:49 +0000</pubDate>
				<category><![CDATA[Imperva Threat Research]]></category>
		<guid isPermaLink="false">https://www.imperva.com/blog/?p=21336</guid>

					<description><![CDATA[<p>Executive Summary  Imperva Threat Research identified a series of remote denial‑of‑service vulnerabilities in GraphQL Java, one of the most widely used libraries for GraphQL in the Java ecosystem.  In this blog, we’ll deep dive into these vulnerabilities, analyze their impact, and provide recommendations to protect your environment. If your endpoints are protected by Imperva Web Application Firewall, your systems are already protected against these threats.   Introduction  GraphQL Java is the engine beneath Spring for GraphQL, Netflix DGS, and Atlassian&#8217;s own products. With over one million downloads [&#8230;]</p>
<p>The post <a href="https://www.imperva.com/blog/new-remote-dos-attacks-against-graphql-java/">New Remote DoS Attacks Against GraphQL Java</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2><span data-contrast="none">Executive Summary</span><span data-ccp-props="{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:160,&quot;335559739&quot;:80}"> </span></h2>
<p><span data-contrast="auto">Imperva Threat Research identified a series of remote denial</span>‑<span data-contrast="auto">of</span>‑<span data-contrast="auto">service vulnerabilities in </span><a href="https://graphql-java.com/" target="_blank" rel="noopener"><span data-contrast="none">GraphQL Java</span></a><span data-contrast="auto">, one of the most widely used libraries for GraphQL in the Java ecosystem.</span><span data-ccp-props="{}"> </span></p>
<p><span data-contrast="auto">In this blog, we’ll deep dive into these vulnerabilities, analyze their impact, and provide recommendations to protect your environment. If your endpoints are protected by </span><a href="https://www.imperva.com/products/web-application-firewall-waf/" target="_blank" rel="noopener"><span data-contrast="none">Imperva Web Application Firewall</span></a><span data-contrast="auto">, your systems are already protected against these threats. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<h2><span data-contrast="none">Introduction</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:160,&quot;335559739&quot;:80,&quot;335559740&quot;:279}"> </span></h2>
<p><span data-contrast="auto">GraphQL Java is the engine beneath Spring for GraphQL, Netflix DGS, and Atlassian&#8217;s own products. With over one million downloads per month and ten years of production use, it is a natural choice for any team building a GraphQL API on the JVM.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Over the last few years, multiple types of </span><a href="https://www.imperva.com/blog/graphql-vulnerabilities-common-attacks/#denial-of-service" target="_blank" rel="noopener"><span data-contrast="none">DoS attacks</span></a><span data-contrast="auto"> have been identified across GraphQL implementations. These vulnerabilities can lead to either denial of service or, in cloud-billed environments, excessive cost consumption. In response, the industry converged on a set of protective controls, like depth limiting, query complexity budgets, and field count caps. Apollo added </span><a href="https://www.apollographql.com/blog/apollo-graphql-announces-major-graphos-update-enhancing%20%20%20-observability-and-performance-for-enterprise-scale-graphql-federation" target="_blank" rel="noopener"><span data-contrast="none">query cost analysis</span></a><span data-contrast="auto"> and depth limiting, GitHub </span><a href="https://docs.github.com/en/graphql/overview/rate-limits-and-query-limits-for-the-graphql-api" target="_blank" rel="noopener"><span data-contrast="none">meters its public GraphQL API</span></a><span data-contrast="auto"> by computed node cost, and </span><a href="https://graphql-java.com/" target="_blank" rel="noopener"><span data-contrast="none">GraphQL Java</span></a><span data-contrast="auto"> also introduced </span><a href="https://github.com/graphql-java/graphql-java/releases/tag/v26.0" target="_blank" rel="noopener"><span data-contrast="none">additional controls</span></a><span data-contrast="auto">.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">However, these enhancements can leave blind spots earlier in the pipeline, before the server has even understood the request.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">The DoS attack we found live in the first half of the pipeline, where the query is parsed and validated, and therefore </span><b><span data-contrast="auto">independent from the schema, the resolvers, and any backend logic</span></b><span data-contrast="auto">.</span><b><span data-contrast="auto"> </span></b><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">They were reported under GHSA-7p4r-9rcc-8vhv (still as draft) and fixed in versions 24.4, 25.1, and 26.1. Several products embedding the library were affected, including Adobe Experience Manager (AEM), Atlassian Confluence, and </span><a href="https://hub.docker.com/r/hapiproject/hapi" target="_blank" rel="noopener"><span data-contrast="none">HAPI FHIR server</span></a><span data-contrast="auto">, a widely used open-source implementation of the HL7 FHIR healthcare interoperability standard.</span><span data-ccp-props="{}"> </span></p>
<h2><span data-contrast="none">Request Processing</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:160,&quot;335559739&quot;:80,&quot;335559740&quot;:279}"> </span></h2>
<p><img class="lazyload alignnone size-full wp-image-21337 lazyload" alt="Screenshot 2026 09 23 at 8.36.15 PM" width="1658" height="748" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.36.15-PM.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.36.15-PM.png 1658w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.36.15-PM-300x135.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.36.15-PM-1024x462.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.36.15-PM-768x346.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.36.15-PM-1536x693.png 1536w" sizes="(max-width: 1658px) 100vw, 1658px" /></p>
<p style="text-align: center"><em>Fig. 1: GraphQL Processing High Level Pipeline </em></p>
<p><span data-contrast="auto">GraphQL was built around a simple </span><a href="https://engineering.fb.com/2015/09/14/core-infra/graphql-a-data-query-language/#:~:text=GraphQL%20queries%20mirror%20their%20response" target="_blank" rel="noopener"><span data-contrast="none">idea</span></a><span data-contrast="auto">: </span><span data-contrast="auto">“GraphQL queries mirror their response.” In other words, the client describes exactly the data it needs, while the server determines how to retrieve and resolve that data. The query is then sent to a GraphQL endpoint, where it goes through a series of processing steps before the response is returned:</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<ul>
<li data-leveltext="" data-font="Symbol" data-listid="8" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">HTTP Request</span><span data-contrast="auto">: The server receives the GraphQL query.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="8" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">Lexing</span><span data-contrast="auto">: The query is broken down into tokens.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="8" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">Parsing</span><span data-contrast="auto">: The tokens are turned into an Abstract Syntax Tree (AST) representing the query structure.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="8" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">Validation</span><span data-contrast="auto">: The query is checked against the GraphQL schema and its rules.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="8" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">Execution</span><span data-contrast="auto">: GraphQL invokes the appropriate resolvers to retrieve the requested data.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="8" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">JSON Response</span><span data-contrast="auto">: The results are assembled and returned to the client.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
</ul>
<p><span data-contrast="auto">The distinction between these stages matters. A request can be rejected before execution because its syntax is invalid or because it does not match the schema. Only after passing these checks does GraphQL reach the resolvers, where the application and its underlying data sources are accessed.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><span data-contrast="auto">For security research, this pipeline provides a useful way to understand the attack surface. Each stage processes attacker-controlled input in a different way, making it important to understand not only what GraphQL does, but also when and where it does it.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<h2><span data-contrast="none">Parsing and Validation: A Closer Look</span><span data-ccp-props="{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:160,&quot;335559739&quot;:80}"> </span></h2>
<p><span data-contrast="auto">Before a server decides what data to return, it must first decide whether the request makes sense. Parsing breaks the raw query text into an Abstract Syntax Tree. This involves:</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<ul>
<li data-leveltext="-" data-font="Aptos" data-listid="9" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Aptos&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;-&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><b><span data-contrast="auto">Resolving string literals:</span></b><span data-contrast="auto"> block strings go through a dedicated normalization routine that strips leading and trailing blank lines.</span><span data-ccp-props="{}"> </span></li>
<li data-leveltext="-" data-font="Aptos" data-listid="9" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Aptos&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;-&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><b><span data-contrast="auto">Constructing AST nodes for every value encountered:</span></b><span data-contrast="auto"> numeric literals are converted to BigInteger or BigDecimal at this point.</span><span data-ccp-props="{}"> </span></li>
</ul>
<p><span data-contrast="auto">Validation walks the AST and checks it against the schema. This involves:</span><span data-ccp-props="{&quot;335559685&quot;:0}"> </span></p>
<ul>
<li data-leveltext="-" data-font="Aptos" data-listid="10" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Aptos&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;-&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><b><span data-contrast="auto">Field and type checks: </span></b><span data-contrast="auto">do the requested fields exist? Do the argument types match?</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></li>
<li data-leveltext="-" data-font="Aptos" data-listid="10" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Aptos&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;-&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><b><span data-contrast="auto">Fragment validation: </span></b><span data-contrast="auto">named fragments must not form cycles, directly or transitively</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></li>
<li data-leveltext="-" data-font="Aptos" data-listid="10" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Aptos&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;-&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><b><span data-contrast="auto">Limit enforcement:</span></b><span data-contrast="auto"> in GraphQL Java 26.0, maxDepth and maxFieldsCount are checked here.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></li>
</ul>
<h2><span data-contrast="none">Fragment Cycle Detection</span><span data-ccp-props="{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:160,&quot;335559739&quot;:80}"> </span></h2>
<p><span data-contrast="auto">Validation is where fragment cycle detection takes place. Named fragments are GraphQL&#8217;s reuse mechanism. Instead of repeating the same selection set in multiple places, a client defines it once and references it with a spread:</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><img class="lazyload alignnone size-full wp-image-21347 lazyload" alt="Screenshot 2026 09 28 at 9.19.01 AM" width="2008" height="800" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-28-at-9.19.01-AM.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-28-at-9.19.01-AM.png 2008w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-28-at-9.19.01-AM-300x120.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-28-at-9.19.01-AM-1024x408.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-28-at-9.19.01-AM-768x306.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-28-at-9.19.01-AM-1536x612.png 1536w" sizes="(max-width: 2008px) 100vw, 2008px" /></p>
<p style="text-align: center"><em>Fig. 2: Named Fragments in GraphQL </em></p>
<p><span data-contrast="auto">Fragments can themselves spread other fragments. The spec allows arbitrary nesting, but it forbids cycles: if A spreads B and B spreads A, resolving either one requires resolving the other first. The execution engine would recurse indefinitely. The same applies to indirect cycles across any number of fragments.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">This check happens during validation, after parsing has produced the AST and before execution starts. At this point the server has a complete map of every named fragment in the document and every spread reference between them. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Cycle detection is pretty straightforward: for each fragment, follow its spread references transitively and check whether any path leads back to the starting node. If it does, the document is rejected with a validation error and execution never starts.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><i><span data-contrast="auto">ValidateNoFragmentCycles </span></i><span data-contrast="auto">is called once per </span><i><span data-contrast="auto">FragmentDefinition </span></i><span data-contrast="auto">in the document. Each call starts with a fresh HashMap.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">For each fragment, it calls </span><i><span data-contrast="auto">buildTransitiveSpreads</span></i><span data-contrast="auto">, a depth-first traversal that follows every spread reference outward, building up the set of fragments reachable from the starting node. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">The traversal tracks its current path in an ArrayList, and at each step calls ArrayList.contains to check whether the next node has already been visited. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<h2><span data-contrast="none">Worst Case Scenario</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:160,&quot;335559739&quot;:80,&quot;335559740&quot;:279}"> </span></h2>
<p><span data-contrast="auto">We considered a document with the following chain of d fragments:</span><span data-ccp-props="{}"> </span></p>
<p><img class="lazyload alignnone size-full wp-image-21339 lazyload" alt="Screenshot 2026 09 23 at 8.38.39 PM" width="1650" height="304" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.38.39-PM.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.38.39-PM.png 1650w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.38.39-PM-300x55.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.38.39-PM-1024x189.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.38.39-PM-768x141.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.38.39-PM-1536x283.png 1536w" sizes="(max-width: 1650px) 100vw, 1650px" /></p>
<p style="text-align: center"><em>Fig. 3: Malicious Payload Structure </em></p>
<p><span data-contrast="auto">For each fragment, </span><i><span data-contrast="auto">ValidateNoFragmentCycles </span></i><span data-contrast="auto">starts a new traversal with a fresh HashMap. Since the traversal follows the entire chain, and ArrayList.contains iterates over the path of fragments visited so far, the cost of a single validation is O(d²</span><span data-contrast="auto">). </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><img class="lazyload alignnone size-full wp-image-21340 lazyload" alt="Screenshot 2026 09 23 at 8.39.14 PM" width="1412" height="1100" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.39.14-PM.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.39.14-PM.png 1412w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.39.14-PM-300x234.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.39.14-PM-1024x798.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.39.14-PM-768x598.png 768w" sizes="(max-width: 1412px) 100vw, 1412px" /></p>
<p style="text-align: center"><em>Fig. 4: Processing of the First Fragment </em></p>
<p><span data-contrast="auto">Since this happens for all fragments, the overall complexity is O(d³), where d is the number of fragments in the document. Within the default 15,000-token limit, a single payload can contain up to around 1,800 fragments (~50 KB), which is sufficient to saturate a CPU core for several minutes at every request.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<h3><b><span data-contrast="auto">Why existing GraphQL</span></b> protections<b><span data-contrast="auto"> may not help</span></b><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></h3>
<p><span data-contrast="auto">Traditional GraphQL protections such as depth limits and field-count limits operate during validation. However, this attack specifically targets the validation step itself. </span><b><span data-contrast="auto">Therefore, it hits before the protections can prevent the attack</span></b><span data-contrast="auto">.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Following the reception of our report, graphql-java released a patch that introduces memoization. Once a fragment has been explored, it is marked as done and never re-traversed again. The same malicious payload is processed in a few milliseconds instead.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">This finding was the most impactful, but it wasn’t the only one.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<h2><span data-contrast="none">Additional Remote DoS Vulnerabilities</span><span data-ccp-props="{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:160,&quot;335559739&quot;:80}"> </span></h2>
<p><span data-contrast="auto">We identified the same underlying idea as </span><a href="https://github.com/vercel/next.js/issues/91890" target="_blank" rel="noopener"><span data-contrast="none">one of the attack vectors</span></a><span data-contrast="auto"> previously identified in React Server Components (BigInt values, CVE-2026-23864), and another vector involving block string normalization routine, more impactful. Both fixed in </span><span data-contrast="auto">24.4, 25.1 and 26.1.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<h2><span data-contrast="none">HAPI FHIR Use Case</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:160,&quot;335559739&quot;:80,&quot;335559740&quot;:279}"> </span></h2>
<p><span data-contrast="auto">HAPI FHIR is a Java server designed to store and serve medical data (patients, prescriptions, lab results) using the FHIR healthcare standard. Like many modern APIs, it exposes a GraphQL endpoint that clients can use to query this data. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Internally, HAPI handles GraphQL requests with its own parser, written specifically for FHIR, which knows how to resolve medical resources. But when a client asks for introspection (a standard GraphQL feature that returns the full list of available queries and types) HAPI delegates directly to graphql-java. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">However, it&#8217;s possible to bypass HAPI&#8217;s custom FHIR resolver and route a non-introspection query straight to graphql-java.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">This delegation is triggered by a simple string check: it relies on the presence of the string `__schema` in the body. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Therefore, simply starting the request with the following pattern (see Fig 5.) was enough.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><img class="lazyload alignnone size-full wp-image-21341 lazyload" alt="Screenshot 2026 09 23 at 8.40.46 PM" width="1560" height="152" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.40.46-PM.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.40.46-PM.png 1560w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.40.46-PM-300x29.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.40.46-PM-1024x100.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.40.46-PM-768x75.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.40.46-PM-1536x150.png 1536w" sizes="(max-width: 1560px) 100vw, 1560px" /></p>
<p style="text-align: center"><em>Fig. 5: bypass HAPI&#8217;s custom FHIR GraphQL resolver </em></p>
<p><span data-contrast="auto">Tested on a fresh c7i.2xlarge instance, with the latest </span><a href="https://hub.docker.com/r/hapiproject/hapi" target="_blank" rel="noopener"><span data-contrast="none">HAPI server</span></a><span data-contrast="auto"> with graphql enabled, a single request took 150 seconds of validation. A single wave of multiple small requests could lock the server entirely for several minutes and pin all 8 CPU cores at 100% for more than an hour.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:0,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">In this application, this attack vector could represent an alternative avenue for a threat actor lacking authorization to exfiltrate patient data (as HAPI&#8217;s authorization model governs GraphQL endpoint access and data read permissions </span><a href="https://github.com/hapifhir/hapi-fhir/blob/master/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/IAuthRuleBuilderGraphQL.java#L25" target="_blank" rel="noopener"><span data-contrast="none">independently</span></a><span data-contrast="auto">), and still willing to cause impact.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">The attack surface is further widened by HAPI&#8217;s default CORS configuration (</span><a href="https://github.com/hapifhir/hapi-fhir/blob/master/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/CorsInterceptor.java#L118" target="_blank" rel="noopener"><span data-contrast="none">allows any origin,</span></a><span data-contrast="auto"> Access-Control-Allow-Origin: *). In environments where no additional network controls are in place, this means the attack could be triggered from a browser: a healthcare worker opening a malicious link while connected to the internal network is sufficient to take down the FHIR server for everyone.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<h2><span data-contrast="none">Who is Affected?</span><span data-ccp-props="{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:160,&quot;335559739&quot;:80}"> </span></h2>
<p><span data-contrast="auto">An application is potentially exposed when:</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<ul>
<li data-leveltext="" data-font="Symbol" data-listid="19" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">It uses an affected version of GraphQL Java; </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="19" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">It accepts attacker-controlled GraphQL documents; </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="19" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">The GraphQL endpoint is remotely reachable; </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="19" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">No upstream control blocks the malicious request. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
</ul>
<h2><span data-contrast="none">Remediation</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></h2>
<p><span data-contrast="auto">The fixes are available in GraphQL Java versions 24.4, 25.1, and 26.1 via PRs #4440, #4441.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">For environments where an immediate upgrade is not possible:</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<ul>
<li data-leveltext="" data-font="Symbol" data-listid="20" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">Restrict access to affected GraphQL endpoints </span><span data-contrast="auto">to authenticated or otherwise trusted clients where the application permits it.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="20" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">Apply rate limiting and concurrency limits </span><span data-contrast="auto">to restrict the number of GraphQL requests that can be processed simultaneously.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="20" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">Monitor CPU utilization and GraphQL request latency </span><span data-contrast="auto">for unusual increases that may indicate resource-exhaustion attempts.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
</ul>
<p><span data-contrast="auto">If your endpoints are protected by </span><a href="https://www.imperva.com/products/web-application-firewall-waf/" target="_blank" rel="noopener"><span data-contrast="none">Imperva Web Application Firewall</span></a><span data-contrast="auto">, your systems are already protected against these threats.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<h2><span data-contrast="none">Conclusion</span><span data-ccp-props="{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:160,&quot;335559739&quot;:80}"> </span></h2>
<p><span data-contrast="auto">As AI accelerates vulnerability discovery and exploitation, threat actors can increasingly scan a target environment in real time, identify weaknesses across its technology stack, and rapidly turn those findings into attacks. This reduces the time organizations must detect and remediate newly exposed vulnerabilities, making proactive and continuously enforced security controls increasingly important.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><span data-contrast="auto">Affected organizations should upgrade to a fixed release as soon as possible. Until patches can be applied, additional controls at the application and network layers can help reduce exposure and limit the impact of potential attacks.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><span data-contrast="auto">Imperva customers are protected against exploitation of these vulnerabilities. Imperva Threat Research will continue to monitor this threat and work to ensure that customers remain protected against emerging attack techniques targeting GraphQL and other widely deployed technologies.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<h2><span data-contrast="none">Timeline</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:160,&quot;335559739&quot;:80,&quot;335559740&quot;:279}"> </span></h2>
<p><span data-contrast="auto">August 11 – </span><span data-contrast="none">We reported the security issue to GraphQL Java.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="none">August 19 – Report Acknowledged.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">August 23 – Fix released in versions </span><span data-contrast="auto">24.4, 25.1 and 26.1.</span><span data-ccp-props="{}"> </span></p>
<p>The post <a href="https://www.imperva.com/blog/new-remote-dos-attacks-against-graphql-java/">New Remote DoS Attacks Against GraphQL Java</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.imperva.com/blog/new-remote-dos-attacks-against-graphql-java/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<enclosure type="image/jpg" url="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.43.00-PM.png" length="1618" />	</item>
		<item>
		<title>From Debugging to Code Execution: RCE in Microsoft DevLabs’ DebugMCP?</title>
		<link>https://www.imperva.com/blog/from-debugging-to-code-execution-rce-in-microsoft-devlabs-debugmcp/</link>
					<comments>https://www.imperva.com/blog/from-debugging-to-code-execution-rce-in-microsoft-devlabs-debugmcp/#respond</comments>
		
		<dc:creator><![CDATA[Imperva Threat Research]]></dc:creator>
		<pubDate>Fri, 25 Sep 2026 15:51:17 +0000</pubDate>
				<category><![CDATA[Imperva Threat Research]]></category>
		<guid isPermaLink="false">https://www.imperva.com/blog/?p=21323</guid>

					<description><![CDATA[<p>Introduction  AI-assisted development has crossed a threshold. The question is no longer whether your IDE communicates with an AI, it&#8217;s how deeply that AI is now wired into your local environment. The Model Context Protocol (MCP) is one of the plumbing behind this shift: a JSON-RPC-based protocol that lets AI assistants invoke tools running on your machine. From setting a breakpoint, to running tests, or launching a debugger&#8230; all from a chat [&#8230;]</p>
<p>The post <a href="https://www.imperva.com/blog/from-debugging-to-code-execution-rce-in-microsoft-devlabs-debugmcp/">From Debugging to Code Execution: RCE in Microsoft DevLabs’ DebugMCP?</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2><b><span data-contrast="none">Introduction</span></b><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:299,&quot;335559739&quot;:299}"> </span></h2>
<p><span data-contrast="auto">AI-assisted development has crossed a threshold. The question is no longer whether your IDE communicates with an AI, it&#8217;s </span><i><span data-contrast="auto">how deeply</span></i><span data-contrast="auto"> that AI is now wired into your local environment. The Model Context Protocol (MCP) is one of the plumbing behind this shift: a JSON-RPC-based protocol that lets AI assistants invoke tools running on your machine. From setting a breakpoint, to running tests, or launching a debugger&#8230; all from a chat window.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">DebugMCP </span><span data-contrast="auto">is one of the extensions leading that charge. Published by Microsoft on </span><a href="https://github.com/microsoft/DebugMCP" target="_blank" rel="noopener"><span data-contrast="none">GitHub</span></a><span data-contrast="auto">, it exposes a local MCP server that gives any compatible AI agent (GitHub Copilot, Cline, Cursor, Codex, Windsurf, and others) direct control over the VS Code debugger. The value proposition is compelling: instead of pasting stack traces into a chat window and waiting for a suggestion, an AI agent can set breakpoints, step through code, inspect variables, and evaluate expressions autonomously. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><span data-contrast="auto">We identified and reported a critical security issue in version 1.1.4. A remote attacker who tricked a developer into visiting a malicious webpage could achieve </span><span data-contrast="auto">arbitrary code execution</span><span data-contrast="auto"> on that developer&#8217;s machine, in the background, without any further user interaction (drive by). </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Following our report, the maintainers patched </span><b><span data-contrast="auto">DebugMCP</span></b><span data-contrast="auto"> via </span><a href="https://github.com/microsoft/DebugMCP/commit/86776b21609578ba7087b0b8ec316c2994c72a32#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5" target="_blank" rel="noopener"><span data-contrast="none">commit 86776b2m.</span></a><span data-contrast="auto"> The fix was silently shipped (no version bump, no advisory) and is included in version 1.2.0 and later. We are publishing this report following the 90-day disclosure period.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">We recommend updating to the latest available version.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<h2><b><span data-contrast="none">Scope</span></b><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:299,&quot;335559739&quot;:299,&quot;335559740&quot;:279}"> </span></h2>
<p><span data-contrast="auto">The exploitability of this weakness was amplified by the context in which the software evolves. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Indeed, we’re talking about an opensource MCP server hosted on </span><a href="https://github.com/microsoft/DebugMCP" target="_blank" rel="noopener"><span data-contrast="none">GitHub</span></a><span data-contrast="auto">, that can be used as a standalone server. But this MCP server is also exposed as an extension in </span><a href="https://marketplace.visualstudio.com/items?itemName=ozzafar.debugmcpextension" target="_blank" rel="noopener"><span data-contrast="none">VSCode Marketplace</span></a><span data-contrast="auto">, installable with a single click both in local endpoints, and in shared servers via systems like Github CodeSpaces, OpenVSCode Server, etc.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">From this single installation click, the server is automatically started and listening on port 3001 without authentication, opening the door to RCE.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">First, we’ll explore how this issue could be exploited from a surrounding compromised device, and we’ll then demonstrate how DNS rebinding could be exploited to trigger RCE via simply having a victim browse to a malicious site.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<h2><b><span data-contrast="none">Root Cause</span></b><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:299,&quot;335559739&quot;:299,&quot;335559740&quot;:279}"> </span></h2>
<h3><span data-contrast="none">DNS Rebinding</span><span data-ccp-props="{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:160,&quot;335559739&quot;:80}"> </span></h3>
<p><span data-contrast="auto">DNS Rebinding is a recurrent risk issue when it comes to MCP servers&#8217; development (See our previous blogpost: </span><a href="https://www.imperva.com/blog/another-critical-rce-discovered-in-a-popular-mcp-server/" target="_blank" rel="noopener"><span data-contrast="none">Another Critical RCE Discovered in a Popular MCP Server</span></a><span data-contrast="auto">).  </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">At the end of 2025, probably following a series of vulnerabilities identified in multiple MCP servers, Anthropic added an additional layer of security to prevent this risk (</span><a href="https://github.com/modelcontextprotocol/typescript-sdk/security/advisories/GHSA-w48q-cv73-mx4w" target="_blank" rel="noopener"><span data-contrast="none">CVE-2025-66414)</span></a><span data-contrast="auto"> that adds a default security layer in most MCP server cases. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Version 1.24.0 of modelcontextprotocol introduces createMcpExpressApp, a preconfigured express server instance that automatically registers validateHostHeader and validateOriginHeader. Together, these functions prevent the risk of DNS rebinding. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">However, the library still relies on maintainers to use header validation middleware functions in case of custom express configuration. And in the case of DebugMCP, this is lacking.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">That was the first node of our attack chain.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Combined with the lack of host and origin definition and validation, the custom express server defined (identical to </span><a href="https://www.imperva.com/blog/another-critical-rce-discovered-in-a-popular-mcp-server/" target="_blank" rel="noopener"><span data-contrast="none">CVE-2025-53967</span></a><span data-contrast="auto">), exposed the MCP tools far beyond the intended reach. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p>But independently from the broad network exposure, an LLM could be tricked via <a href="https://www.imperva.com/learn/application-security/prompt-injection/" target="_blank" rel="noopener">indirect prompt injection</a> to access a file outside VSCode workspace trust, and the <a href="https://github.com/microsoft/DebugMCP/commit/86776b21609578ba7087b0b8ec316c2994c72a32#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5" target="_blank" rel="noopener">fix</a> produced by the maintainers doesn&#8217;t answer this question.</p>
<h3><span data-contrast="none">Uncontrolled File Path</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:160,&quot;335559739&quot;:80,&quot;335559740&quot;:279}"> </span></h3>
<p><span data-contrast="auto">To further explore the attack chain, let’s review the tools exposed.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">The README lists the available tools, including:</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<ul>
<li data-leveltext="" data-font="Symbol" data-listid="3" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">start_debugging: launches a debugging session for a given file path</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="3" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">get_debugger_state: returns the current state of an active debugging session</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="3" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">add_breakpoint / remove_breakpoint: manage breakpoints</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="3" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">step_over / step_into / step_out: stepping controls</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="3" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">get_variables: inspect local variables in the current stack frame</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="3" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">evaluate_expression: evaluate an arbitrary expression in the debugger context</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:0,&quot;335559739&quot;:0}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="3" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">continue_execution: resume execution</span></li>
</ul>
<p><span data-contrast="auto">From reading the tool definitions, </span><i><span data-contrast="auto">start_debugging</span></i><span data-contrast="auto"> jumped out immediately since it accepted a </span><i><span data-contrast="auto">fileFullPath </span></i><span data-contrast="auto">argument and instructs VS Code to launch a debugger session for that file. That&#8217;s a file execution primitive.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">But to obtain an efficient RCE chain, a few more steps were required.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<h3><span data-contrast="none">The UNC Path Primitive</span><span data-ccp-props="{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:160,&quot;335559739&quot;:80}"> </span></h3>
<p><span data-contrast="auto">At first glance, because the vulnerability requires knowing the full path of an executable on the victim&#8217;s machine, it seems difficult to weaponize reliably in the wild.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">However, on Windows, the Universal Naming Convention (UNC) path format allows programs to reference files on network shares using paths of the form:</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><i><span data-contrast="auto">\\SERVER\SHARE\path\to\file</span></i><span data-ccp-props="{}"> </span></p>
<p><span data-contrast="auto">This feature enabled us to make DebugMCP pass the path to VS Code&#8217;s debugging infrastructure, which passed it to the Python launcher, which reached out to the attacker&#8217;s SMB share and loaded the file. The file executed under the victim&#8217;s user context.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><img class="lazyload alignnone size-full wp-image-21330 lazyload" alt="Screenshot 2026 09 23 at 8.22.07 PM" width="1554" height="398" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.22.07-PM.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.22.07-PM.png 1554w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.22.07-PM-300x77.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.22.07-PM-1024x262.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.22.07-PM-768x197.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.22.07-PM-1536x393.png 1536w" sizes="(max-width: 1554px) 100vw, 1554px" /></p>
<p style="text-align: center"><em>Fig. 1: SMB endpoint to fetch payload </em></p>
<p><span data-contrast="auto">The proof-of-concept payload was intentionally benign:</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><i><span data-contrast="auto">import os</span></i><br />
<i><span data-contrast="auto">os.system(&#8220;calc.exe&#8221;)</span></i><span data-ccp-props="{}"> </span></p>
<p><span data-contrast="auto">After a few seconds, Calculator opened. The attacker&#8217;s code was running on the victim&#8217;s machine via a single HTTP request.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><span data-contrast="auto">At this point we had a working local exploit, if we could send one HTTP request to port 3001 with an attacker-controlled UNC path and get code execution. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">The remaining question was how to deliver that request from a remote attacker&#8217;s position to a victim&#8217;s localhost, across the same-origin policy that is supposed to make this impossible.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<h3><span data-contrast="none">Stateless MCP session</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:160,&quot;335559739&quot;:80,&quot;335559740&quot;:279}"> </span></h3>
<p><span data-contrast="auto">One part of the answer lies in the MCP itself. You can find a detailed introduction to the protocol </span><a href="https://www.imperva.com/blog/mcp-server-security-blind-spot-ai-stack/" target="_blank" rel="noopener"><span data-contrast="none">here</span></a><span data-contrast="auto">.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">What matters here is one implementation detail that significantly reduced the attack complexity.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">MCP over HTTP is built on JSON-RPC 2.0. The protocol specification describes a lifecycle: a client must send an </span><i><span data-contrast="auto">initialize </span></i><span data-contrast="auto">request, receive the server&#8217;s capability response, then send an initialized notification (only after this handshake can tool calls be made). This sequence implies a minimum of two round-trips before any tool is invoked, and it gives a server the opportunity to establish authenticated session state.</span><span data-ccp-props="{}"> </span></p>
<p><span data-contrast="auto">The MCP TypeScript SDK&#8217;s </span><i><span data-contrast="auto">StreamableHTTPServerTransport </span></i><span data-contrast="auto">enforces this lifecycle through a </span><i><span data-contrast="auto">validateSession</span></i><span data-contrast="auto"> function called on every non-initialize request. The enforcement is conditional:</span><span data-ccp-props="{}"> </span></p>
<p><img class="lazyload alignnone size-full wp-image-21331 lazyload" alt="Screenshot 2026 09 23 at 8.22.55 PM" width="1740" height="566" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.22.55-PM.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.22.55-PM.png 1740w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.22.55-PM-300x98.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.22.55-PM-1024x333.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.22.55-PM-768x250.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.22.55-PM-1536x500.png 1536w" sizes="(max-width: 1740px) 100vw, 1740px" /></p>
<p style="text-align: center"><em>Fig. 2: Stateless MCP mode</em><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:2,&quot;335551620&quot;:2,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">When sessionIdGenerator is undefined, validateSession returns immediately without checking anything. The entire initialization lifecycle is bypassed. In DebugMCP v1.1.4, the transport was explicitly configured in </span><a href="https://github.com/microsoft/DebugMCP/blob/7cbe4f9f68eb81c0adf2475f1d4e0c07e4f286a0/src/debugMCPServer.ts#L351" target="_blank" rel="noopener"><span data-contrast="none">stateless</span></a><span data-contrast="auto"> mode. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">The consequence for the attack chain is direct: a single no-cors HTTP request was sufficient to trigger the attack.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<h3><span data-contrast="none">Browser Local Network Protections</span><span data-ccp-props="{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:160,&quot;335559739&quot;:80}"> </span></h3>
<p><span data-contrast="auto">However, there was a last ingredient we needed to incorporate to obtain a frictionless exploit.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Indeed, </span><a href="https://developer.chrome.com/blog/local-network-access" target="_blank" rel="noopener"><span data-contrast="none">Local Network Access’s</span></a><span data-contrast="auto"> aim is to protect users from cross-site request forgery (CSRF) attacks targeting routers and other devices on private networks, and to reduce the ability of sites to use these requests to fingerprint the user&#8217;s local network.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Combined with the same-origin policy (that prevents a piece of JavaScript from one domain  and make cors requests to a different one and get the response), in </span><a href="https://support.mozilla.org/en-US/kb/control-personal-device-local-network-permissions-firefox" target="_blank" rel="noopener"><span data-contrast="none">modern browsers</span></a><span data-contrast="auto">, there is a good chance a warning popup would be displayed and halt the execution of the malicious content if a threat actor tries to scan the local network. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">But DNS rebinding is a technique that can potentially circumvent this boundary by exploiting the way browsers cache DNS records. And as we explained earlier, DebugMCP doesn’t include MCP default mitigation added by Anthropic against this risk.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Here is the attack flow:</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><img class="lazyload alignnone size-full wp-image-21332 lazyload" alt="Screenshot 2026 09 23 at 8.24.01 PM" width="1862" height="928" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.24.01-PM.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.24.01-PM.png 1862w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.24.01-PM-300x150.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.24.01-PM-1024x510.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.24.01-PM-768x383.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.24.01-PM-1536x766.png 1536w" sizes="(max-width: 1862px) 100vw, 1862px" /></p>
<p style="text-align: center"><em>Fig. 3: Attack Flow </em></p>
<p><span data-contrast="auto">The sequence unfolds in six steps:</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><b><span data-contrast="auto">Step 1: Victim visits the page.</span></b><span data-contrast="auto"> The attacker&#8217;s domain resolves to the attacker&#8217;s public IP (Phase 1 DNS). The browser loads the initial page content. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><b><span data-contrast="auto">Step 2: DNS Rebinding.</span></b><span data-contrast="auto"> The domain was registered with a very short TTL: 1 to 2 seconds. Firefox enforces an internal minimum cache duration of ~60 seconds regardless of the declared TTL, so the page polls in a JavaScript loop until the entry expires and Firefox re-resolves the name: at which point the attacker&#8217;s DNS server returns 127.0.0.1.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><b><span data-contrast="auto">Step 3: Local Network Access.</span></b><span data-contrast="auto"> The attacker&#8217;s JavaScript, issues a fetch to http://evil.attacker.com:3001/mcp?transport=streamable_http. The browser considers this request same-origin and sends it. The DNS entry now points to 127.0.0.1, so the request arrives at the victim&#8217;s local DebugMCP server.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><b><span data-contrast="auto">Step 4: DebugMCP Execution.</span></b><span data-contrast="auto"> The request reaches the Microsoft DebugMCP server running locally on the victim&#8217;s machine. DebugMCP processes the request and triggers its Python launcher, which is responsible for starting the debugging workflow.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><b><span data-contrast="auto">Step 5: Malicious Payload Download.</span></b><span data-contrast="auto"> The Python launcher connects to a publicly accessible SMB share controlled by the attacker and downloads the malicious Python script onto the victim&#8217;s machine.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><b><span data-contrast="auto">Step 6: Code Execution.</span></b><span data-contrast="auto"> The launcher passes the downloaded script to the </span><span data-contrast="auto">start_debugging()</span><span data-contrast="auto"> function. DebugMCP then executes the attacker-controlled payload, ultimately giving the attacker code execution on the victim&#8217;s machine.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<h2><b><span data-contrast="none">Demonstration</span></b><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:299,&quot;335559739&quot;:299}"> </span></h2>
<div style="width: 1906px;" class="wp-video"><video class="wp-video-shortcode" id="video-21323-1" width="1906" height="360" preload="metadata" controls="controls"><source type="video/mp4" src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/video_poc.mp4?_=1" /><a href="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/video_poc.mp4">https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/video_poc.mp4</a></video></div>
<p><span data-contrast="auto">Although the exploit triggers error messages in the VS Code console, the payload is still successfully executed. We used Firefox version 150.0.3, the latest at the time of our research.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><em><b>Note:</b> After the research, Firefox enforced a Local Network Access Protections (version 153). This prevents the a request originating from a domain associated with a public IP to reach more private address networks. This recent feature, currently existing in Chrome and Firefox, isn’t yet generalized to all browsers.  </em></p>
<h2><b><span data-contrast="none">Impact</span></b><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:299,&quot;335559739&quot;:299}"> </span></h2>
<p><span data-contrast="auto">The target is a developer. That means the compromised machine holds live credentials, source code, and trusted access to internal infrastructure.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><span data-contrast="auto">In practice: AWS keys, SSH keys, GitHub tokens in VS Code&#8217;s secret storage, active cloud CLI sessions, VPN tunnels open to the internal network, and push access to production branches would be likely available: a payload that runs as the developer inherits all of it silently.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">The delivery requires no interaction beyond visiting a page, it’s a drive-by attack.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<h2><b><span data-contrast="none">Recommendations</span></b><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:299,&quot;335559739&quot;:299}"> </span></h2>
<p><span data-contrast="auto">Developers using this tool should update to the latest available version. The fix ships after 1.1.4 (version 1.2.0 and later). </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">In addition, it’s recommended to regularly audit which servers are listening on loopback.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Use authentication in your MCP servers and enforce governance to control which MCP server is running in your network and be able to remove it if necessary.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Regarding MCP development more specifically:</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Use middleware that enforce validation (like createMcpExpressApp Since SDK v1.23.0).</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">Validate file path inputs. Reject UNC paths and remote schemes before passing any path to an execution primitive.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<h3><b><span data-contrast="none">Disclosure Timeline</span></b><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:299,&quot;335559739&quot;:299}"> </span></h3>
<ul>
<li data-leveltext="-" data-font="Aptos" data-listid="6" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Aptos&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;-&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="1" data-aria-level="1"><b><span data-contrast="auto">May 19</span></b><span data-contrast="auto">: Issue reported to Microsoft </span><span data-ccp-props="{}"> </span></li>
</ul>
<ul>
<li data-leveltext="-" data-font="Aptos" data-listid="6" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Aptos&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;-&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="2" data-aria-level="1"><b><span data-contrast="auto">May 24</span></b><span data-contrast="auto">: Fix shipped in commit </span><span data-contrast="auto">86776b2</span><span data-contrast="auto">, released as version 1.2.0</span><span data-ccp-props="{}"> </span></li>
</ul>
<ul>
<li data-leveltext="-" data-font="Aptos" data-listid="6" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Aptos&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;-&quot;,&quot;469777815&quot;:&quot;hybridMultilevel&quot;}" data-aria-posinset="3" data-aria-level="1"><b><span data-contrast="auto">September 25: </span></b><span data-contrast="auto">Public disclosure (this blogpost)</span><span data-ccp-props="{}"> </span></li>
</ul>
<h2><b><span data-contrast="none">Conclusion</span></b><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:299,&quot;335559739&quot;:299}"> </span></h2>
<p><span data-contrast="auto">AI-assisted development is quietly rewriting the developer machine&#8217;s threat model. To give an agent useful capabilities, extensions expose local servers, wire in execution primitives, and grant broad access to the filesystem and the debugger. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><span data-contrast="auto">Each of these is a reasonable engineering decision on its own. Together, they turn the workstation into a dense collection of automation endpoints, and those same endpoints, built to be driven by a trusted agent, are equally drivable by an attacker who reaches them. The productivity story and the attack surface story are the same story.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><span data-contrast="auto">Developer environments are where source code, signing keys, pipeline credentials, and cloud sessions converge; compromising one is often a shorter path to production than attacking production directly. </span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p><span data-contrast="auto">This vulnerability was not sophisticated. The techniques here are not new; what’s new is the rate at which capable, unvetted local servers are being deployed onto high-value machines, and the growing ability of AI agents to discover and chain weaknesses autonomously.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;201341983&quot;:0,&quot;335551550&quot;:1,&quot;335551620&quot;:1,&quot;335559685&quot;:0,&quot;335559737&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240,&quot;335559740&quot;:279}"> </span></p>
<p>The post <a href="https://www.imperva.com/blog/from-debugging-to-code-execution-rce-in-microsoft-devlabs-debugmcp/">From Debugging to Code Execution: RCE in Microsoft DevLabs’ DebugMCP?</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.imperva.com/blog/from-debugging-to-code-execution-rce-in-microsoft-devlabs-debugmcp/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<enclosure type="image/jpg" url="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-23-at-8.14.13-PM.png" length="1842" />	</item>
		<item>
		<title>OWASP LLM Top 10 2026: Every Move Points the Same Direction</title>
		<link>https://www.imperva.com/blog/owasp-llm-top-10-2026-what-changed/</link>
					<comments>https://www.imperva.com/blog/owasp-llm-top-10-2026-what-changed/#respond</comments>
		
		<dc:creator><![CDATA[Michael Wright]]></dc:creator>
		<pubDate>Wed, 23 Sep 2026 17:14:56 +0000</pubDate>
				<category><![CDATA[Application Security]]></category>
		<guid isPermaLink="false">https://www.imperva.com/blog/?p=21307</guid>

					<description><![CDATA[<p>This is Post 4 of a four-part series: Post 1: Agentic AI Security: The Chatbot Era Is Over Post 2: Generative AI Security: Why AI Needs a New Kind of Security Post 3: The OWASP LLM Top 10 Was the Warm-Up: What Comes Next The 2026 edition of the the OWASP Top 10 for LLM [&#8230;]</p>
<p>The post <a href="https://www.imperva.com/blog/owasp-llm-top-10-2026-what-changed/">OWASP LLM Top 10 2026: Every Move Points the Same Direction</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><em>This is Post 4 of a four-part series:<br />
Post 1: <a href="https://www.imperva.com/blog/agentic-ai-security-the-chatbot-era-is-over/">Agentic AI Security: The Chatbot Era Is Over</a><br />
Post 2: <a href="https://www.imperva.com/blog/generative-ai-security-why-ai-needs-a-new-kind-of-security/">Generative AI Security: Why AI Needs a New Kind of Security</a><br />
Post 3: <a href="https://www.imperva.com/blog/owasp-llm-top-10-what-comes-next-agentic-mcp/">The OWASP LLM Top 10 Was the Warm-Up: What Comes Next</a><br />
</em></p>
<p>The 2026 edition of the the <a href="https://genai.owasp.org/resource/owasp-genai-llm-top-10-2026/" target="_blank" rel="noopener">OWASP Top 10 for LLM Applications</a>, published by the OWASP GenAI Security Project on August 3, 2026, is easy to skim past. No entry was dropped and no new category was introduced, so at a glance it can read as housekeeping. It is worth a closer look than that. Eight of the ten entries changed position, and one was renamed and widened in scope, which changes what it asks of the teams working against it.</p>
<p>When a framework adds or drops entries, it is usually telling you the threat surface itself has changed. This edition did something more specific. The categories held, but their order was substantially revised and one of them grew, which suggests the original naming was sound while the relative priority had drifted from what teams were meeting in production. Read the movements together and a pattern shows up.</p>
<p><strong>The short version: </strong>the OWASP Top 10 for LLM Applications 2026 kept all ten categories but moved eight of them. Excessive Agency climbed from LLM06 to LLM03, Unbounded Consumption from LLM10 to LLM06 and Misinformation from LLM09 to LLM07, while Improper Output Handling fell from LLM05 to LLM10. System Prompt Leakage was renamed Hidden Context Exposure and broadened to cover everything an application places in front of the model without the user seeing it.</p>
<h2>What changed in the OWASP LLM Top 10 2026</h2>
<p>The table below sets the 2026 order against the 2025 one, listed by 2026 rank.</p>
<table width="576">
<tbody>
<tr>
<td width="72"><strong>2025 rank</strong></td>
<td width="206"><strong>Entry</strong></td>
<td width="72"><strong>2026 rank</strong></td>
<td width="226"><strong>Movement</strong></td>
</tr>
<tr>
<td width="72"><strong>LLM01</strong></td>
<td width="206">Prompt Injection</td>
<td width="72">LLM01</td>
<td width="226">No change</td>
</tr>
<tr>
<td width="72"><strong>LLM02</strong></td>
<td width="206">Sensitive Information Disclosure</td>
<td width="72">LLM02</td>
<td width="226">No change</td>
</tr>
<tr>
<td width="72"><strong>LLM06</strong></td>
<td width="206">Excessive Agency</td>
<td width="72">LLM03</td>
<td width="226">Up 3</td>
</tr>
<tr>
<td width="72"><strong>LLM03</strong></td>
<td width="206">Supply Chain</td>
<td width="72">LLM04</td>
<td width="226">Down 1</td>
</tr>
<tr>
<td width="72"><strong>LLM04</strong></td>
<td width="206">Data and Model Poisoning</td>
<td width="72">LLM05</td>
<td width="226">Down 1</td>
</tr>
<tr>
<td width="72"><strong>LLM10</strong></td>
<td width="206">Unbounded Consumption</td>
<td width="72">LLM06</td>
<td width="226">Up 4</td>
</tr>
<tr>
<td width="72"><strong>LLM09</strong></td>
<td width="206">Misinformation</td>
<td width="72">LLM07</td>
<td width="226">Up 2</td>
</tr>
<tr>
<td width="72"><strong>LLM07</strong></td>
<td width="206">Hidden Context Exposure</td>
<td width="72">LLM08</td>
<td width="226">Down 1, renamed and widened from System Prompt Leakage</td>
</tr>
<tr>
<td width="72"><strong>LLM08</strong></td>
<td width="206">Vector and Embedding Weaknesses</td>
<td width="72">LLM09</td>
<td width="226">Down 1</td>
</tr>
<tr>
<td width="72"><strong>LLM05</strong></td>
<td width="206">Improper Output Handling</td>
<td width="72">LLM10</td>
<td width="226">Down 5</td>
</tr>
</tbody>
</table>
<p>Prompt Injection and Sensitive Information Disclosure held first and second, which surprised nobody. Every other entry sits somewhere new, and the rest of this piece is about why the direction of those moves matters more than the individual rankings.</p>
<h2>Excessive Agency and Unbounded Consumption: the climbers describe applications, not models</h2>
<p>The two biggest climbers are the same kind of risk wearing different clothes. Excessive Agency is about what an application is permitted to do once a model is driving it: which tools it can call, which systems it can reach, how far one decision can travel before a human sees it. Unbounded Consumption is about what happens when that same application meets traffic engineered to abuse it, producing no malware and no traditional indicators, just an enormous bill. Neither is a property of the model. Both are properties of an application in production.</p>
<p>The biggest faller makes the same argument from the other end. Improper Output Handling dropped five places, and not because it stopped happening. It fell because it is the entry the industry already knew how to answer. Rendering untrusted output safely, refusing to execute what came back from an untrusted source, treating downstream consumers as a boundary: application security teams have been practicing that discipline for twenty years. The skill transferred. The novelty did not survive contact with people who already had the muscle.</p>
<p>Setting the renamed entry aside, the three entries that each slipped a place have something in common too. Supply Chain, Data and Model Poisoning, and Vector and Embedding Weaknesses are all risks you address before the application serves its first request, in procurement, in the training pipeline, in how the knowledge base was assembled and secured. They did not become less serious. They became less urgent relative to the things that only exist once the system is live.</p>
<p>Misinformation climbing two places fits once you ask who pays for it. A model that invents a refund policy is a quality problem in a lab and a liability problem in production, and <a href="https://www.americanbar.org/groups/business_law/resources/business-law-today/2024-february/bc-tribunal-confirms-companies-remain-liable-information-provided-ai-chatbot/" target="_blank">a Canadian tribunal has already held Air Canada responsible for what its chatbot told a customer</a> (Moffatt v. Air Canada, 2024). That entry did not move because models got worse. It moved because the consequences arrived.</p>
<p>Read together: the entries that climbed are the ones that only exist while the application is running. The entries that fell are handled before deployment, or handled by controls the industry already had.</p>
<h2>From System Prompt Leakage to Hidden Context Exposure: the rename nobody is discussing</h2>
<p>System Prompt Leakage became Hidden Context Exposure, and it is the most consequential edit in the document.</p>
<p>A system prompt is one specific thing: the instruction block sitting at the top of a conversation, defining the model&#8217;s role and its rules. Hidden context is everything else the application quietly places in front of the model without the user ever seeing it. Retrieved documents. Tool definitions. Prior turns held in memory. Configuration a developer assumed was private because no interface displays it.</p>
<p>The rename takes the entry from one field to an entire supply of runtime input, and it lands the same point the reordering makes. What the application feeds the model has become the attack surface. That is a materially bigger claim than the 2025 wording made, and any content or tooling still describing this entry as system prompt protection is now describing a fraction of it.</p>
<h2>How to read an OWASP LLM Top 10 coverage claim, including ours</h2>
<p>A reordering like this produces a wave of updated coverage claims, and some of them will describe protection across the whole list. Those claims are worth examining rather than accepting, and one question does most of the work: which control fires, inline, at runtime, for this specific entry?</p>
<p>Ask it of the entries that just fell. A poisoned model dependency arrives before a single request is served. At the moment of compromise there is no traffic to inspect, no prompt to score, no response to hold. Something does address that risk, but that something is a procurement process, a posture scan or a signed build pipeline. The same is true of a poorly governed vector store. These are real controls and they matter; they are simply not the same category of thing as a runtime control, and they usually sit with a different team and a different budget.</p>
<p>This is not a criticism of any product. It is the shape of the problem. Runtime protection covers runtime problems. When you meet a claim spanning all ten entries, the useful follow-up is to ask which of the ten are covered by inline enforcement, which by a scanner, which by a partner integration, and which by a policy document, and then to decide whether that composition is what you thought you were buying. A vendor who can answer that cleanly is telling you something about how they think. So is one who cannot.</p>
<p>Apply the same question to us. We would rather you did.</p>
<h2>Where we stand against the 2026 order</h2>
<p>Thales I<a href="https://www.imperva.com/products/ai-application-security/">mperva AI Application Security</a> addresses five entries with runtime enforcement. In 2026 numbering, they are Prompt Injection (LLM01), Sensitive Information Disclosure (LLM02), Unbounded Consumption (LLM06), Hidden Context Exposure (LLM08) and Improper Output Handling (LLM10).</p>
<p>Two of those five moved this year, and the moves cut in opposite directions. Unbounded Consumption climbed four places, which raises the profile of a control we already ship. Improper Output Handling fell five, which lowers the profile of another one we already ship. Reporting the first without the second would be the kind of selective reading this piece is arguing against.</p>
<p>Two of those five are also where our next work lands, and they are connected. Hidden Context Exposure now covers tool definitions, and Excessive Agency is the question of what an application is permitted to do once a model is driving it. We are adding tool call guardrails that check whether the specific tool being called is permitted, and the tool definitions themselves are what we look at next. Today we detect and monitor tool calls. Checking them against what is allowed is the step after that, and it is better to say so plainly than to let a coverage table imply it already exists.</p>
<p>The other five entries need different tools, and we would rather name them than imply otherwise. Supply Chain and Data and Model Poisoning are build-time and procurement problems. Vector and Embedding Weaknesses belongs with the data security controls sitting in front of the retrieval pipeline. Misinformation is evaluation and grounding work. Excessive Agency is the one to watch: it is the entry moving fastest toward runtime, it is where the agentic controls across this whole category are heading, and at number three it is now the highest-ranked risk that most security programs have no inline answer for at all.</p>
<h2>The list caught up with agentic AI</h2>
<p>In a recent piece we argued that the <a href="https://www.imperva.com/blog/owasp-llm-top-10-what-comes-next-agentic-mcp/">LLM Top 10 had been the warm-up</a>, and that the frameworks describing agentic and MCP risk had already been published while most security programs were still resourcing against the first list. The 2026 edition is that argument told from inside the framework itself.</p>
<p>Excessive Agency at number three is an agentic risk sitting near the top of an LLM list. Hidden Context Exposure is the retrieval and tool layer being named as attack surface. Neither entry is about a model producing text. Both are about a system taking action on the strength of what it was fed. The list has started describing applications that act, which is the same shift the newer frameworks were built for.</p>
<p>A practical exercise for this quarter: take the four entries that moved most, and for each one write down which control in your own environment would fire while the attack was in progress, not after it appeared in a report. The gaps in that list are what the 2026 reordering is pointing at.</p>
<p>Thales’s Imperva AI Application Security is purpose-built runtime protection for AI applications, agents, and the ecosystems behind them, deployable in-app, at the Imperva edge, or via API, standalone or as part of Imperva&#8217;s unified application security platform. Our white paper, <a href="https://www.imperva.com/resources/resource-library/white-papers/beyond-the-llm-top-10-securing-ai-applications-agents-and-the-ecosystems-behind-them/">Beyond the LLM Top 10</a>, maps the agentic and MCP threat surface against the published frameworks.</p>
<h2>Frequently asked questions about the OWASP LLM Top 10 2026</h2>
<h3>What changed in the OWASP Top 10 for LLM Applications 2026?</h3>
<p>The 2026 edition, published by the OWASP GenAI Security Project on August 3, 2026, added and removed no categories. Eight of the ten entries changed position: Excessive Agency rose from LLM06 to LLM03, Unbounded Consumption from LLM10 to LLM06 and Misinformation from LLM09 to LLM07, while Improper Output Handling fell from LLM05 to LLM10. Prompt Injection (LLM01) and Sensitive Information Disclosure (LLM02) held their places, and System Prompt Leakage was renamed Hidden Context Exposure.</p>
<h3>What is Hidden Context Exposure in the OWASP LLM Top 10?</h3>
<p>Hidden Context Exposure (LLM08 in 2026) replaces System Prompt Leakage (LLM07 in 2025). It widens the entry from the system prompt alone to everything an application places in front of the model without the user seeing it: retrieved documents, tool definitions, prior turns held in memory and configuration a developer assumed was private.</p>
<h3>Why did Excessive Agency move up to LLM03?</h3>
<p>Excessive Agency describes what an application is permitted to do once a model is driving it: which tools it can call, which systems it can reach and how far one decision can travel before a human sees it. It climbed three places, from LLM06 to LLM03, as agentic applications that take actions moved into production.</p>
<h3>Which OWASP LLM Top 10 risks can runtime protection address?</h3>
<p>Runtime controls act on live traffic: prompts, responses and tool calls. Supply Chain and Data and Model Poisoning are build-time and procurement problems, Vector and Embedding Weaknesses belongs with data security controls in front of the retrieval pipeline, and Misinformation is evaluation and grounding work. When a vendor claims coverage of all ten entries, ask which are covered by inline enforcement, which by a scanner, which by a partner integration and which by a policy document.</p>
<p>Read more in our white paper: <a href="/resources/resource-library/white-papers/beyond-the-llm-top-10-securing-ai-applications-agents-and-the-ecosystems-behind-them/">Beyond the LLM Top 10</a>.</p>
<p>The post <a href="https://www.imperva.com/blog/owasp-llm-top-10-2026-what-changed/">OWASP LLM Top 10 2026: Every Move Points the Same Direction</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.imperva.com/blog/owasp-llm-top-10-2026-what-changed/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<enclosure type="image/jpg" url="https://www.imperva.com/blog/wp-content/uploads/sites/9/2021/05/Web-Application-Gateway-e1622210611627.png" length="845" />	</item>
		<item>
		<title>Imperva Customers Protected Against StyleSmuggler (CVE-2026-75650) in Adobe Commerce and Magento Open Source</title>
		<link>https://www.imperva.com/blog/imperva-customers-protected-against-stylesmuggler-cve-2026-75650-in-adobe-commerce-and-magento-open-source/</link>
					<comments>https://www.imperva.com/blog/imperva-customers-protected-against-stylesmuggler-cve-2026-75650-in-adobe-commerce-and-magento-open-source/#respond</comments>
		
		<dc:creator><![CDATA[Gabi Sharadin]]></dc:creator>
		<pubDate>Thu, 10 Sep 2026 17:43:37 +0000</pubDate>
				<category><![CDATA[Imperva Threat Research]]></category>
		<guid isPermaLink="false">https://www.imperva.com/blog/?p=21297</guid>

					<description><![CDATA[<p>TL;DR: CVE-2026-75650, dubbed StyleSmuggler, is a critical vulnerability affecting Adobe Commerce and Magento Open Source. The vulnerability allows an unauthenticated attacker to inject malicious PHP code into Magento’s template system and achieve remote code execution. Adobe assigned the vulnerability a CVSS score of 10.0 and released an emergency hotfix after exploitation was observed in the wild. Imperva Cloud WAF and On-Prem WAF [&#8230;]</p>
<p>The post <a href="https://www.imperva.com/blog/imperva-customers-protected-against-stylesmuggler-cve-2026-75650-in-adobe-commerce-and-magento-open-source/">Imperva Customers Protected Against StyleSmuggler (CVE-2026-75650) in Adobe Commerce and Magento Open Source</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><b><i><span data-contrast="auto">TL;DR:</span></i></b><i><span data-contrast="auto"> </span></i><a href="https://www.cve.org/CVERecord?id=CVE-2026-75650" target="_blank" rel="noopener"><i><span data-contrast="none">CVE-2026-75650</span></i></a><i><span data-contrast="auto">, dubbed StyleSmuggler, is a critical vulnerability affecting Adobe Commerce and Magento Open Source. The vulnerability allows an unauthenticated attacker to inject malicious PHP code into Magento’s template system and achieve remote code execution. Adobe assigned the vulnerability a CVSS score of 10.0 and released an emergency hotfix after exploitation was observed in the wild. Imperva Cloud WAF and On-Prem WAF customers are protected against exploitation attempts associated with CVE-2026-75650.</span></i><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:0,&quot;335551620&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<h2><span data-contrast="none">Understanding the StyleSmuggler Vulnerability</span><span data-ccp-props="{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:160,&quot;335559739&quot;:80}"> </span></h2>
<p><span data-contrast="auto">StyleSmuggler is an improper neutralization vulnerability in Magento’s template engine. Attackers can abuse the processing of styles properties to smuggle malicious PHP code past existing safeguards and into content that Magento later renders.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:0,&quot;335551620&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><span data-contrast="auto">The attack occurs in two stages. First, the attacker sends a crafted request that causes malicious PHP code to be stored within Magento-generated content, such as a failure report. The attacker then triggers application functionality that renders the poisoned content, including Magento’s standard failed-payment email process. When the template is rendered, the injected PHP executes on the server.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:0,&quot;335551620&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><span data-contrast="auto">No authentication or user interaction is required. The recipient does not need to open the failed-payment email, and the attack can succeed even if the email is never delivered. Successful exploitation gives the attacker arbitrary code execution in the context of the Magento application, potentially enabling malware deployment, persistent access, credential theft, payment-data compromise, or further movement within the environment. The vulnerability affects </span><a href="https://helpx.adobe.com/security/products/magento/apsb26-146.html" target="_blank" rel="noopener"><span data-contrast="none">supported versions</span></a><span data-contrast="auto"> across multiple Adobe Commerce and Magento Open Source branches, including systems that had received recent security patches.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:0,&quot;335551620&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><span data-contrast="auto">Observed post-exploitation activity has included the deployment of persistent Linux backdoors disguised as legitimate processes such as kworker, fc-cache, and chronyd. Researchers have also identified a separate campaign using the vulnerability to install a PHP web shell, demonstrating that multiple threat actors are already attempting to operationalize StyleSmuggler.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:0,&quot;335551620&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<h2><span data-contrast="none">What Imperva Has Seen So Far</span><span data-ccp-props="{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:160,&quot;335559739&quot;:80}"> </span></h2>
<p><span data-contrast="auto">Imperva has observed exploitation activity targeting websites across 15 countries, indicating that StyleSmuggler scanning and attack attempts are already geographically widespread. The United States accounts for 25% of targeted sites, followed by Mexico at 15.9%, Spain at 14%, and Singapore at 13.6%.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:0,&quot;335551620&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><img class="lazyload alignnone size-full wp-image-21299 lazyload" alt="Screenshot 2026 09 10 at 10.40.57 AM" width="1582" height="932" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-10-at-10.40.57-AM.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-10-at-10.40.57-AM.png 1582w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-10-at-10.40.57-AM-300x177.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-10-at-10.40.57-AM-1024x603.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-10-at-10.40.57-AM-768x452.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-10-at-10.40.57-AM-1536x905.png 1536w" sizes="(max-width: 1582px) 100vw, 1582px" /></p>
<p><span class="TextRun SCXW106553014 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SCXW106553014 BCX0">Retail websites </span><span class="NormalTextRun SCXW106553014 BCX0">represent</span><span class="NormalTextRun SCXW106553014 BCX0"> the largest share of observed targets at 39.5%, consistent with Magento’s extensive use across ecommerce environments. Lifestyle sites account for another 19.5% of targets, followed by healthcare at 17.9%.</span></span><span class="EOP SCXW106553014 BCX0" data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:0,&quot;335551620&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><img class="lazyload alignnone size-full wp-image-21298 lazyload" alt="Screenshot 2026 09 10 at 10.41.25 AM" width="1582" height="932" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-10-at-10.41.25-AM.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-10-at-10.41.25-AM.png 1582w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-10-at-10.41.25-AM-300x177.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-10-at-10.41.25-AM-1024x603.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-10-at-10.41.25-AM-768x452.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/09/Screenshot-2026-09-10-at-10.41.25-AM-1536x905.png 1536w" sizes="(max-width: 1582px) 100vw, 1582px" /></p>
<p><span data-contrast="auto">Attack traffic has primarily automated attacks. While client identifiers can be modified or spoofed, their prevalence is consistent with attackers using scripted tools to automate scanning and exploitation rather than interacting through conventional web browsers.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:0,&quot;335551620&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p><b><span data-contrast="auto">Imperva protections are actively identifying and blocking malicious requests associated with the StyleSmuggler attack chain before they can reach protected applications.</span></b><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:0,&quot;335551620&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<h2><span data-contrast="none">Conclusion</span><span data-ccp-props="{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:160,&quot;335559739&quot;:80}"> </span></h2>
<p><span data-contrast="auto">CVE-2026-75650 poses an immediate risk: it enables unauthenticated remote code execution, has already been weaponized, and can give attackers direct control over ecommerce servers. Adobe Commerce and Magento Open Source administrators should apply the VULN-39341 hotfix immediately and investigate potentially exposed systems for signs of compromise. As exploitation began before a patch was available, applying the hotfix does not remove malware or persistence mechanisms that may already be present.</span><span data-ccp-props="{}"> </span></p>
<p><b><i><span data-contrast="auto">Imperva Cloud WAF and On-Prem WAF customers are protected against exploitation attempts associated with StyleSmuggler. </span></i></b><span data-contrast="auto">Imperva will continue monitoring the campaign as attackers refine their payloads and additional activity emerges.</span><span data-ccp-props="{&quot;134233117&quot;:false,&quot;134233118&quot;:false,&quot;335551550&quot;:0,&quot;335551620&quot;:0,&quot;335559738&quot;:240,&quot;335559739&quot;:240}"> </span></p>
<p>The post <a href="https://www.imperva.com/blog/imperva-customers-protected-against-stylesmuggler-cve-2026-75650-in-adobe-commerce-and-magento-open-source/">Imperva Customers Protected Against StyleSmuggler (CVE-2026-75650) in Adobe Commerce and Magento Open Source</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.imperva.com/blog/imperva-customers-protected-against-stylesmuggler-cve-2026-75650-in-adobe-commerce-and-magento-open-source/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Bring Your Own CA: Introducing the Thales Imperva SSL Integration Center, Featuring DigiCert Trust Lifecycle Manager</title>
		<link>https://www.imperva.com/blog/ssl-integration-center-digicert-trust-lifecycle-manage/</link>
					<comments>https://www.imperva.com/blog/ssl-integration-center-digicert-trust-lifecycle-manage/#respond</comments>
		
		<dc:creator><![CDATA[Michael Wright]]></dc:creator>
		<pubDate>Mon, 24 Aug 2026 09:01:34 +0000</pubDate>
				<category><![CDATA[Application Security]]></category>
		<guid isPermaLink="false">https://www.imperva.com/blog/?p=21250</guid>

					<description><![CDATA[<p>Somewhere in your estate right now, a certificate is counting down to its expiry date. Today you probably know which one, because renewals still come around annually and someone owns the calendar. The industry is taking that comfort away: the CA/Browser Forum has voted to cut the maximum TLS certificate lifespan to 47 days by [&#8230;]</p>
<p>The post <a href="https://www.imperva.com/blog/ssl-integration-center-digicert-trust-lifecycle-manage/">Bring Your Own CA: Introducing the Thales Imperva SSL Integration Center, Featuring DigiCert Trust Lifecycle Manager</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Somewhere in your estate right now, a certificate is counting down to its expiry date. Today you probably know which one, because renewals still come around annually and someone owns the calendar. The industry is taking that comfort away: the CA/Browser Forum has voted to cut the maximum TLS certificate lifespan to 47 days by 2029, a decision we looked at in detail in <a href="https://www.imperva.com/blog/the-future-of-ssl-certificate-management-adapting-to-shortened-renewal-periods/">our piece on shortened renewal periods</a>. Renewals that happen once a year will soon happen every few weeks, and every manual touchpoint in that process becomes a potential outage. The math stops working.</p>
<p>The honest complication is that most enterprises do not live in a single-vendor world. You may run your own internal PKI. You may have standardized on a dedicated Certificate Lifecycle Management (CLM) platform. You may answer to compliance mandates that dictate exactly which Certificate Authority issues your certificates, and how. In those environments, visibility and control across every certificate matters as much as automating the renewals themselves. Until now, connecting those established workflows to Imperva meant manual effort, and manual effort is exactly what shrinking lifecycles no longer allow.</p>
<p>Today we are introducing the <strong>SSL Integration Center</strong>: an integration framework connecting Imperva Cloud WAF with leading Certificate Lifecycle Management platforms. It launches with its first supported integration, the <a href="https://www.digicert.com/trust-lifecycle-manager" target="_blank">DigiCert Trust Lifecycle Manager (TLM)</a> Agent.</p>
<h2>Your CLM stays in charge for certificate lifecycle management</h2>
<p>The SSL Integration Center is not a new product or another console to learn. It is an integration framework, and the experience runs from the side you already live in: you configure the integration from within your CLM platform, and your CLM remains the place where certificates are managed. Once connected, two things happen from there. You can see all of your Imperva-managed domains and the SSL coverage status of each one, directly in your certificate workflow. And the complete certificate lifecycle cadence, issuance, renewal and deployment to Imperva, runs automatically under the policies your CLM already enforces. Imperva&#8217;s role is to integrate smoothly into the workflow you have, supplying application and SSL-coverage visibility and taking automated deployment off your hands. DigiCert is the first integration, and it sets the pattern for the CLM vendors that follow.</p>
<h2>Thales-managed or customer-managed: your choice</h2>
<p>Many organizations choose Thales-managed certificates because that removes the operational load of provisioning, renewal, monitoring and deployment in one move, and for them nothing changes. Others cannot adopt a fully managed approach: compliance requirements, PKI investments, established CLM platforms and governance policies often require a customer to keep control of their own certificate ecosystem. The Integration Center is built for that second group. You keep your CA, your CLM and your lifecycle processes, exactly where they run today, and Imperva plugs into them. Governance stays yours, and so does the console.</p>
<h2>Starting with a leader: DigiCert Trust Lifecycle Manager</h2>
<p>DigiCert TLM gives enterprises one place to discover, govern, automate and see certificates across cloud, hybrid and on-premises environments. It builds an organization-wide certificate inventory, enforces consistent cryptographic policy, and replaces surprise expirations with automated renewals. A useful way to think about the pairing: TLM is the system of record for your certificates, and the Integration Center is the delivery route into the applications Imperva protects.</p>
<p>With this integration, the DigiCert TLM Agent automates certificate issuance, renewal and deployment straight into Imperva. Under the hood, a <strong>post-enrollment script</strong> securely uploads the certificate chain and private key to Imperva through the Provisioning API, so a certificate governed in TLM arrives at your protected applications without anyone touching it. It runs on both Linux and Windows.</p>
<p>The value of that automation is documented. In a commissioned Total Economic Impact study, Forrester Consulting found organizations standardizing on DigiCert ONE, the platform behind Trust Lifecycle Manager, achieved <strong>96% fewer outages</strong> from expired or misconfigured certificates, and a <strong>312% return on investment</strong> over three years.</p>
<p><span style="font-size: 14px;"><em>Source: </em><a href="https://www.digicert.com/news/total-economic-report-shows-big-roi-with-digicert-one" target="_blank"><em>The Total Economic Impact<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" /> of DigiCert ONE (July 2025)</em></a><em>, a commissioned study conducted by Forrester Consulting on behalf of DigiCert. Results are based on a composite organization derived from customer interviews. Forrester does not endorse DigiCert or its offerings.</em></span></p>
<h2>How the DigiCert TLM integration works</h2>
<ul>
<li><strong>Govern in DigiCert TLM. </strong>Your certificate is issued and managed centrally, under the policies your organization already enforces.</li>
<li><strong>Automate with the TLM Agent. </strong>A post-enrollment script runs on issuance or renewal and packages the certificate chain and private key.</li>
<li><strong>Deploy through the Provisioning API. </strong>The script securely uploads the certificate to your Imperva cloud account and puts it to work protecting your applications. No manual upload. No missed renewal window.</li>
</ul>
<h2>What this means for your team</h2>
<ul>
<li><strong>Continuous, compliant TLS protection. </strong>Issuance, renewal and deployment of custom certificates run without manual intervention, so your encryption stays current as lifecycles shrink.</li>
<li><strong>Full bring-your-own-CA automation. </strong>If you use your own Certificate Authority and custom certificates, the entire lifecycle can now run end to end.</li>
<li><strong>Fewer outages, less toil. </strong>Removing the manual steps removes the TLS outages that come from missed renewals, and frees your team from certificate babysitting.</li>
<li><strong>Your Imperva estate, visible from your CLM.</strong> Once connected, your Imperva-managed domains and the SSL coverage status of each appear inside your certificate workflow, so DigiCert&#8217;s organisation-wide discovery and Imperva&#8217;s application coverage read as one picture, without switching consoles.</li>
</ul>
<h2>A certificate automation ecosystem that grows with you</h2>
<p>Shorter certificate lifecycles are the new baseline, and they reward the organizations that automate. The SSL Integration Center makes that automation work on your terms: the CA you trust, the CLM platform you have standardized on, the compliance posture you are held to. It sits alongside Thales&#8217;s own SSL management capabilities, including certificate visibility, site coverage monitoring, notifications and real-time SSL health monitoring. DigiCert Trust Lifecycle Manager is the first integration and it will not be the last; each CLM vendor added becomes one more certificate workflow that arrives at your applications without a human in the renewal loop.</p>
<p>That certificate counting down in your estate? Under TLM and the Integration Center, its renewal has already happened by the time you would have thought to check.</p>
<p>It is also one thread in a wider fabric. Imperva integrates across the tools enterprises already run, from SIEM and ITSM platforms to API gateways, scanners and cloud providers, through the Imperva Technology Alliance Program. If your certificate stack is the workflow we meet today, the rest of your stack has a meeting point there too.</p>
<h2>Get started with the SSL Integration Center</h2>
<p>If you are a Thales Imperva Cloud WAF customer using DigiCert Trust Lifecycle Manager, you can configure the integration from your TLM console today. For step-by-step setup, see the <a href="https://docs-cybersec.thalesgroup.com/bundle/cloud-application-security/page/more/integrate-custom-certificates.htm" target="_blank">Imperva documentation on integrating custom certificates</a> and the <a href="https://www.digicert.com/integrations/imperva" target="_blank">DigiCert + Imperva integration overview</a>.</p>
<p>The post <a href="https://www.imperva.com/blog/ssl-integration-center-digicert-trust-lifecycle-manage/">Bring Your Own CA: Introducing the Thales Imperva SSL Integration Center, Featuring DigiCert Trust Lifecycle Manager</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.imperva.com/blog/ssl-integration-center-digicert-trust-lifecycle-manage/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<enclosure type="image/jpg" url="https://www.imperva.com/blog/wp-content/uploads/sites/9/2022/05/Blog-image-26-e1652971621578.jpg" length="845" />	</item>
		<item>
		<title>The OWASP LLM Top 10 Was the Warm-Up: What Comes Next</title>
		<link>https://www.imperva.com/blog/owasp-llm-top-10-what-comes-next-agentic-mcp/</link>
					<comments>https://www.imperva.com/blog/owasp-llm-top-10-what-comes-next-agentic-mcp/#respond</comments>
		
		<dc:creator><![CDATA[Michael Wright]]></dc:creator>
		<pubDate>Sun, 16 Aug 2026 04:23:05 +0000</pubDate>
				<category><![CDATA[Application Security]]></category>
		<guid isPermaLink="false">https://www.imperva.com/blog/?p=21240</guid>

					<description><![CDATA[<p>This is Post 3 of a four-part series: Post 1: Agentic AI Security: The Chatbot Era Is Over Post 2: Generative AI Security: Why AI Needs a New Kind of Security Post 4: OWASP LLM Top 10 2026: Every Move Points the Same Direction When the OWASP Top 10 for LLM Applications arrived, it did [&#8230;]</p>
<p>The post <a href="https://www.imperva.com/blog/owasp-llm-top-10-what-comes-next-agentic-mcp/">The OWASP LLM Top 10 Was the Warm-Up: What Comes Next</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><em>This is Post 3 of a four-part series:<br />
Post 1: <a href="https://www.imperva.com/blog/agentic-ai-security-the-chatbot-era-is-over/">Agentic AI Security: The Chatbot Era Is Over</a><br />
Post 2: <a href="https://www.imperva.com/blog/generative-ai-security-why-ai-needs-a-new-kind-of-security/">Generative AI Security: Why AI Needs a New Kind of Security</a><br />
Post 4: <a href="https://www.imperva.com/blog/owasp-llm-top-10-2026-what-changed/">OWASP LLM Top 10 2026: Every Move Points the Same Direction</a><br />
</em></p>
<p>When the OWASP Top 10 for LLM Applications arrived, it did the industry a real service. It gave security teams a stable, vendor-neutral vocabulary for a threat surface that was moving too fast to describe. Prompt injection, sensitive information disclosure, system prompt leakage, improper output handling, unbounded consumption: five of those ten account for the bulk of what actually shows up in red-team exercises and public incidents.</p>
<p>Every framework earns its keep by naming what defenders are already fighting. Which is exactly why the next part matters: the next lists are not coming. They have already arrived. Most security programs simply have not caught up with them yet.</p>
<h2>The three OWASP lists that now define AI security</h2>
<p>Three published OWASP lists now cover the AI stack end to end. Together they are the checklist most security programs are not yet resourced against:</p>
<p><strong>OWASP Top 10 for LLM Applications (2025)</strong> &#8211; the conversation layer. Prompt injection, sensitive information disclosure, system prompt leakage, improper output handling and unbounded consumption are the five that dominate real incidents.</p>
<p><strong>OWASP Top 10 for Agentic Applications (2026)</strong> &#8211; the systems that act. Released 9 December 2025 by the OWASP GenAI Security Project. Ten risks, prefixed ASI, covering what happens when AI stops answering and starts doing.</p>
<p><strong>OWASP MCP Top 10 (MCP01:2025-MCP10:2025)</strong> &#8211; the connective tissue. Currently in beta (Phase 3, beta release and pilot testing), covering the Model Context Protocol layer that wires assistants to real systems and data.</p>
<h2>The OWASP agentic and MCP Top 10 lists are published.  The budgets are not.</h2>
<p>In December 2025, the OWASP GenAI Security Project published the OWASP Top 10 for Agentic Applications (2026), covering the risks that appear when AI stops answering questions and starts taking actions: agent goal hijack (ASI01), tool misuse and exploitation (ASI02), identity and privilege abuse (ASI03), memory and context poisoning (ASI06), insecure inter-agent communication (ASI07) and rogue agents (ASI10).</p>
<p>Alongside it, <a href="https://owasp.org/www-project-mcp-top-10/" target="_blank">OWASP’s MCP Top 10 project</a> is codifying the risks of the Model Context Protocol, the standard that connects AI assistants to real systems and data. It is a young list, currently in beta &#8211; Phase 3, beta release and pilot testing, with entries carrying the MCP01:2025 through MCP10:2025 designation &#8211; and it is already one of the most useful documents in AI security, because it names the attack patterns defenders are meeting right now. Three of them deserve particular attention.</p>
<p><strong>Command injection and execution (MCP05)</strong>. An AI agent executes system commands built from untrusted input, without proper validation. An adversary who compromises the toolchain gets their work carried forward by the agent itself, with the agent’s legitimate permissions. The prompt was never touched. The model behaved exactly as designed. The compromise came in through the tools.</p>
<p><strong>Tool poisoning (MCP03)</strong>. The model is handed a list of tools it may call, and it trusts their definitions and their outputs. Poison either one and you have redirected the application’s behavior without a single suspicious token appearing in the conversation.</p>
<p><strong>Insufficient authentication and authorization (MCP07)</strong>. MCP servers, tools, and agents interacting without properly verifying identity or enforcing access controls. Who is allowed to call this tool? Which agent may delegate to which? In most environments today the answer is: whoever asks. That is not a vulnerability in a model. It is a missing identity layer for machines.</p>
<p>One more entry is worth a mention because it will sound familiar to anyone tracking shadow IT: <strong>shadow MCP servers (MCP09)</strong>, the unapproved deployments running outside security governance, often on default credentials. The shadow AI problem now has an OWASP number. For the practical exposures behind these entries, see <a href="/blog/mcp-server-security-blind-spot-ai-stack/">MCP Server Security: The Blind Spot in Your AI Stack</a>.</p>
<p>None of these are theoretical. All of them get easier as organizations wire agents into more systems. And none of them have the household-name status that prompt injection now enjoys, which means the frameworks are ahead of most security programs’ resourcing. That is a new and uncomfortable position: the industry usually waits years for its threat lists. This time the lists arrived before the budgets.</p>
<h2>History does not repeat, but it files tickets</h2>
<p>We have watched this movie before. Monolithic applications got the OWASP Top 10. API-based applications got the API Security Top 10, because the attacks changed shape when the architecture did. AI applications and agents are the next architecture, and this time the pattern completed itself faster than ever: the LLM Top 10 for the conversation layer, the Agentic Top 10 for the systems that act, and the MCP Top 10 for the connective tissue between them.</p>
<p>So the catch-up question for security teams is no longer “what threats might emerge?” It is “which published OWASP entries is my program actually resourced against?” And the question for vendors sharpens the same way. Not “do you block prompt injection?” but “walk me through the MCP Top 10 and tell me what you see, and what you can control, beyond the prompt.”</p>
<p>The LLM Top 10 taught the industry to take AI threats seriously. The warm-up worked. The event has already started.</p>
<h2>Frequently asked questions about the OWASP AI Top 10 lists</h2>
<p><strong>What is the OWASP LLM Top 10?</strong> The OWASP Top 10 for Large Language Model Applications is a vendor-neutral list of the ten most critical security risks in LLM-based applications, maintained by the OWASP GenAI Security Project. Prompt injection, sensitive information disclosure, system prompt leakage, improper output handling and unbounded consumption account for most of what shows up in red-team exercises and public incidents.</p>
<p><strong>Is there an OWASP Top 10 for AI agents?</strong> Yes. The OWASP Top 10 for Agentic Applications (2026) was released on 9 December 2025. Its ten entries carry the ASI prefix and run from agent goal hijack (ASI01) to rogue agents (ASI10).</p>
<p><strong>What is the OWASP MCP Top 10?</strong> A list codifying the security risks of the Model Context Protocol, the standard connecting AI assistants to real systems and data. Entries run MCP01:2025 to MCP10:2025 and include tool poisoning (MCP03), command injection and execution (MCP05), insufficient authentication and authorization (MCP07) and shadow MCP servers (MCP09). The project is in beta.</p>
<p><strong>How many of the OWASP LLM Top 10 does Imperva address?</strong> Five out of the box: prompt injection and jailbreaking, sensitive information disclosure, system prompt leakage, improper output handling and unbounded consumption.</p>
<p><strong>What should I ask an AI security vendor?</strong> Not &#8220;do you block prompt injection?&#8221; but &#8220;walk me through the MCP Top 10 and tell me what you see, and what you can control, beyond the prompt.&#8221;</p>
<p><em><a href="https://www.imperva.com/products/ai-application-security/">Thales’s Imperva AI Application Security</a> addresses five of the OWASP LLM Top 10 out of the box. We believe the industry’s next frameworks will be written about agents and toolchains. Thales announced the AI Security Fabric in December 2025, with an MCP security gateway and runtime access control for agentic AI interactions on the 2026 roadmap. Our white paper, <a href="/resources/resource-library/white-papers/beyond-the-llm-top-10-securing-ai-applications-agents-and-the-ecosystems-behind-them/">Beyond the LLM Top 10</a>, maps that terrain.</em></p>
<p>The post <a href="https://www.imperva.com/blog/owasp-llm-top-10-what-comes-next-agentic-mcp/">The OWASP LLM Top 10 Was the Warm-Up: What Comes Next</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.imperva.com/blog/owasp-llm-top-10-what-comes-next-agentic-mcp/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<enclosure type="image/jpg" url="https://www.imperva.com/blog/wp-content/uploads/sites/9/2024/03/shutterstock_1071270287-22.jpg" length="845" />	</item>
		<item>
		<title>Imperva API Security Token &#038; Authentication Risk Report: Nearly 40% of APIs Face Multiple Authentication Risks</title>
		<link>https://www.imperva.com/blog/imperva-api-security-token-authentication-risk-report-nearly-40-of-apis-face-multiple-authentication-risks/</link>
					<comments>https://www.imperva.com/blog/imperva-api-security-token-authentication-risk-report-nearly-40-of-apis-face-multiple-authentication-risks/#respond</comments>
		
		<dc:creator><![CDATA[Rohit Kumar]]></dc:creator>
		<pubDate>Thu, 13 Aug 2026 09:19:33 +0000</pubDate>
				<category><![CDATA[Application Security]]></category>
		<guid isPermaLink="false">https://www.imperva.com/blog/?p=21228</guid>

					<description><![CDATA[<p>Every year, the security industry publishes benchmark reports built more or less the same way: pick a handful of common vulnerabilities, measure how often they show up, publish the percentages, and move on. We just finished our second year running one of those reports — and the most important thing we found wasn&#8217;t a percentage. [&#8230;]</p>
<p>The post <a href="https://www.imperva.com/blog/imperva-api-security-token-authentication-risk-report-nearly-40-of-apis-face-multiple-authentication-risks/">Imperva API Security Token &#038; Authentication Risk Report: Nearly 40% of APIs Face Multiple Authentication Risks</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Every year, the security industry publishes benchmark reports built more or less the same way: pick a handful of common vulnerabilities, measure how often they show up, publish the percentages, and move on. We just finished our second year running one of those reports — and the most important thing we found wasn&#8217;t a percentage. It was a pattern hiding underneath all of them. </p>
<p>This is <a href="/resources/resource-library/reports/imperva-api-security-token-authentication-risk-report/?6">Imperva API Security&#8217;s 2026 Token &#038; Authentication Risk Report</a>: a year-over-year look at how organizations actually handle JSON Web Tokens (JWTs), Basic Authentication, and token lifecycles, based on real detection data — not survey answers — across 1,104 customer environments and 32,725 live API endpoints. Some of what we found is good news. Some of them should genuinely worry you. And one finding, buried in a few layers beneath the headline numbers, is the reason we think most organizations are fixing the wrong things first. </p>
<h2>What We Measured, and Why It&#8217;s Worth Trusting </h2>
<p>This is the second year of this benchmark, which matters more than it might seem. One year of data tells you what&#8217;s happening. Two years of consistent measurement tells you what&#8217;s changing — and change is where the real signal lives. </p>
<p>We tracked five risk categories, unchanged from last year&#8217;s methodology: whether JWTs contain sensitive data they shouldn&#8217;t, whether they&#8217;re signed with weak algorithms, whether they&#8217;re issued with excessively long lifespans, whether Basic Authentication with raw credentials is still in use, and whether tokens keep granting access after they should have expired. Every number below is a share of real detections, not a projection. </p>
<p><img data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/risk-prevalence-by-category.jpg" alt="risk prevalence by category" width="1958" height="1066" class="lazyload aligncenter size-full wp-image-21230 lazyload" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/risk-prevalence-by-category.jpg 1958w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/risk-prevalence-by-category-300x163.jpg 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/risk-prevalence-by-category-1024x557.jpg 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/risk-prevalence-by-category-768x418.jpg 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/risk-prevalence-by-category-1536x836.jpg 1536w" sizes="(max-width: 1958px) 100vw, 1958px" /></p>
<h2The Good News First </h2>
<p>Three of the five risks have improved. Weak signing algorithms dropped from 19.0% to 15.2% of detections — a 20% relative decline, the sharpest improvement in the study. Basic Authentication with raw credentials fell from 9.0% to 7.3%. Long-lived tokens eased slightly, from 21.0% to 19.2%. </p>
<p>These three have something in common: each map to a specific, well-publicized fix. Use a stronger algorithm. Migrate to OAuth2 or mTLS. Shorten your token lifetimes. None of that is a secret, and the data suggests teams that heard the advice actually acted on it. </p>
<p>That&#8217;s a genuine win worth taking seriously. It&#8217;s also, as it turns out, the easy part. </p>
<h2The Two Numbers That Should Worry You </h2>
<p>The two risk categories that got worse this year aren&#8217;t the ones with a tidy, well-known fix. They live in implementation details, and, not coincidentally, they&#8217;re the two with the most direct line to actual data exposure. </p>
<p>Sensitive data inside tokens climbed to 49.8% of all detections, up from 46.0% last year — already the largest risk category in the study, now touching essentially half of everything we measured. That number deserves more alarm than it might get on first read: a JWT isn&#8217;t encrypted by default. It&#8217;s typically just base64-encoded, which is not the same thing — anyone who can see the token can read what&#8217;s inside it; no exploit required. A JWT doesn&#8217;t need to be &#8220;hacked&#8221; to leak data. It just needs to pass through an ordinary place in a modern stack: a log line capturing request headers, browser storage on a shared machine, a support ticket where a developer pastes a request for debugging. If the token carries a name, an email, an account number, every one of those mundane, everyday paths becomes a potential exposure event. </p>
<p>Expired-token access jumped from 5.0% to 8.5% — a 70% relative increase, the sharpest move of any category we track, in either direction. This one is arguably more alarming precisely because it&#8217;s the more mechanical risk to get right. Deciding what counts as &#8220;sensitive&#8221; involves judgment. Enforcing that a token stops working after its exp claim has passed does not. When it fails anyway, it&#8217;s usually because expiration was checked in one place — a central auth service — and never independently re-verified everywhere else the token gets used. Every other assumption a security team makes about tokens rests on expiration being the backstop. When that backstop doesn&#8217;t hold, everything built on top of it gets quietly weaker too. </p>
<p>We can&#8217;t say with certainty why either number moved the way it did — a mix of factors is plausible, including genuine changes in practice, improvements in our own detection, and shifts in which organizations were measured each year. What we can say is that the direction, for both, is the wrong one, two years running. </p>
<h2>The Finding That Changes the Story </h2>
<p>Here&#8217;s what we didn&#8217;t expect going in: authentication risk doesn&#8217;t usually show up alone. </p>
<p>We went endpoint by endpoint and asked a specific question — how often do these five risks appear together, on the same API, at the same time? The answer: 13,016 of the 32,725 endpoints we analyzed, nearly 40%, carried more than one authentication risk simultaneously. Not an edge case. Not occasional. Roughly two out of every five. </p>
<p><img data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/endpoint-risk-e1786623373594.jpg" alt="endpoint risk" width="1873" height="1423" class="lazyload aligncenter size-full wp-image-21231 lazyload" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/endpoint-risk-e1786623373594.jpg 1873w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/endpoint-risk-e1786623373594-300x228.jpg 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/endpoint-risk-e1786623373594-1024x778.jpg 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/endpoint-risk-e1786623373594-768x583.jpg 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/endpoint-risk-e1786623373594-1536x1167.jpg 1536w" sizes="(max-width: 1873px) 100vw, 1873px" /></p>
<p>Picture what that looks like in practice. An endpoint that embeds sensitive data inside its tokens — a risk present in essentially half of all detections — sitting on the same endpoint as an expired-token gap that lets access continue indefinitely, a risk that grew 70% this year. We can&#8217;t say how often that exact pairing occurs; our data tells us endpoints carry multiple risks, not which specific risks pair together most often. But it&#8217;s exactly the kind of compounding scenario nearly 40% of endpoints are positioned for — a token that doesn&#8217;t just leak once, but keeps leaking, because nothing in the system ever cuts it off. </p>
<p>At the extreme end, it&#8217;s worse than pairing. The single riskiest endpoint we found carried all five risk types at once: sensitive data in the token, a weak signing algorithm, an excessively long lifetime, Basic Authentication, and continued access after expiry. Endpoints like that usually aren&#8217;t the result of five separate, unrelated mistakes. More often, they&#8217;re a single legacy or lightly-used endpoint that never got touched when the rest of the environment moved to better practices — quietly running on old assumptions while everything around it improved. </p>
<p>That&#8217;s the pattern that should reframe how this whole report gets read. If these risks were scattered at random, an endpoint like that would be a statistical fluke. Instead, the pattern repeats across nearly 40% of everything we measured. That&#8217;s not scattered. That&#8217;s systemic — and it means the standard response to finding one authentication issue, patching it and closing the ticket, is very likely leaving a second or third issue sitting untouched on the exact same endpoint. </p>
<h2>What This Means for How We Approach Authentication </h2>
<p>Here&#8217;s the uncomfortable pattern sitting underneath all of the numbers above: the risks that improved this year are the ones that are easy to check. The risks that got worse are the ones that are hard to check. That&#8217;s not a coincidence — it&#8217;s a fairly accurate description of how security improvement actually happens inside most organizations. </p>
<p>&#8220;Did we pick a strong signing algorithm&#8221; is a yes-or-no question a scanner can answer in seconds. &#8220;What data did we decide to put inside this token, and did anyone revisit that decision when a new field got added eighteen months later&#8221; is not. &#8220;Are we still using Basic Auth&#8221; shows up on nearly every audit checklist in the industry. &#8220;Does every service that validates this token independently re-check its expiration or does one of them just trust the gateway&#8221; usually doesn&#8217;t, because answering it requires understanding how a system actually behaves, not just which protocol it uses. </p>
<p>We think that&#8217;s the real story in this year&#8217;s data. The industry has gotten reasonably good at fixing the authentication problems that are legible — the ones a checklist can catch, the ones a single well-publicized recommendation can meaningfully move. It hasn&#8217;t gotten meaningfully better at the problems that require understanding how a system was actually built, which is exactly the category the two worsening risks, and the clustering pattern connecting them, fall into. A scanner can tell you a token is signed with a weak algorithm. It&#8217;s much worse at telling you that the same token is also carrying a customer&#8217;s date of birth. </p>
<p>If there&#8217;s one thing worth taking from this report, it&#8217;s this: the next time your team finds one authentication issue on an endpoint, the right instinct isn&#8217;t relief that you caught it. It&#8217;s to ask what else is sitting there next to it — because in nearly 40% of the cases we looked at, the answer was something. </p>
<h2>Get the Full Report </h2>
<p>This post covers the headline findings. The full 2026 Token &#038; Authentication Risk Report includes the complete year-over-year breakdown across all five categories, the reasoning behind each shift, and specific, practical recommendations for where security and engineering teams should focus first. </p>
<p><a href="https://www.imperva.com/resources/resource-library/reports/imperva-api-security-token-authentication-risk-report/?6">Download the 2026 Token &#038; Authentication Risk Report → </a></p>
<p>The post <a href="https://www.imperva.com/blog/imperva-api-security-token-authentication-risk-report-nearly-40-of-apis-face-multiple-authentication-risks/">Imperva API Security Token &#038; Authentication Risk Report: Nearly 40% of APIs Face Multiple Authentication Risks</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.imperva.com/blog/imperva-api-security-token-authentication-risk-report-nearly-40-of-apis-face-multiple-authentication-risks/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<enclosure type="image/jpg" url="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/skyscrapers.jpg" length="845" />	</item>
		<item>
		<title>CopyEscape: Taking Over Docker Hosts with docker cp</title>
		<link>https://www.imperva.com/blog/copyescape-taking-over-docker-hosts-with-docker-cp/</link>
					<comments>https://www.imperva.com/blog/copyescape-taking-over-docker-hosts-with-docker-cp/#respond</comments>
		
		<dc:creator><![CDATA[Ron Masas]]></dc:creator>
		<pubDate>Tue, 11 Aug 2026 03:45:11 +0000</pubDate>
				<category><![CDATA[Imperva Threat Research]]></category>
		<guid isPermaLink="false">https://www.imperva.com/blog/?p=21210</guid>

					<description><![CDATA[<p>Imperva Red Team uncovered CVE-2026-17106, a container-to-host arbitrary file-write vulnerability in Docker’s docker cp command. Docker later confirmed that the same CVE also affected sbx cp when copying files out of Docker Sandboxes. A malicious container or sandbox could exploit the copy process to create or overwrite files outside the destination selected by the user, [&#8230;]</p>
<p>The post <a href="https://www.imperva.com/blog/copyescape-taking-over-docker-hosts-with-docker-cp/">CopyEscape: Taking Over Docker Hosts with docker cp</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><span style="font-weight: 400">Imperva Red Team uncovered </span><a href="https://www.cve.org/CVERecord?id=CVE-2026-17106" target="_blank" rel="noopener"><b>CVE-2026-17106</b></a><span style="font-weight: 400">, a container-to-host arbitrary file-write vulnerability in Docker’s </span><i><span style="font-weight: 400">docker cp</span></i><span style="font-weight: 400"> command. Docker later confirmed that the same CVE also affected </span><i><span style="font-weight: 400">sbx cp</span></i><span style="font-weight: 400"> when copying files out of Docker Sandboxes. A malicious container or sandbox could exploit the copy process to create or overwrite files outside the destination selected by the user, potentially enabling code execution on the machine running the </span><a href="https://www.docker.com/products/cli/" target="_blank" rel="noopener"><span style="font-weight: 400">Docker CLI</span></a><span style="font-weight: 400">.</span></p>
<p><span style="font-weight: 400">Through CVE-2026-17106, an attacker-controlled container could turn a routine file copy into two powerful outcomes:</span></p>
<p><b>Host file overwrite</b><span style="font-weight: 400">: creating or replacing any file writable by the user running </span><i><span style="font-weight: 400">docker cp</span></i><span style="font-weight: 400">, including shell configuration, executables, SSH configuration, source code, and persistence mechanisms.</span></p>
<p><b>Code execution:</b><span style="font-weight: 400"> Executing attacker-controlled code as the logged-in user on macOS or, when docker cp runs with elevated privileges on Linux, achieving root code execution immediately after the command completes by overwriting the </span><a href="https://www.docker.com/blog/runc/" target="_blank" rel="noopener"><i><span style="font-weight: 400">runc</span></i></a><span style="font-weight: 400"> binary.</span></p>
<p><span style="font-weight: 400">The exploit chains two weaknesses in Docker’s archive pipeline: a filesystem race that lets a running container produce an inconsistent tar archive, and an extraction flaw that allows the Docker CLI to follow a planted symlink outside the intended destination.</span></p>
<p><span style="font-weight: 400">Together, these weaknesses turn the user’s own Docker CLI into a write primitive. The attacker controls the container and its files, the CLI supplies access to the host filesystem.</span></p>
<p><span style="font-weight: 400">The </span><i><span style="font-weight: 400">docker cp </span></i><span style="font-weight: 400">command is routinely used to retrieve build artifacts, test results, logs, and forensic evidence from containers. This makes the vulnerability particularly relevant to CI systems, developer workstations, privileged automation, and incident-response workflows. In the last case, simply collecting evidence from a compromised container could activate the payload waiting inside it.</span></p>
<p><span style="font-weight: 400">The impact also reaches AI-agent workflows. Docker Sandboxes uses </span><i><span style="font-weight: 400">sbx cp</span></i><span style="font-weight: 400"> to move files between an isolated agent environment and the host. Docker Sandboxes 0.38.0, released August 6, identifies and fixes a “destination-escape flaw in sbx cp copy-out” under CVE-2026-17106. This means retrieving an artifact produced inside an untrusted or compromised coding-agent sandbox could expose the host to the same class of destination escape.</span></p>
<h2><b>From a Simple Copy to a Host Write</b></h2>
<p><span style="font-weight: 400">The command that started this research could hardly look more ordinary:</span></p>
<pre><i><span style="font-weight: 400">docker cp container:/path/to/file.txt ./file.txt</span></i></pre>
<p><span style="font-weight: 400">The source is inside the container. The destination is chosen by the user. The expected security boundary seems obvious: Docker should write to ./file.txt and nowhere else.</span></p>
<p><span style="font-weight: 400">But docker cp is not a direct filesystem-to-filesystem copy.</span></p>
<p><span style="font-weight: 400">When copying from a container, the Docker daemon walks the container&#8217;s live filesystem and turns the selected path into a tar archive. The Docker CLI receives that archive and extracts it on the client machine.</span></p>
<p><img class="lazyload alignnone size-full wp-image-21213 lazyload" alt="image3" width="1536" height="1024" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image3.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image3.png 1536w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image3-300x200.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image3-1024x683.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image3-768x512.png 768w" sizes="(max-width: 1536px) 100vw, 1536px" /></p>
<p><span style="font-weight: 400">This architecture creates a powerful connection between two security domains. The container controls the archive contents, while the local CLI performs the resulting filesystem operations with the permissions of the person or process that invoked docker cp.</span></p>
<p><span style="font-weight: 400">For this design to remain safe, Docker needs to preserve two properties:</span></p>
<ol>
<li style="font-weight: 400"><span style="font-weight: 400">The daemon must produce a coherent archive from the container&#8217;s filesystem.</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">The CLI must confine every extracted object to the destination selected by the user.</span></li>
</ol>
<p><span style="font-weight: 400">We found a way to break both properties in the same copy operation.</span></p>
<h2><b>Impact</b></h2>
<p><span style="font-weight: 400">The vulnerability provides an </span><b>arbitrary file create or overwrite primitive within the permissions of the Docker CLI process</b><span style="font-weight: 400">.</span></p>
<p><span style="font-weight: 400">The malicious container does not automatically inherit root privileges from </span><i><span style="font-weight: 400">dockerd</span></i><span style="font-weight: 400">, and exploitation requires a user or automated system to invoke docker cp against the attacker-controlled path.</span></p>
<p><span style="font-weight: 400">But the final write occurs on the machine running the CLI, with the authority of that user-not with the permissions of the process inside the container.</span></p>
<p><span style="font-weight: 400">We validated the exploit on Linux with Docker Engine 29.6.1 and on macOS with Docker Desktop 4.81.0 (232925).</span></p>
<h3><span style="font-weight: 400">Developer Compromise on macOS</span></h3>
<div style="width: 1792px;" class="wp-video"><video class="wp-video-shortcode" id="video-21210-2" width="1792" height="360" preload="metadata" controls="controls"><source type="video/mp4" src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/copyescape-macos-poc.mp4?_=2" /><a href="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/copyescape-macos-poc.mp4">https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/copyescape-macos-poc.mp4</a></video></div>
<p><span style="font-weight: 400">Docker Desktop runs the daemon inside a Linux virtual machine, but a container-to-local docker cp operation is extracted by the CLI running on macOS.</span></p>
<p><span style="font-weight: 400">This means the archive crosses the VM boundary before the vulnerable operation occurs. The symlink is followed by a process on the Mac, and its target is interpreted in the Mac&#8217;s filesystem namespace.</span></p>
<p><span style="font-weight: 400">A malicious container could therefore target files such as shell startup scripts, user-level executables, SSH configuration, source trees, cloud configuration, or persistence mechanisms under ~/Library/LaunchAgents. Overwriting a shell startup file could execute the attacker&#8217;s code the next time the user opens a terminal.</span></p>
<p><span style="font-weight: 400">The container does not need to escape the Docker Desktop VM directly. It convinces the local CLI to perform the write on its behalf.</span></p>
<h3><span style="font-weight: 400">Root Code Execution on Linux</span></h3>
<div style="width: 1792px;" class="wp-video"><video class="wp-video-shortcode" id="video-21210-3" width="1792" height="360" preload="metadata" controls="controls"><source type="video/mp4" src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/copyescape-linux.mp4?_=3" /><a href="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/copyescape-linux.mp4">https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/copyescape-linux.mp4</a></video></div>
<p><span style="font-weight: 400">On Linux, the daemon and CLI commonly run on the same host. The write still carries the CLI user&#8217;s permissions.</span></p>
<p><span style="font-weight: 400">For an ordinary user, the attacker can reach files writable by that account. If an administrator, CI worker, or maintenance process invokes sudo docker cp, the operation can reach root-owned system paths.</span></p>
<p><span style="font-weight: 400">In our </span><a href="https://github.com/masasron/CopyEscape-CVE-2026-17106" target="_blank" rel="noopener"><span style="font-weight: 400">proof of concept</span></a><span style="font-weight: 400">, we replaced </span><i><span style="font-weight: 400">/usr/bin/runc</span></i><span style="font-weight: 400"> with a shell script. A later Docker lifecycle operation executed the replaced binary and created a marker file as root.</span></p>
<p><span style="font-weight: 400">The exploit did not obtain root from the Docker daemon. The copy already had enough authority to replace </span><i><span style="font-weight: 400">runc</span></i><span style="font-weight: 400">, and the later execution converted that file write into root code execution.</span></p>
<h2><b>The Archive That Described Two Filesystems</b></h2>
<p><span style="font-weight: 400">The first part of the chain was in the archive producer.</span></p>
<p><span style="font-weight: 400">Both the Moby and Docker CLI source trees we reviewed used github.com/moby/go-archive v0.2.0. For a container-to-local copy, Moby&#8217;s containerArchivePath creates a tarballer and runs it inside the container filesystem:</span></p>
<p><img class="lazyload alignnone size-full wp-image-21223 lazyload" alt="image13" width="1944" height="446" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image13.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image13.png 1944w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image13-300x69.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image13-1024x235.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image13-768x176.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image13-1536x352.png 1536w" sizes="(max-width: 1944px) 100vw, 1944px" /></p>
<p style="text-align: center"><i><span style="font-weight: 400">Source: </span></i><a href="https://github.com/moby/moby/blob/docker-v29.6.1/daemon/archive_unix.go#L76-L82" target="_blank" rel="noopener"><i><span style="font-weight: 400">Moby containerArchivePath, Docker Engine 29.6.1, lines 76–82</span></i></a><i><span style="font-weight: 400">.</span></i></p>
<p><span style="font-weight: 400">Docker locks the container object while the archive is read, but that lock protects Docker&#8217;s internal state. It does not freeze processes running inside the container.</span></p>
<p><span style="font-weight: 400">Those processes can continue renaming files, replacing directories, and creating symlinks while the daemon walks the source tree.</span></p>
<p><span style="font-weight: 400">The tarballer performs that walk with </span><i><span style="font-weight: 400">filepath.WalkDir</span></i><span style="font-weight: 400">:</span></p>
<p><img class="lazyload alignnone size-full wp-image-21218 lazyload" alt="image8" width="1999" height="623" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image8.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image8.png 1999w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image8-300x93.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image8-1024x319.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image8-768x239.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image8-1536x479.png 1536w" sizes="(max-width: 1999px) 100vw, 1999px" /></p>
<p style="text-align: center"><i><span style="font-weight: 400">Source: </span></i><a href="https://github.com/moby/go-archive/blob/v0.2.0/archive.go#L691-L802" target="_blank" rel="noopener"><i><span style="font-weight: 400">moby/go-archive v0.2.0 archive walk, lines 691–802</span></i></a><i><span style="font-weight: 400">.</span></i></p>
<p><i><span style="font-weight: 400">WalkDir</span></i><span style="font-weight: 400"> reads a directory entry and records its type. If the entry is a directory, the walker plans to descend into it.</span></p>
<p><span style="font-weight: 400">The callback then passes the pathname to </span><i><span style="font-weight: 400">addTarFile</span></i><span style="font-weight: 400">, which looks it up again with </span><i><span style="font-weight: 400">Lstat</span></i><span style="font-weight: 400"> to create the tar header:</span></p>
<p><img class="lazyload alignnone size-full wp-image-21222 lazyload" alt="image12" width="1940" height="964" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image12.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image12.png 1940w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image12-300x149.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image12-1024x509.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image12-768x382.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image12-1536x763.png 1536w" sizes="(max-width: 1940px) 100vw, 1940px" /></p>
<p style="text-align: center"><i><span style="font-weight: 400">Source: </span></i><a href="https://github.com/moby/go-archive/blob/v0.2.0/archive.go#L295-L317" target="_blank" rel="noopener"><i><span style="font-weight: 400">moby/go-archive v0.2.0 addTarFile, lines 295–317</span></i></a><i><span style="font-weight: 400">.</span></i></p>
<p><span style="font-weight: 400">The same pathname now answers two different questions at two different times:</span></p>
<p><b>Traversal decision</b><span style="font-weight: 400">: is this entry a directory that WalkDir should enter?</span></p>
<p><b>Archive metadata</b><span style="font-weight: 400">: is this entry a file, directory, or symlink that should be written to the tar stream?</span></p>
<p><span style="font-weight: 400">If the path changes between those observations, the two answers no longer need to agree.</span></p>
<h2><b>Turning the Race into a Reliable Primitive</b></h2>
<p><span style="font-weight: 400">In our </span><a href="https://github.com/masasron/CopyEscape-CVE-2026-17106" target="_blank" rel="noopener"><span style="font-weight: 400">proof of concept</span></a><span style="font-weight: 400">, /watched/file.txt is intentionally deceptive. An </span><i><span style="font-weight: 400">LD_PRELOAD</span></i><span style="font-weight: 400"> interposer makes it appear to be a regular file to processes inside the container by redirecting exact accesses to a hidden backing file, /watched/.file.txt.regular. The Docker daemon, however, sees the underlying file.txt path as a directory and can walk the attacker-controlled tree beneath it.</span></p>
<p><span style="font-weight: 400">The walker initially sees the following directory:</span></p>
<p><img class="lazyload alignnone size-full wp-image-21224 lazyload" alt="image14" width="1999" height="204" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image14.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image14.png 1999w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image14-300x31.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image14-1024x105.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image14-768x78.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image14-1536x157.png 1536w" sizes="(max-width: 1999px) 100vw, 1999px" /></p>
<p><span style="font-weight: 400">After </span><i><span style="font-weight: 400">WalkDir</span></i><span style="font-weight: 400"> records escape as a directory, the attacker moves it aside and replaces it with a staged symlink:</span></p>
<p><img class="lazyload alignnone size-full wp-image-21217 lazyload" alt="image7" width="1999" height="198" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image7.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image7.png 1999w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image7-300x30.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image7-1024x101.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image7-768x76.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image7-1536x152.png 1536w" sizes="(max-width: 1999px) 100vw, 1999px" /></p>
<p><span style="font-weight: 400">The switch requires only two rename operations, winning a filesystem race blindly would be unreliable, so we gave the container a clock.</span></p>
<p><span style="font-weight: 400">Our </span><a href="https://github.com/masasron/CopyEscape-CVE-2026-17106" target="_blank" rel="noopener"><span style="font-weight: 400">proof of concept</span></a><span style="font-weight: 400"> places a large file immediately before the pivot directory and monitors it with filesystem notifications. When the daemon opens that file, the attacker knows the walk has reached the right location. The large file widens the timing window, and the notification signals when to perform the two renames.</span></p>
<p><span style="font-weight: 400">What begins as a race becomes a repeatable sequence.</span></p>
<p><span style="font-weight: 400">After the switch, </span><i><span style="font-weight: 400">addTarFile</span></i><span style="font-weight: 400"> sees a symlink and emits a symlink header for file.txt/escape. Control then returns to </span><i><span style="font-weight: 400">WalkDir</span></i><span style="font-weight: 400">, whose earlier directory entry still says that escape is a directory. The walker descends through the same pathname and adds a child beneath the symlink&#8217;s archive name.</span></p>
<p><span style="font-weight: 400">The resulting tar stream contains two entries:</span></p>
<p><img class="lazyload alignnone size-full wp-image-21215 lazyload" alt="image5" width="1999" height="200" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image5.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image5.png 1999w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image5-300x30.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image5-1024x102.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image5-768x77.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image5-1536x154.png 1536w" sizes="(max-width: 1999px) 100vw, 1999px" /></p>
<p><span style="font-weight: 400">Each entry is understandable on its own. Together, they describe two different moments in the source filesystem: escape is represented as a symlink, while its child is represented as though escape were still a directory.</span></p>
<p><img class="lazyload alignnone size-full wp-image-21221 lazyload" alt="image11" width="1774" height="887" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image11.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image11.png 1774w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image11-300x150.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image11-1024x512.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image11-768x384.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image11-1536x768.png 1536w" sizes="(max-width: 1774px) 100vw, 1774px" /></p>
<p><span style="font-weight: 400">At this point, the container has produced an inconsistent archive. That alone should not be enough to write outside the destination. The client still controls extraction and can reject the dangerous sequence.</span></p>
<p><span style="font-weight: 400">It did not.</span></p>
<h2><b>The Extractor Checked One Path and Created Another</b></h2>
<p><span style="font-weight: 400">For a copy from a container, the Docker CLI eventually reaches </span><i><span style="font-weight: 400">archive.CopyTo</span></i><span style="font-weight: 400">:</span></p>
<p><img class="lazyload alignnone size-full wp-image-21216 lazyload" alt="image6" width="1532" height="390" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image6.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image6.png 1532w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image6-300x76.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image6-1024x261.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image6-768x196.png 768w" sizes="(max-width: 1532px) 100vw, 1532px" /></p>
<p style="text-align: center"><i><span style="font-weight: 400">Source: </span></i><a href="https://github.com/moby/go-archive/blob/v0.2.0/copy.go#L418-L437" target="_blank" rel="noopener"><i><span style="font-weight: 400">moby/go-archive v0.2.0 CopyTo, lines 418–437</span></i></a><i><span style="font-weight: 400">.</span></i></p>
<p><span style="font-weight: 400">Neither option confines traversal through an intermediate symlink. The vulnerable symlink handling attempted to perform its own containment check:</span></p>
<p><img class="lazyload alignnone size-full wp-image-21211 lazyload" alt="image1" width="1528" height="622" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image1.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image1.png 1528w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image1-300x122.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image1-1024x417.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image1-768x313.png 768w" sizes="(max-width: 1528px) 100vw, 1528px" /></p>
<p style="text-align: center"><i><span style="font-weight: 400">Source: </span></i><a href="https://github.com/moby/go-archive/blob/v0.2.0/archive.go#L480-L492" target="_blank" rel="noopener"><i><span style="font-weight: 400">moby/go-archive v0.2.0 symlink extraction, lines 480–492</span></i></a><i><span style="font-weight: 400">.</span></i></p>
<p><span style="font-weight: 400">The validation and the filesystem operation use different values.</span></p>
<p><span style="font-weight: 400">The containment check validates targetPath, a path constructed with filepath.Join. The subsequent os.Symlink call receives the original hdr.Linkname from the archive.</span></p>
<p><span style="font-weight: 400">For an extraction path of /safe/output/file.txt/escape and a link target of /usr/bin, the validation evaluates:</span></p>
<p><img class="lazyload alignnone size-full wp-image-21212 lazyload" alt="image2" width="1216" height="208" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image2.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image2.png 1216w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image2-300x51.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image2-1024x175.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image2-768x131.png 768w" sizes="(max-width: 1216px) 100vw, 1216px" /></p>
<p><span style="font-weight: 400">That constructed path appears to remain under /safe/output, so the check approves it. Docker then gives the original absolute target to the kernel:</span></p>
<p><img class="lazyload alignnone size-full wp-image-21214 lazyload" alt="image4" width="1204" height="158" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image4.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image4.png 1204w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image4-300x39.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image4-1024x134.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image4-768x101.png 768w" sizes="(max-width: 1204px) 100vw, 1204px" /></p>
<p><span style="font-weight: 400">The check approves one path. The filesystem creates another.</span></p>
<p><span style="font-weight: 400">The same condition has an additional weakness: string prefixes do not represent path containment. A path such as /safe/output-elsewhere also begins with </span><i><span style="font-weight: 400">/safe/output</span></i><span style="font-weight: 400">. Our chain already had what it needed from the checked-value-versus-used-value mismatch.</span></p>
<p><span style="font-weight: 400">The extractor then processes the child entry, file.txt/escape/runc.</span></p>
<p><span style="font-weight: 400">Docker cleans the archive name, joins it to the destination, and checks for a lexical ../ escape, but the child entry contains no ../. As text, it remains beneath the destination.</span></p>
<p><span style="font-weight: 400">The previous tar entry has changed what the pathname means on disk. Before creating the child, the vulnerable extractor does not re-establish confinement against the resolved target:</span></p>
<p><img class="lazyload alignnone size-full wp-image-21220 lazyload" alt="image10" width="1608" height="678" data-src="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image10.png" srcset="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image10.png 1608w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image10-300x126.png 300w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image10-1024x432.png 1024w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image10-768x324.png 768w, https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image10-1536x648.png 1536w" sizes="(max-width: 1608px) 100vw, 1608px" /></p>
<p style="text-align: center"><i><span style="font-weight: 400">Source: </span></i><a href="https://github.com/moby/go-archive/blob/v0.2.0/archive.go#L295-L317" target="_blank" rel="noopener"><i><span style="font-weight: 400">moby/go-archive v0.2.0 addTarFile, lines 295–317</span></i></a><i><span style="font-weight: 400">.</span></i></p>
<p><span style="font-weight: 400">When the file is created, the kernel follows escape -&gt; /usr/bin. The attacker&#8217;s bytes land at /usr/bin/runc on the Docker client rather than under /safe/output.</span></p>
<p><span style="font-weight: 400">The full chain is:</span></p>
<ol>
<li style="font-weight: 400"><span style="font-weight: 400">WalkDir records escape as a directory.</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">The container replaces it with an absolute symlink.</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">addTarFile emits the symlink into the tar stream.</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">WalkDir descends using its earlier directory type and emits a child entry.</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">The CLI validates a constructed target but creates the original absolute symlink.</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">The CLI extracts the child through that symlink and writes outside the destination.</span></li>
</ol>
<p><span style="font-weight: 400">One stale directory entry and one ineffective containment check were enough to turn docker cp into a host write.</span></p>
<h2><b>From Host Write to Host Compromise</b></h2>
<p><span style="font-weight: 400">At this point, the copy operation is no longer confined to the destination chosen by the user. The attacker-controlled container has gained a write primitive on the Docker client, with the permissions of the process running </span><i><span style="font-weight: 400">docker cp</span></i><span style="font-weight: 400">.</span></p>
<p><span style="font-weight: 400">What happens next depends on those permissions. A copy launched by a developer could target user-writable startup files, shell configuration, source code, or persistence mechanisms. If the command runs as root, as is common in automation and some Linux environments, the same primitive could reach system executables and privileged configuration, turning the file write into root code execution.</span></p>
<p><span style="font-weight: 400">The vulnerability simply prepares the malicious filesystem and waits. The trigger may be a developer retrieving a build artifact, a CI job collecting test results, or an incident responder copying evidence from a container they already suspect is compromised.</span></p>
<p><span style="font-weight: 400">In each case, the operation intended to take data safely out of the container becomes the step that carries the attack back onto the host.</span></p>
<h2><b>Mitigations</b></h2>
<p><span style="font-weight: 400">Users should upgrade to Docker Engine and CLI 29.7.2 or later, and Docker Desktop 4.86.0 or later.</span></p>
<p><span style="font-weight: 400">Where upgrading is not immediately possible:</span></p>
<ul>
<li style="font-weight: 400"><span style="font-weight: 400">Avoid copying from running, untrusted, or compromised containers onto a sensitive client.</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Stop the container before copying. Docker supports copying from a stopped container, preventing a live process from performing the race used in this chain.</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Avoid </span><span style="font-weight: 400">sudo docker cp</span><span style="font-weight: 400"> and root-run copy automation.</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Run the Docker CLI with the least privilege required for the workflow.</span></li>
<li style="font-weight: 400"><span style="font-weight: 400">Retrieve data from suspicious containers using a disposable account, VM, or similarly isolated environment.</span></li>
</ul>
<p><span style="font-weight: 400">Stopping the container blocks the producer race demonstrated here. It does not replace safe extraction: any archive originating from an untrusted source should still be treated as hostile input.</span></p>
<h2><b>Conclusion</b></h2>
<p><span style="font-weight: 400">Container boundaries are not defined only by namespaces, virtual machines, or the Docker daemon. They also depend on the client-side tools that move data across those boundaries.</span></p>
<p><span style="font-weight: 400">docker cp connects a live, attacker-controlled filesystem to an extractor running with the user&#8217;s authority. That design requires both sides of the pipeline to preserve a strict contract: the archive must be coherent, and every extracted object must remain inside the destination.</span></p>
<p><span style="font-weight: 400">CVE-2026-17106 broke that contract. The daemon observed one pathname as two different objects, producing a symlink followed by its apparent child. The CLI then validated one path, created another, and allowed the child entry to cross onto the client filesystem.</span></p>
<p><span style="font-weight: 400">The most important lesson is simple: archive extraction is a security boundary. Path normalization and string-prefix checks cannot enforce that boundary once symlinks and concurrent filesystem changes are involved. Filesystem operations must be rooted so that the kernel, not a string comparison, guarantees where the write can land.</span></p>
<p><span style="font-weight: 400">We responsibly disclosed the vulnerability to Docker and delayed publication several times to align disclosure with a usable patch. We would like to thank Docker&#8217;s security and engineering teams for investigating the report, coordinating the CVE, and working through the regressions introduced by the initial fix.</span></p>
<h3><span style="font-weight: 400">Responsible Disclosure Timeline</span></h3>
<p><b>April 11, 2026</b><span style="font-weight: 400"> &#8211; We reported the vulnerability to Docker with technical details and reproduction information.</span></p>
<p><b>April 14, 2026</b><span style="font-weight: 400"> &#8211; Docker acknowledged receipt and began reviewing the report.</span></p>
<p><b>April 15, 2026</b><span style="font-weight: 400"> &#8211; Docker confirmed the behavior as a valid finding and explained its assessment of the client-side privilege boundary.</span></p>
<p><b>July 10, 2026</b><span style="font-weight: 400"> &#8211; The initial 90-day disclosure period elapsed without a public patch. We requested a concrete remediation, advisory, and publication schedule.</span></p>
<p><b>July 14, 2026</b><span style="font-weight: 400"> &#8211; Docker described two remediation tracks: extraction-library hardening as the primary security fix and source-walk hardening as follow-up work. We agreed to delay publication while the fixes were prepared.</span></p>
<p><b>July 24, 2026</b><span style="font-weight: 400"> &#8211; Docker provided </span><a href="https://www.cve.org/CVERecord?id=CVE-2026-17106" target="_blank" rel="noopener"><span style="font-weight: 400">CVE-2026-17106</span></a><span style="font-weight: 400"> / </span><a href="https://github.com/moby/go-archive/security/advisories/GHSA-hfg8-hc9c-6c3h" target="_blank" rel="noopener"><span style="font-weight: 400">GHSA-hfg8-hc9c-6c3h</span></a><span style="font-weight: 400"> and targeted an August 3 coordinated release.</span></p>
<p><b>July 27, 2026</b><span style="font-weight: 400"> &#8211; Docker confirmed that the source-walk TOCTOU would not receive a separate CVE and would instead be addressed as defense-in-depth hardening.</span></p>
<p><b>July 30, 2026</b><span style="font-weight: 400"> &#8211; moby/go-archive v0.3.0 and Docker Engine/CLI 29.7.0 shipped the extraction fix.</span></p>
<p><b>July 31, 2026</b><span style="font-weight: 400"> &#8211; Docker reported significant functional regressions caused by the initial hardening and requested a final extension to August 10. Follow-up go-archive and Engine releases addressed the regressions.</span></p>
<p><b>August 1, 2026</b><span style="font-weight: 400"> &#8211; We agreed to extend coordinated disclosure to August 10.</span></p>
<p><b>August 6, 2026</b><span style="font-weight: 400"> &#8211; Docker Sandboxes 0.38.0 shipped a fix for a destination-escape flaw in </span><span style="font-weight: 400">sbx cp</span><span style="font-weight: 400"> copy-out under CVE-2026-17106. Docker also confirmed that the Docker Desktop update remained scheduled for August 10.</span></p>
<p><b>August 10, 2026</b><span style="font-weight: 400"> &#8211; Docker released</span><a href="https://docs.docker.com/desktop/release-notes/#4860" target="_blank" rel="noopener"> <span style="font-weight: 400">Docker Desktop 4.86.0</span></a><span style="font-weight: 400">, bundling Docker Engine 29.7.2 and delivering the corresponding Docker Desktop fix.</span></p>
<p>The post <a href="https://www.imperva.com/blog/copyescape-taking-over-docker-hosts-with-docker-cp/">CopyEscape: Taking Over Docker Hosts with docker cp</a> appeared first on <a href="https://www.imperva.com/blog">Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.imperva.com/blog/copyescape-taking-over-docker-hosts-with-docker-cp/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		<enclosure url="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/copyescape-macos-poc.mp4" length="6058" type="video/mp4" />
<enclosure url="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/copyescape-linux.mp4" length="6058" type="video/mp4" />

		<enclosure type="image/jpg" url="https://www.imperva.com/blog/wp-content/uploads/sites/9/2026/08/image9.png" length="1536" />	</item>
	</channel>
</rss>
