
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
    <channel>
        <title><![CDATA[ The Cloudflare Blog ]]></title>
        <description><![CDATA[ Get the latest news on how products at Cloudflare are built, technologies used, and join the teams helping to build a better Internet. ]]></description>
        <link>https://blog.cloudflare.com</link>
        <atom:link href="https://blog.cloudflare.com/" rel="self" type="application/rss+xml"/>
        <language>en-us</language>
        <image>
            <url>https://blog.cloudflare.com/favicon.png</url>
            <title>The Cloudflare Blog</title>
            <link>https://blog.cloudflare.com</link>
        </image>
        <lastBuildDate>Thu, 02 Apr 2026 08:34:07 GMT</lastBuildDate>
        <item>
            <title><![CDATA[The most-seen UI on the Internet? Redesigning Turnstile and Challenge Pages]]></title>
            <link>https://blog.cloudflare.com/the-most-seen-ui-on-the-internet-redesigning-turnstile-and-challenge-pages/</link>
            <pubDate>Fri, 27 Feb 2026 06:00:00 GMT</pubDate>
            <description><![CDATA[ We serve 7.6 billion challenges daily. Here’s how we used research, AAA accessibility standards, and a unified architecture to redesign the Internet’s most-seen user interface. ]]></description>
            <content:encoded><![CDATA[ <p>You've seen it. Maybe you didn't register it consciously, but you've seen it. That little widget asking you to verify you're human. That full-page security check before accessing a website. If you've spent any time on the Internet, you've encountered Cloudflare's Turnstile widget or Challenge Pages — likely more times than you can count.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5YaxxmA9nz7AufmcJmhagL/0db6b65ec7456bc8091affc6beaf3ec2/Image_1_-_Turnstile.png" />
          </figure><p><sup><i>The Turnstile widget – a familiar sight across millions of websites</i></sup></p><p>When we say that a large portion of the Internet sits behind Cloudflare, we mean it. Our Turnstile widget and Challenge Pages are served 7.67 billion times every single day. That's not a typo. Billions. This might just be the most-seen user interface on the Internet.</p><p>And that comes with enormous responsibility.</p><p>Designing a product with billions of eyeballs on it isn't just challenging — it requires a fundamentally different approach. Every pixel, every word, every interaction has to work for someone's grandmother in rural Japan, a teenager in São Paulo, a visually impaired developer in Berlin, and a busy executive in Lagos. All at the same time. In moments of frustration.</p><p>Today we’re sharing the story of how we redesigned Turnstile and Challenge Pages. It's a story told in three parts, by three of us: the design process and research that shaped our decisions (Leo), the engineering challenge of deploying changes at unprecedented scale (Ana), and the measurable impact on billions of users (Marina).</p><p>Let's start with how we approached the problem from a design perspective.</p>
    <div>
      <h2>Part 1: The design process</h2>
      <a href="#part-1-the-design-process">
        
      </a>
    </div>
    
    <div>
      <h3>The problem</h3>
      <a href="#the-problem">
        
      </a>
    </div>
    <p>Let's be honest: nobody likes being asked to prove they're human. You know you're human. I know I'm human. The only one who doesn't seem convinced is that little widget standing between you and the website you're trying to access. At best, it's a minor inconvenience. At worst? You've probably wanted to throw your computer out the window in a fit of rage. We've all been there. And no one would blame you.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/640zjNaqDcNdJy4mYN6H14/ce184df68c9612d77f0767726bf27822/2.png" />
          </figure><p><sup><i>Turnstile integrated into a login flow</i></sup></p><p>As the world warms up to what appears to be an inevitable AI revolution, the need for security verification is only increasing. At Cloudflare, we've seen a significant rise in bot attacks — and in response, organizations are investing more heavily in security measures. That means more challenges being issued to more end users, more often.</p><p>The numbers tell the story:</p><p>2023: 2.14B daily</p><p>2024: 3B daily</p><p>2025: 5.35B daily</p><p>That's a 58.1% average increase in security checks, year over year. More security checks mean more opportunities for end user frustration. The more companies integrate these verification systems to protect themselves and their customers, the higher the chance that someone, somewhere, is going to have a bad experience.</p><p>We knew it was time to take a hard look at our flagship products and ask ourselves: Are we doing right by the billions of people who encounter these experiences? Are we fulfilling our mission to build a better Internet — not just a more secure one, but a more human one?</p><p>The answer, we discovered, was: we could do better.</p>
    <div>
      <h3>The design audit</h3>
      <a href="#the-design-audit">
        
      </a>
    </div>
    <p>Before redesigning anything, we needed to understand what we were working with. We started by conducting a comprehensive audit of every state, every error message, and every interaction across both Turnstile and Challenge Pages.</p><p>What we found wasn't the best.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1g1exDgeRH9QlApBXItcfL/fb0051d1dabaa6c91cf976ef64793502/3.png" />
          </figure><p><sup><i>The state of inconsistency in the Turnstile widget. Multiple states with no unified approach</i></sup></p><p>The inconsistencies were glaring. We had no unified approach across the multitude of different error scenarios. Some messages were overly verbose and technical ("Your device clock is set to a wrong time or this challenge page was accidentally cached by an intermediary and is no longer available"). Others were too vague to be helpful ("Timed out"). The visual language varied wildly — different layouts, different hierarchies, different tones of voice.</p><p>We also examined the feedback we'd received online. Social media, support tickets, community forums — we read it all. The frustration was palpable, and much of it was avoidable.</p><p>Take our feedback mechanism, for example. We offered users feedback options like "The widget sometimes fails" versus "The widget fails all the time." But what's the difference, really? And how were they supposed to know how often it failed? We were asking users to interpret ambiguous options during their most frustrated moments. The more we left open to interpretation, the less useful the feedback became — and the more frustration we saw across social channels.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5xKRSM0FfDZikEECwgHoof/ad55208973698cb237444c21d384aff8/4.png" />
          </figure><p><sup><i>The previous feedback screen: "The widget sometimes fails" vs "The widget fails all the time" — what's the difference?</i></sup></p><p>Our Challenge Pages — the full-page security blocks that appear when we detect suspicious activity or when site owners have heightened security settings — had similar issues. Some states were confusing. Others used too much technical jargon. Many failed to provide actionable guidance when users needed it most.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5JUxHjJ4VG13F7QfLONJEQ/fa443e5dd24f10d0c256864cd3f42734/5.png" />
          </figure><p><sup><i>The state of inconsistency on the Challenge pages. Multiple states with no unified approach</i></sup></p><p>The audit was humbling. But it gave us a clear picture of where we needed to focus.</p>
    <div>
      <h2>Mapping the user journey</h2>
      <a href="#mapping-the-user-journey">
        
      </a>
    </div>
    <p>To design better experiences, we first needed to understand every possible path a user could take. What was the happy path? Was there even one? And what were the unhappy paths that led to escalating frustration?</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1oTbFZoRu7guIxzoe64qcm/4f579fe2e70d6225a51504b3de10030f/6.png" />
          </figure><p><sup><i>Mapping the complete user journey — from initial encounter through error scenarios, with sentiment tracking</i></sup></p><p>This was a true cross-functional effort. We worked closely with engineers like Ana who knew the technical ins and outs of every edge case, and with Marina on the product side who understood not just how the product worked, but how users felt about it — the love and the hate we'd see online.</p><p>We have some of the smartest people working on bot protection at Cloudflare. But intelligence and clarity aren't the same thing. There's a delicate balance between technical complexity and user simplicity. Only when these two dance together successfully can we communicate information in a way that actually makes sense to people.</p><p>And here's the thing: the messaging has to work for everyone. A person of any age. Any mental or physical capability. Any cultural background. Any level of technical sophistication. That's what designing at scale really means — you can’t ignore edge cases, since, at such scale, they are no longer edge cases.</p>
    <div>
      <h2>Establishing a unified information architecture</h2>
      <a href="#establishing-a-unified-information-architecture">
        
      </a>
    </div>
    <p>One of the most influential books in UX design is Steve Krug's <a href="https://sensible.com/dont-make-me-think/"><u>Don't Make Me Think</u></a>. The core principle is simple: every moment a user spends trying to interpret, understand, or decode your interface is a moment of friction. And friction, especially in moments of frustration, leads to abandonment.</p><p>Our audit revealed that we were asking users to think far too much. Different pieces of information occupied the same space in the UI across different states. There was no consistent visual hierarchy. Users encountering an error state in Turnstile would find information in a completely different place than they would on a Challenge Page.</p><p>We made a fundamental decision: <b>one information architecture to rule them all</b>.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3runU0ihKhNpgdw3LxNZUv/aa4bd76efb5847fde0659bccdae7242d/7.png" />
          </figure><p><sup><i>Visual diagram displaying a unified information architecture with a consistent structure across Turnstile widget and Challenge pages</i></sup></p><p>Both Turnstile and Challenge Pages would now follow the same structural pattern. The same visual hierarchy. The same placement for actions, for explanatory text, for links to documentation.</p><p>Did this constrain our design options? Absolutely. We had to say no to a lot of creative ideas that didn't fit the framework. But constraints aren't the enemy of good design — they're often its best friend. By limiting our options, we could go deeper on the details that actually mattered.</p><p>For users, the benefit is profound: they don't need to re-learn what each piece of the UI means. Error states look consistent. Help links are always in the same place. Once you understand one state, you understand them all. That's cognitive load reduced to a minimum — exactly where it should be during a security verification.</p>
    <div>
      <h2>What user research taught us</h2>
      <a href="#what-user-research-taught-us">
        
      </a>
    </div>
    <p>How do you keep yourself accountable when redesigning something that billions of people see? You test. A lot.</p><p>We recruited 8 participants across 8 different countries, deliberately seeking diversity in age, digital savviness, and cultural background. We weren't looking for tech-savvy early adopters — we wanted to understand how the redesign would work for everyone.</p><p>Our approach was rigorous: participants saw both the current experience and proposed changes, without knowing which was "old" or "new." We counterbalanced positioning to eliminate bias. And we did not just test our new ideas, but also challenged our assumptions about what needed changing in the first place.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/59mmLHihbM9TewXmlYQwbO/e5db88efca948de1b31e9dc499195eb8/8.png" />
          </figure><p><sup><i>Two different versions of a Turnstile being tested in an A/B test</i></sup></p>
    <div>
      <h3>Some things didn’t need fixing</h3>
      <a href="#some-things-didnt-need-fixing">
        
      </a>
    </div>
    <p>One hypothesis: should we align with competitors? Most CAPTCHA providers show "I am human" across all states. We use distinct content — "Verify you are human," then "Verifying...," then "Success!"</p><p>Were we overcomplicating things? We tested it head-to-head.</p><p>Our approach won decisively. For the interactivity state, "Verify you are human" scored 5 out of 8 points versus just 3 for "I am human." For the verifying state, it was even more dramatic — 7.5 versus 0.5. Users wanted to know what was happening, not just be told what they were.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6ke1kO0i7EZxZm6voQBpyn/f489bef9b66d1221aa89adb5746559b7/9.png" />
          </figure><p><sup><i>User testing results: users strongly favored our approach over the competitor-style design</i></sup></p><p>This experiment didn't ship as a feature, but it was invaluable. It gave us confidence we weren't just being different for the sake of it. Some things were already right.</p>
    <div>
      <h3>But these needed to change</h3>
      <a href="#but-these-needed-to-change">
        
      </a>
    </div>
    <p>The research surfaced four areas where we were failing users:</p><p><b>Help, not bureaucracy</b>. When users encountered errors, we offered "Send Feedback." In testing, they were baffled. "Who am I sending this to? The website? Cloudflare? My ISP?" More importantly, we discovered something fundamental: at the moment of maximum frustration, people don't want to file a report — they want to fix the problem. We replaced "Send Feedback" with "Troubleshoot" — a single word that promises action rather than bureaucracy.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2jN2reUR55qCbssCDFTZfB/fb5396ec853ee549ebfec5d0d94b901f/10.png" />
          </figure><p><sup><i>The problematic "Send Feedback" prompt: users didn't know who they were sending feedback to</i></sup></p><p><b>Attention, not alarm</b>. We'd used red backgrounds liberally for errors. The reaction in testing was visceral — participants felt they had failed, felt powerless. Even for simple issues that would resolve with a retry, users assumed the worst and gave up. Red at full saturation wasn't communicating "Here's something to address." It was communicating "You have failed, and there's nothing you can do." The fix: red only for icons, never for text or backgrounds.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5seE6Xcrj9lvSpBYDEkk6N/7f0c1c17fd86b05397d35b685b0addfb/11.png" />
          </figure><p><sup><i>The evolution: from the states with unclear error state description in red to much clearer and concise error communication in neutral-color text.</i></sup></p><p><b>Scannable, not verbose</b>. We'd tried to be thorough, explaining errors in technical detail. It backfired. Non-technical users found it alienating. Technical users didn't need it. Everyone was trying to read it in the tiny real estate of a widget. The lesson: less is more, especially in constrained spaces during stressful moments.</p><p><b>Accessible to everyone</b>. Our audit revealed 10px fonts in some states. Grey text that technically met AA (at least 4.5:1 for normal text and 3:1 for large text) compliance but was difficult to read in practice. "Technically compliant" isn't good enough when you're serving the entire Internet.</p><p>We set a clear goal: to meet the <a href="https://www.w3.org/TR/WCAG22/"><u>WCAG 2.2 AAA</u></a> standard— the highest and most stringent level of web accessibility compliance, designed to make content accessible to the broadest range of users, including those with severe disabilities. Throughout the redesign, when visual consistency conflicted with readability, readability won. Every time.</p><p>This extended beyond vision. We designed for screen reader users, keyboard-only navigators, and people with color vision variations — going beyond what automated compliance tools can catch.</p><p>And accessibility isn't just about impairments — it's about language. What fits in English, overflows in German. What's concise in Spanish is ambiguous in Japanese. Supporting over 40 languages forced us to radically simplify. The same "Unable to connect to website / Troubleshoot" pattern now works across English, Bulgarian, Danish, German, Greek, Japanese, Indonesian, Russian, Slovak, Slovenian, Serbian, Filipino, and many more.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6e4pvgMUS4BUXsPqi1qV6l/b6ffdc0d5f1e8e90394169db7162d10c/12.png" />
          </figure><p><sup><i>The redesigned error state across 12 languages — consistent layout despite varying text lengths </i></sup></p>
    <div>
      <h2>Final redesign</h2>
      <a href="#final-redesign">
        
      </a>
    </div>
    <p>So what did we actually ship?</p><p>First, let's talk about what we didn't change. The happy path — "Verify you are human" → "Verifying..." → "Success!" — tested exceptionally well. Users understood what was happening at each stage. The distinct content for each state, which we'd worried might be overcomplicating things, was actually our competitive advantage.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2R4QJ04uz9r1TVZjuqsHG9/61c1023eaa105b4841456258f3370220/13.png" />
          </figure><p><i><sup> The happy path: Verify you are human → Verifying → Success! These states tested well and remained largely unchanged</sup></i></p><p>But for the states that needed work, we made significant changes guided by everything we learned.</p>
    <div>
      <h3>Simplified, scannable content</h3>
      <a href="#simplified-scannable-content">
        
      </a>
    </div>
    <p>We radically reduced the amount of text in error states. Instead of verbose explanations like "Your device clock is set to a wrong time or this challenge page was accidentally cached by an intermediary and is no longer available," we now show:</p><ol><li><p>A clear, simple state name (e.g., "Incorrect device time")</p></li><li><p>A prominent "Troubleshoot" link</p></li></ol><p>That's it. The detailed guidance now lives in a dedicated modal screen that opens when users need it — giving them room to actually read and follow troubleshooting steps.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4ZYjlJgw6DOiTuJBFXpewn/5d714c3a19723dfe9fa9802d0d5926b8/14.png" />
          </figure><p><sup><i>The troubleshooting modal: detailed guidance when users need it, without cluttering the widget</i></sup></p><p>The troubleshooting modal provides context ("This error occurs when your device's clock or calendar is inaccurate. To complete this website’s security verification process, your device must be set to the correct date and time in your time zone."), numbered steps to try, links to documentation, and — only after the user has tried to resolve the issue — an option to submit feedback to Cloudflare. Help first, feedback second.</p>
    <div>
      <h3>AAA accessibility compliance</h3>
      <a href="#aaa-accessibility-compliance">
        
      </a>
    </div>
    <p>Every state now meets WCAG 2.2 AAA standards for contrast and readability. Font sizes have established minimums. Interactive elements are clearly focusable and properly announced by screen readers.</p>
    <div>
      <h3>Unified experience across Turnstile and Challenge pages</h3>
      <a href="#unified-experience-across-turnstile-and-challenge-pages">
        
      </a>
    </div>
    <p>Whether users encounter the compact Turnstile widget or a full Challenge Page, the information architecture is now consistent. Same hierarchy. Same placement. Same mental model.</p><p>Challenge Pages now follow a clean structure: the website name and favicon at the top, a clear status message (like "Verification successful" or "Your browser is out of date"), and actionable guidance below. No more walls of orange or red text. No more technical jargon without context.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4PuWePTOaLihpfqm2iimJW/e34c4a009c36524a6d72c15ae0f78d00/15.png" />
          </figure><p><sup><i>Re-designed Challenge page states with clear troubleshooting instructions.</i></sup></p>
    <div>
      <h3>Validated across languages</h3>
      <a href="#validated-across-languages">
        
      </a>
    </div>
    <p>Every piece of content was tested in over 40 supported languages. Our process involved three layers of validation:</p><ol><li><p>Initial design review by the design team</p></li><li><p>Professional translation by our qualified vendor</p></li><li><p>Final review by native-speaking Cloudflare employees</p></li></ol><p>This wasn't just about translation accuracy — it was about ensuring the visual design held up when content length varied dramatically between languages.</p>
    <div>
      <h3>The complete picture</h3>
      <a href="#the-complete-picture">
        
      </a>
    </div>
    <p>The result is a security verification experience that's clearer, more accessible, less frustrating, and — crucially — just as secure. We didn't compromise on protection to improve the experience. We proved that good design and strong security aren't in conflict.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5t6FRRzLamGaTbEiZqVpnf/92b688679d1c8265ba3c6fd4159061bf/16.png" />
          </figure><p><sup><i>Re-designed Turnstile widgets on the left and a re-designed Challenge page on the right</i></sup></p><p>But designing the experience was only half the battle. Shipping it to billions of users? That's where Ana comes in.</p>
    <div>
      <h2>Part 2: Shipping to billions</h2>
      <a href="#part-2-shipping-to-billions">
        
      </a>
    </div>
    
    <div>
      <h4><b>Beyond centering a div</b></h4>
      <a href="#beyond-centering-a-div">
        
      </a>
    </div>
    <p>Some may say the hardest part of being a Frontend Engineer is centering a div. In reality, the real challenge often lies much deeper, especially when working close to the platform primitives. Building a critical piece of Internet infrastructure using native APIs forces you to think differently about UI development, tradeoffs, and long-term maintainability.</p><p>In our case, we use Rust to handle the UI for both the Turnstile widget and the Challenge page. This decision brought clear benefits in terms of safety and consistency across platforms, but it also increased frontend complexity. Many of us are used to the ergonomics of modern frameworks like React, where common UI interactions come almost for free. Working with Rust meant reimplementing even simple interactions using lower level constructs like <i>document.getElementById</i>, <i>createElement</i>, and <i>appendChild</i>.</p><p>On top of that, compile times and strict checks naturally slowed down rapid UI iteration compared to JavaScript based frameworks. Debugging was also more involved, as the tooling ecosystem is still evolving. These constraints pushed us to be more deliberate, more thoughtful, and ultimately more disciplined in how we approached UI development.</p>
    <div>
      <h4><b>Small visual changes, big global impact</b></h4>
      <a href="#small-visual-changes-big-global-impact">
        
      </a>
    </div>
    <p>What initially looked like small visual tweaks such as padding adjustments or alignment changes quickly revealed a much bigger challenge: internationalization.</p><p>Once translations were available, we had to ensure that content remained readable and usable across 38 languages and 16 different UI states. Text length variability alone required careful design decisions. Some translations can be 30 to 300 percent longer than English. A short English string like “Stuck?” becomes “Tidak bisa melanjutkan?” in Indonesian or “Es geht nicht weiter?” in German, dramatically changing layout requirements.</p><p>Right-to-left language support added another layer of complexity. Supporting Arabic, Persian or Farsi, and Hebrew meant more than flipping text direction. Entire layouts had to be mirrored, including alignment, navigation patterns, directional icons, and animation flows. Many of these elements are implicitly designed with left-to-right assumptions, so we had to revisit those decisions and make them truly bidirectional.</p><p>Ordered lists also required special care. Not every culture uses the Western 1, 2, 3 numbering system, and hardcoding numeric sequences can make interfaces feel foreign or incorrect. We leaned on locale-aware numbering and fully translatable list formats to ensure ordering felt natural and culturally appropriate in every language.</p>
    <div>
      <h4><b>Building confidence through testing</b></h4>
      <a href="#building-confidence-through-testing">
        
      </a>
    </div>
    <p>As we started listing action points in feedback reports, correctness became even more critical. Every action needed to render properly, trigger the right flow, and behave consistently across states, languages, and edge cases.</p><p>To get there, we invested heavily in testing. Unit tests helped us validate logic in isolation, while end-to-end tests ensured that new states and languages worked as expected in real scenarios. This testing foundation gave us confidence to iterate safely, prevented regressions, and ensured that feedback reports remained reliable and actionable for users.</p>
    <div>
      <h4><b>The outcome</b></h4>
      <a href="#the-outcome">
        
      </a>
    </div>
    <p>What began as a set of technical constraints turned into an opportunity to build a more robust, inclusive, and well-tested UI system. Working with fewer abstractions and closer to the browser primitives forced us to rethink assumptions, improve our internationalization strategy, and raise the overall quality bar.</p><p>The result is not just a solution that works, but one we trust. And that trust is what allows us to keep improving, even when centering a div turns out to be the easy part.</p>
    <div>
      <h2>Part 3: The impact</h2>
      <a href="#part-3-the-impact">
        
      </a>
    </div>
    <p>Designing for billions of people is a responsibility we take seriously. At this scale, it is essential to leverage measurable data to tell us the real impact of our design choices. As we prepare to roll out these changes, we are focusing on <b>five key metrics</b> that will tell us if we’ve truly succeeded in making the Internet’s most-seen UI more human.</p>
    <div>
      <h4><b>1. Challenge Completion Rate</b></h4>
      <a href="#1-challenge-completion-rate">
        
      </a>
    </div>
    <p>Our primary north star is the <b>Challenge Solve Rate: </b>the percentage of issued challenges that are successfully completed. By moving away from technical jargon like "intermediary caching" and toward simple, actionable labels like "Incorrect device time," we expect a significant uptick in CSR. A higher CSR doesn't mean we're being easier on bots; it means we’re removing the hurdles that were accidentally tripping up legitimate human users.</p>
    <div>
      <h4><b>2. Time to Complete</b></h4>
      <a href="#2-time-to-complete">
        
      </a>
    </div>
    <p>Every second a user spends on a challenge page is a second they aren't getting the information that they need. Our research showed that users were often paralyzed by choice when seeing a wall of red text. With our new scannable, neutral-color design, we are tracking <b>Time to Complete</b> to ensure users can identify and resolve issues in seconds rather than minutes.</p>
    <div>
      <h4><b>3. Abandonment Rate Changes</b></h4>
      <a href="#3-abandonment-rate-changes">
        
      </a>
    </div>
    <p>In the past, our liberal use of "saturated red" caused a visceral reaction: users felt they had failed and simply gave up. By reserving red only for icons and using a unified architecture, we aim to reduce Abandonment Rates. We want users to feel empowered to click Troubleshoot rather than feeling powerless and clicking away.</p>
    <div>
      <h4><b>4. Support Ticket Volume</b></h4>
      <a href="#4-support-ticket-volume">
        
      </a>
    </div>
    <p>One of the bigger shifts from a product perspective is our new Troubleshooting Modal. By providing clear, numbered steps directly within the widget, we are building self-service support into the UI. We expect this to result in a measurable decrease in support ticket volume for both our customers and our own internal teams.</p>
    <div>
      <h4><b>5. Social Sentiment</b></h4>
      <a href="#5-social-sentiment">
        
      </a>
    </div>
    <p>We know that security challenges are rarely loved, but they shouldn't be hated because they are confusing. We are monitoring <b>Social Sentiment</b> across community forums, feedback reports, and social channels to see if the conversation shifts from "this widget is broken" to "I had an issue, but I fixed it".</p><p>As a Product Manager, my goal is often invisible security — the best challenge is the one the user never sees. But when a challenge <i>must</i> be seen, it should be an assistant, not a bouncer. This redesign proves that <b>AAA accessibility</b> and <b>high-security standards</b> aren't in competition; they are two sides of the same coin. By unifying the architecture of Turnstile and Challenge Pages, we’ve built a foundation that allows us to iterate faster and protect the Internet more humanely than ever before.</p>
    <div>
      <h2>Looking ahead</h2>
      <a href="#looking-ahead">
        
      </a>
    </div>
    <p>This redesign is a foundation, not a finish line.</p><p>We're continuing to monitor how users interact with the new experience, and we're committed to iterating based on what we learn. The feedback mechanisms we've built into the new design — the ones that actually help users troubleshoot, rather than just asking them to report problems — will give us richer insights than we've ever had before.</p><p>We're also watching how the security landscape evolves. As bot attacks grow more sophisticated, and as AI continues to blur the line between human and automated behavior, the challenge of verification will only get harder. Our job is to stay ahead — to keep improving security without making the human experience worse.</p><p>If you encounter the new Turnstile or Challenge Pages and have feedback, we want to hear it. Reach out through our <a href="https://community.cloudflare.com/"><u>community forums</u></a> or use the feedback mechanisms built into the experience itself.</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Turnstile]]></category>
            <category><![CDATA[Challenge Page]]></category>
            <category><![CDATA[Design]]></category>
            <category><![CDATA[Product Design]]></category>
            <category><![CDATA[User Research]]></category>
            <category><![CDATA[Bots]]></category>
            <category><![CDATA[Bot Management]]></category>
            <category><![CDATA[WAF]]></category>
            <category><![CDATA[Engineering]]></category>
            <category><![CDATA[Product News]]></category>
            <category><![CDATA[Accessibility]]></category>
            <guid isPermaLink="false">19fiiQAG0XsaS9p0daOBus</guid>
            <dc:creator>Leo Bacevicius</dc:creator>
            <dc:creator>Ana Foppa</dc:creator>
            <dc:creator>Marina Elmore</dc:creator>
        </item>
        <item>
            <title><![CDATA[ASPA: making Internet routing more secure]]></title>
            <link>https://blog.cloudflare.com/aspa-secure-internet/</link>
            <pubDate>Fri, 27 Feb 2026 06:00:00 GMT</pubDate>
            <description><![CDATA[ ASPA is the cryptographic upgrade for BGP that helps prevent route leaks by verifying the path network traffic takes. New features in Cloudflare Radar make tracking its adoption easy. ]]></description>
            <content:encoded><![CDATA[ <p>Internet traffic relies on the <a href="https://www.cloudflare.com/learning/security/glossary/what-is-bgp/"><u>Border Gateway Protocol (BGP)</u></a> to find its way between networks. However, this traffic can sometimes be misdirected due to configuration errors or malicious actions. When traffic is routed through networks it was not intended to pass through, it is known as a <a href="https://datatracker.ietf.org/doc/html/rfc7908"><u>route leak</u></a>. We have <a href="https://blog.cloudflare.com/bgp-route-leak-venezuela/"><u>written on our blog</u></a> <a href="https://blog.cloudflare.com/cloudflare-1111-incident-on-june-27-2024/"><u>multiple times</u></a> about <a href="https://blog.cloudflare.com/route-leak-detection-with-cloudflare-radar/"><u>BGP route leaks</u></a> and the impact they have on Internet routing, and a few times we have even alluded to a future of path verification in BGP. </p><p>While the network community has made significant progress in verifying the final destination of Internet traffic, securing the actual path it takes to get there remains a key challenge for maintaining a reliable Internet. To address this, the industry is adopting a new cryptographic standard called <a href="https://datatracker.ietf.org/doc/draft-ietf-sidrops-aspa-verification/"><u>ASPA (Autonomous System Provider Authorization)</u></a>, which is designed to validate the entire path of network traffic and prevent route leaks.</p><p>To help the community track the rollout of this standard, Cloudflare Radar has introduced a new ASPA deployment monitoring feature. This view allows users to observe ASPA adoption trends over time across the five<a href="https://en.wikipedia.org/wiki/Regional_Internet_registry"><u> Regional Internet Registries (RIRs)</u></a>, and view ASPA records and changes over time at the<a href="https://www.cloudflare.com/learning/network-layer/what-is-an-autonomous-system/"><u> Autonomous System (AS)</u></a> level.</p>
    <div>
      <h2>What is ASPA?</h2>
      <a href="#what-is-aspa">
        
      </a>
    </div>
    <p>To understand how ASPA works, it is helpful to look at how the Internet currently secures traffic destinations.</p><p>Today, networks use a secure infrastructure system called <a href="https://en.wikipedia.org/wiki/Resource_Public_Key_Infrastructure"><u>RPKI (Resource Public Key Infrastructure)</u></a>, which has seen <a href="https://blog.apnic.net/2026/02/20/rpkis-2025-year-in-review/"><u>significant deployment growth</u></a> over the past few years. Within RPKI, networks publish specific cryptographic records called ROAs (Route Origin Authorizations). A ROA acts as a verifiable digital ID card, confirming that an Autonomous System (AS) is officially authorized to announce specific IP addresses. This addresses the "origin hijacks" issue, where one network attempts to impersonate another.</p><p><a href="https://datatracker.ietf.org/doc/draft-ietf-sidrops-aspa-verification/"><u>ASPA (Autonomous System Provider Authorization)</u></a> builds directly on this foundation. While a ROA verifies the <i>destination</i>, an ASPA record verifies the <i>journey</i>.</p><p>When data travels across the Internet, it keeps a running log of every network it passes through. In BGP, this log is known as the <a href="https://datatracker.ietf.org/doc/html/rfc4271#section-5.1.2"><code><u>AS_PATH</u></code></a> (Autonomous System Path). ASPA provides networks with a way to officially publish a list of their authorized upstream providers within the RPKI system. This allows any receiving network to look at the <code>AS_PATH</code>, check the associated ASPA records, and verify that the traffic only traveled through an approved chain of networks.</p><p>A ROA helps ensure the traffic arrives at the correct destination, ASPA ensures the traffic takes an intended, authorized route to get there. Let’s take a look at how path evaluation actually works in practice.</p>
    <div>
      <h2>Route leak detection with ASPA</h2>
      <a href="#route-leak-detection-with-aspa">
        
      </a>
    </div>
    <p>How does ASPA know if a route is a <i>detour</i>? It relies on the hierarchy of the Internet.</p><p>In a healthy Internet routing topology (e.g. <a href="https://ieeexplore.ieee.org/document/6363987"><u>“valley-free” routing</u></a>), traffic generally follows a specific path: it travels "up" from a customer to a large provider (like a major ISP), optionally crosses over to another big provider, and then flows "down" to the destination. You can visualize this as a “mountain” shape:</p><ol><li><p><b>The Up-Ramp:</b> Traffic starts at a Customer and travels "up" through larger and larger Providers (ISPs), where ISPs pay other ISPs to transit traffic for them.</p></li><li><p><b>The Apex:</b> It reaches the top tier of the Internet backbone and may cross a single peering link.</p></li></ol><p><b>The Down-Ramp:</b> It travels "down" through providers to reach the destination Customer.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1VGuSHfq6GcQZUYLGmoDH3/a1486f40c16e568f32ca2fa81d58ac41/1.png" />
          </figure><p><sup><i>A visualization of "valley-free" routing. Routes propagate up to a provider, optionally across one peering link, and down to a customer.</i></sup></p><p>In this model, a route leak is like a valley, or dip. One type of such leak happens when traffic goes down to a customer and then unexpectedly tries to go back <i>up</i> to another provider. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6eoaEpdIJpCCLbMnNZD5ob/7ceca2a98f2252e8161915b942bf7dbd/2.png" />
          </figure><p>This "down-and-up" movement is undesirable as customers aren't intended nor equipped to transit traffic between two larger network providers.</p>
    <div>
      <h4>How ASPA validation works</h4>
      <a href="#how-aspa-validation-works">
        
      </a>
    </div>
    <p>ASPA gives network operators a cryptographic way to declare their <i>authorized providers,</i> enabling receiving networks to verify that an AS path follows this expected structure.</p><p>ASPA validates AS paths by checking the “chain of relationships” from both ends of the routes propagation:</p><ul><li><p><b>Checking the Up-Ramp:</b> The check starts at the origin and moves forward. At every hop, it asks: <i>"Did this network authorize the next network as a Provider?"</i> It keeps going until the chain stops.</p></li><li><p><b>Checking the Down-Ramp:</b> It does the same thing from the destination of a BGP update, moving backward.</p></li></ul><p>If the "Up" path and the "Down" path overlap or meet at the top, the route is <b>Valid</b>. The mountain shape is intact.</p><p>However, if the two valid paths <b>do not meet</b>, i.e. there is a gap in the middle where authorization is missing or invalid, ASPA reports such paths as problematic. That gap represents the "valley" or the leak.</p>
    <div>
      <h4>Validation process example</h4>
      <a href="#validation-process-example">
        
      </a>
    </div>
    <p>Let’s look at a scenario where a network (AS65539) receives a bad route from a customer (AS65538).</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7kn8W6c7CaPcMLMycjS5NO/59036dc52a942870e9bb0e377f235dd4/3.png" />
          </figure><p>The customer (AS65538) is trying to send traffic received from one provider (AS65537) "up" to another provider (AS65539), acting like a bridge between providers. This is a <a href="https://datatracker.ietf.org/doc/html/rfc7908#autoid-4"><u>classic route leak</u></a>. Now let’s walk the ASPA validation process.</p><ol><li><p>We check the <b>Up-Ramp</b>: The original source (AS65536) authorizes its provider. (Check passes).</p></li><li><p>We check the <b>Down-Ramp</b>: We start from the destination and look back. We see the customer (AS65538).</p></li><li><p><b>The Mismatch:</b> The up-ramp ends at AS65537, while the down-ramp ends at 65538. The two ramps do not connect.</p></li></ol><p>Because the "Up" path and "Down" path fail to connect, the system flags this as ASPA <b>Invalid</b>. ASPA is required to do this path validation, as without signed ASPA objects in RPKI, we cannot find which networks are authorized to advertise which prefixes to whom. By signing a list of provider networks for each AS, we know which networks should be able to propagate prefixes laterally or upstream.</p>
    <div>
      <h3>ASPA against forged-origin hijacks</h3>
      <a href="#aspa-against-forged-origin-hijacks">
        
      </a>
    </div>
    <p>ASPA can serve as an effective defense against <a href="https://www.usenix.org/conference/nsdi24/presentation/holterbach"><u>forged-origin hijacks</u></a>, where an attacker bypasses Route Origin Validation (ROV) by pretending and advertising a BGP path to a real origin prefix. Although the origin AS remains correct, the relationship between the hijacker and the victim is fabricated.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6MNVRoNDzxlHDVGTP2nRPw/87485ad246baa734eef3192fd48012a8/4.png" />
          </figure><p>ASPA exposes this deception by allowing the victim network to cryptographically declare its actual authorized providers; because the hijacker is not on that authorized list, the path is rejected as invalid, effectively preventing the malicious redirection.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2KGtsKWBdlNFySIswRb5rD/d26b266c2dc942be9b9f6c6ec383843b/5.png" />
          </figure><p>ASPA cannot fully protect against forged-origin hijacks, however. There is still at least one case where not even ASPA validation can fully prevent this type of attack on a network. An example of a forged-origin hijack that ASPA cannot account for is when a provider forges a path advertisement <i>to their customer.</i></p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3DPYEXwSUPmWUWvsyxFJHX/b059dae85cf764fdcd5a5257f5ebc373/6.png" />
          </figure><p>Essentially, a provider could “fake” a peering link with another AS to attract traffic from a customer with a short AS_PATH length, even when no such peering link exists. ASPA does not prevent this path forgery by the provider, because ASPA only works off of provider information and knows nothing specific about peering relationships.</p><p>So while ASPA can be an effective means of rejecting forged-origin hijack routes, there are still some rare cases where it will be ineffective, and those are worth noting.</p>
    <div>
      <h2>Creating ASPA objects: just a few clicks away</h2>
      <a href="#creating-aspa-objects-just-a-few-clicks-away">
        
      </a>
    </div>
    <p>Creating an ASPA object for your network (or Autonomous System) is now a simple process in registries like <a href="https://labs.ripe.net/author/tim_bruijnzeels/aspa-in-the-rpki-dashboard-a-new-layer-of-routing-security/"><u>RIPE</u></a> and <a href="https://www.arin.net/announcements/20260120/"><u>ARIN</u></a>. All you need is your AS number and the AS numbers of the providers you purchase Internet transit service from. These are the authorized upstream networks you trust to announce your IP addresses to the wider Internet. In the opposite direction, these are also the networks you authorize to send you a full routing table, which acts as the complete map of how to reach the rest of the Internet.</p><p>We’d like to show you just how easy creating an ASPA object is with a quick example. </p><p>Say we need to create the ASPA object for AS203898, an AS we use for our Cloudflare London office Internet. At the time of writing we have three Internet providers for the office: AS8220, AS2860, and AS1273. This means we will create an ASPA object for AS203898 with those three provider members in a list.</p><p>First, we log into the RIPE <a href="https://dashboard.rpki.ripe.net/#overview"><u>RPKI dashboard</u></a> and navigate to the <a href="https://dashboard.rpki.ripe.net/#aspa"><u>ASPA</u></a> section:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3CCFItZpP8JbYCotDGfuM3/c7ad0041ceea4f48c37ff59f416f8242/7.png" />
          </figure><p>Then, we click on “Create ASPA” for the object we want to create an ASPA object for. From there, we just fill in the providers for that AS. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6ABmfhRQQRbLhMat6Ug01K/3a9d73ad8ade315416c4cc6eb9073ada/8.png" />
          </figure><p>It’s as simple as that. After just a short period of waiting, we can query the global RPKI ecosystem and find our ASPA object for AS203898 with the providers we defined. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/xAKD1b704fg7SMxeg867P/59ce564867565331e2d531de15dc7e87/Screenshot_2026-02-27_at_11.09.55.png" />
          </figure><p>It’s a similar story with <a href="https://www.arin.net/"><u>ARIN</u></a>, the only other <a href="https://en.wikipedia.org/wiki/Regional_Internet_registry"><u>Regional Internet Registries (RIRs)</u></a> that currently supports the creation of ASPA objects. Log in to <a href="https://account.arin.net/public/login"><u>ARIN online,</u></a> then navigate to Routing Security, and click “Manage RPKI”.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/PTCdyldcTc1Uc0iazZlg4/51ed97a8ef0d095b947f7ab2bf4b1fd3/9.png" />
          </figure><p>From there, you’ll be able to click on “Create ASPA”. In this example, we will create an object for another one of our ASNs, AS400095.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4bLLHAeU4Eaz6RPgSPDzn9/a482b6c7ed4ef78f7346ca80c9a5ba46/10.png" />
          </figure><p>And that’s it – now we have created our ASPA object for AS40095 with provider AS0.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/9yOZPpMH4olQXu2DNpJPO/cca432fd82e61c6492987b7ccedbdc57/11.png" />
          </figure>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6emDXxMbU0BSKk5BVXUdJ6/132b9a7279b93e3ae0329dec83a9bfac/Screenshot_2026-02-27_at_11.11.31.png" />
          </figure><p>The “AS0” provider entry is special when used, and means the AS owner attests there are <b>no</b> valid upstream providers for their network. By definition this means every transit-free Tier-1 network should eventually sign an ASPA with only “AS0” in their object, if they truly only have peer and customer relationships.</p>
    <div>
      <h2>New ASPA features in Cloudflare Radar </h2>
      <a href="#new-aspa-features-in-cloudflare-radar">
        
      </a>
    </div>
    <p>We have added a new ASPA deployment monitoring feature to <a href="https://radar.cloudflare.com/"><u>Cloudflare Radar</u></a>. The new ASPA deployment view allows users to examine the growth of ASPA adoption over time, with the ability to visualize trends across the five <a href="https://en.wikipedia.org/wiki/Regional_Internet_registry"><u>Regional Internet Registries</u></a> (RIRs) based on AS registration. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7FoW86CVloqBqZO7wcOiq8/f5f2973db227b8184127f76fdad64dc4/12.png" />
          </figure><p>We have also integrated ASPA data directly into the country/region and ASN routing pages. Users can now track how different locations are progressing in securing their infrastructure, based on the associated ASPA records from the customer ASNs registered locally.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1tBhOpIxc6tNOJXWPPAk4U/7c334c9ddb089eb823ce23eb49ddbdc3/13.png" />
          </figure><p>There are also new features when you zoom into a particular Autonomous System (AS), for example <a href="https://radar.cloudflare.com/routing/AS203898#connectivity"><u>AS203898</u></a>.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7nTBPD0PgzPOS0eOxpG3rW/65d9b312be2e81e4c59164c98b7b6276/14.png" />
          </figure><p>We can see whether a network’s observed BGP upstream providers are ASPA authorized, their full list of providers in their ASPA object, and the timeline of ASPA changes that involve their AS.</p>
    <div>
      <h2>The road to better routing security</h2>
      <a href="#the-road-to-better-routing-security">
        
      </a>
    </div>
    <p>With ASPA finally becoming a reality, we have our cryptographic upgrade for Internet path validation. However, those who have been around since the start of RPKI for route origin validation know <a href="https://manrs.org/2023/05/estimating-the-timeline-for-aspa-deployment/"><u>this will be a long road</u></a> to actually providing significant value on the Internet. Changes are needed to RPKI Relaying Party (RP) packages, signer implementations, RTR (RPKI-to-Router protocol) software, and BGP implementations to actually use ASPA objects and validate paths with them.</p><p>In addition to ASPA adoption, operators should also configure BGP roles as described within <a href="https://datatracker.ietf.org/doc/rfc9234/"><u>RFC9234</u></a>. The BGP roles configured on BGP sessions will help future ASPA implementations on routers <a href="https://datatracker.ietf.org/doc/html/draft-ietf-sidrops-aspa-verification-24#section-6.3"><u>decide which algorithm to apply</u></a>: <i>upstream</i> or <i>downstream</i>. In other words, BGP roles give us the power as operators to directly tie our intended BGP relationships with another AS to sessions with those neighbors. Check with your routing vendors and make sure they support <a href="https://datatracker.ietf.org/doc/rfc9234/"><u>RFC9234 BGP roles and OTC</u></a> (Only-to-Customer) attribute implementation.</p><p>To get the most out of ASPA, we encourage everyone to create their ASPA objects for their AS<i>. </i>Creating and maintaining these ASPA objects requires careful attention. In the future, as networks use these records to actively block invalid paths, omitting a legitimate provider could cause traffic to be dropped. However, managing this risk is no different from how networks already handle Route Origin Authorizations (ROAs) today. ASPA is the necessary cryptographic upgrade for Internet path validation, and we’re happy it’s here!</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[BGP]]></category>
            <category><![CDATA[RPKI]]></category>
            <category><![CDATA[Routing]]></category>
            <category><![CDATA[Routing Security]]></category>
            <category><![CDATA[Radar]]></category>
            <guid isPermaLink="false">5NwDf8fspgoSx9Pgcx1xLy</guid>
            <dc:creator>Mingwei Zhang</dc:creator>
            <dc:creator>Bryton Herdes</dc:creator>
        </item>
        <item>
            <title><![CDATA[Security Week 2025: in review]]></title>
            <link>https://blog.cloudflare.com/security-week-2025-wrap-up/</link>
            <pubDate>Mon, 24 Mar 2025 13:05:00 GMT</pubDate>
            <description><![CDATA[ Security Week 2025 has officially come to a close. Our updates for the week included a deep dive on our AI offering, a unified navigation experience, and an introduction to our AI Agent Cloudy. ]]></description>
            <content:encoded><![CDATA[ <p>Thank you for following along with another Security Week at Cloudflare. We’re extremely proud of the work our team does to make the Internet safer and to help meet the challenge of emerging threats. As our CISO Grant Bourzikas outlined in his <a href="https://blog.cloudflare.com/welcome-to-security-week-2025/"><u>kickoff post</u></a> this week, security teams are facing a landscape of rapidly increasing complexity introduced by vendor sprawl, an “AI Boom”, and an ever-growing surface area to protect.</p><p>As we continuously work to meet new challenges, Innovation Weeks like Security Week give us an invaluable opportunity to share our point of view and engage with the wider Internet community. Cloudflare’s mission is to <i>help</i> build a better Internet. We want to help safeguard the Internet from the arrival of quantum supercomputers, help protect the livelihood of content creators from <a href="https://www.cloudflare.com/learning/ai/how-to-prevent-web-scraping/">unauthorized AI scraping</a>, help raise awareness of the latest Internet threats, and help find new ways to help reduce the reuse of compromised passwords. Solving these challenges will take a village. We’re grateful to everyone who has engaged with us on these issues via social media, contributed to <a href="https://github.com/cloudflare"><u>our open source repositories</u></a>, and reached out through our <a href="https://www.cloudflare.com/partners/technology-partners/"><u>technology partner program</u></a> to work with us on the issues most important to them. For us, that’s the best part.</p><p>Here’s a recap of this week’s announcements:</p>
    <div>
      <h3>Helping make the Internet safer</h3>
      <a href="#helping-make-the-internet-safer">
        
      </a>
    </div>
    <table><tr><td><p><b>Title</b></p></td><td><p><b>Excerpt</b></p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/post-quantum-zero-trust/"><u>Conventional cryptography is under threat. Upgrade to post-quantum cryptography with Cloudflare Zero Trust</u></a></p></td><td><p>We’re thrilled to announce that organizations can now protect their sensitive corporate network traffic against quantum threats by tunneling it through Cloudflare’s Zero Trust platform.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/how-cloudflare-is-using-automation-to-tackle-phishing/"><u>How Cloudflare is using automation to tackle phishing head on</u></a></p></td><td><p>How Cloudflare is using threat intelligence and our Developer Platform products to automate phishing abuse reports.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/advancing-account-security-as-part-of-cloudflare-commitment-to-cisa-secure-by-design-pledge/"><u>Advancing account security as part of Cloudflare’s commitment to CISA’s Secure by Design pledge</u></a></p></td><td><p>Cloudflare has made significant progress in boosting multi-factor authentication (MFA) adoption. With the addition of Apple and Google social logins, we’ve made secure access easier for our users.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/email-security-now-available-for-free-for-political-parties-and-campaigns/"><u>Email Security now available for free for political parties and campaigns through Cloudflare for Campaigns</u></a></p></td><td><p>We’re excited to announce that Cloudflare for Campaigns now includes Email Security, adding an extra layer of protection to email systems that power political campaigns.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/enhanced-security-and-simplified-controls-with-automated-botnet-protection/"><u>Enhanced security and simplified controls with automated botnet protection, cipher suite selection, and URL Scanner updates</u></a></p></td><td><p>Enhanced security, simplified control! This Security Week, Cloudflare unveils automated botnet protection, flexible cipher suites, and an upgraded URL Scanner.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/password-reuse-rampant-half-user-logins-compromised/"><u>Password reuse is rampant: nearly half of user logins are compromised</u></a></p></td><td><p>Nearly half of login attempts across websites protected by Cloudflare involved leaked credentials. The pervasive issue of password reuse is enabling automated bot attacks on a massive scale.</p></td></tr></table>
    <div>
      <h3>Threat research from the network that sees the most threats </h3>
      <a href="#threat-research-from-the-network-that-sees-the-most-threats">
        
      </a>
    </div>
    <table><tr><td><p><b>Title</b></p></td><td><p><b>Excerpt</b></p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/threat-events-platform/"><u>Unleashing improved context for threat actor activity with our Cloudforce One threat events platform</u></a></p></td><td><p>Gain real-time insights with our new threat events platform. This tool empowers your cybersecurity defense with actionable intelligence to stay ahead of attacks and protect your critical assets.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/cloudflare-security-posture-management/"><u>One platform to manage your company’s predictive security posture with Cloudflare</u></a></p></td><td><p>Cloudflare introduces a single platform for unified security posture management, helping protect SaaS and web applications deployed across various environments.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/monitoring-and-forensics/"><u>Cloudflare enables native monitoring and forensics with Log Explorer and custom dashboards</u></a></p></td><td><p>We are excited to announce support for Zero Trust datasets, and custom dashboards where customers can monitor critical metrics for suspicious or unusual activity</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/upgraded-turnstile-analytics-enable-deeper-insights-faster-investigations/"><u>Introducing new Turnstile Analytics: Gain insight into your visitor traffic, bot behavior patterns, traffic anomalies, and attack attributes.</u></a></p></td><td><p>Introducing new Turnstile Analytics: gain insight into your visitor traffic, bot behavior patterns, traffic anomalies, and attack attributes.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/cloudflare-radar-ddos-leaked-credentials-bots/"><u>Extending Cloudflare Radar’s security insights with new DDoS, leaked credentials, and bots datasets</u></a></p></td><td><p>For Security Week 2025, we are adding several new DDoS-focused graphs, new insights into leaked credential trends, and a new Bots page to Cloudflare Radar.</p></td></tr></table>
    <div>
      <h3>Securing models and guarding against AI threats </h3>
      <a href="#securing-models-and-guarding-against-ai-threats">
        
      </a>
    </div>
    <table><tr><td><p><b>Title</b></p></td><td><p><b>Excerpt</b></p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/cloudflare-for-ai-supporting-ai-adoption-at-scale-with-a-security-first-approach/"><u>Cloudflare for AI: supporting AI adoption at scale with a security-first approach</u></a></p></td><td><p>With Cloudflare for AI, developers, security teams, and content creators can leverage Cloudflare’s network and portfolio of tools to secure, observe, and make AI applications resilient and safe to use.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/how-we-train-ai-to-uncover-malicious-javascript-intent-and-make-web-surfing-safer/"><u>How we train AI to uncover malicious JavaScript intent and make web surfing safer</u></a></p></td><td><p>Learn more about how Cloudflare developed an AI model to uncover malicious JavaScript intent using a Graph Neural Network, from pre-processing data to inferencing at scale.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/an-early-look-at-cryptographic-watermarks-for-ai-generated-content/"><u>An early look at cryptographic watermarks for AI-generated content</u></a></p></td><td><p>It's hard to tell the difference between web content produced by humans and web content produced by AI. We're taking a new approach to making AI content distinguishable without impacting performance.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/ai-labyrinth/"><u>How Cloudflare uses generative AI to slow down, confuse, and waste the resources of AI Crawlers and other bots that don’t respect “no crawl” directives.</u></a></p></td><td><p>How Cloudflare uses generative AI to slow down, confuse, and waste the resources of AI Crawlers and other bots that don’t respect “no crawl” directives.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/take-control-of-public-ai-application-security-with-cloudflare-firewall-for-ai/"><u>Take control of public AI application security with Cloudflare's Firewall for AI</u></a></p></td><td><p>Firewall for AI discovers and protects your public LLM-powered applications, and is seamlessly integrated with Cloudflare WAF. Join the beta now and take control of your generative AI security</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/bots-heuristics/"><u>Improved Bot Management flexibility and visibility with new high-precision heuristics</u></a></p></td><td><p>By building and integrating a new heuristics framework into the Cloudflare Ruleset Engine, we now have a more flexible system to write rules and deploy new releases rapidly</p></td></tr></table>
    <div>
      <h3>Simplifying security</h3>
      <a href="#simplifying-security">
        
      </a>
    </div>
    <table><tr><td><p><b>Title</b></p></td><td><p><b>Excerpt</b></p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/introducing-ai-agent/"><u>Introducing Cloudy, Cloudflare’s AI agent for simplifying complex configurations</u></a></p></td><td><p>Cloudflare’s first AI agent, Cloudy, helps make complicated configurations easy to understand for Cloudflare administrators.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/new-application-security-experience/"><u>Making Application Security simple with a new unified dashboard experience</u></a></p></td><td><p>We’re introducing a new Application Security experience in the Cloudflare dashboard, with a reworked UI organized by use cases, making it easier for customers to navigate and secure their accounts</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/improved-support-for-private-applications-and-reusable-access-policies-with-cloudflare-access/"><u>Improved support for private applications and reusable access policies with Cloudflare Access</u></a></p></td><td><p>We are excited to introduce support for private hostname and IP address-defined applications as well as reusable access policies.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/aegis-deep-dive/"><u>Simplify allowlist management and lock down origin access with Cloudflare Aegis</u></a></p></td><td><p>Cloudflare Aegis provides dedicated egress IPs for Zero Trust origin access strategies, now supporting BYOIP and customer-facing configurability, with observability of Aegis IP address utilization coming soon.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/https-only-for-cloudflare-apis-shutting-the-door-on-cleartext-traffic"><u>HTTPS-only for Cloudflare APIs: shutting the door on cleartext traffic</u></a></p></td><td><p>We are closing the cleartext HTTP ports entirely for Cloudflare API traffic. This prevents the risk of clients unintentionally leaking their secret API keys in cleartext during the initial request, before we can reject the connection at the server side.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/cloudflare-named-leader-waf-forrester-2025/"><u>Cloudflare named a leader in Web Application Firewall Solutions in 2025 Forrester report</u></a></p></td><td><p>Forrester Research has recognized Cloudflare as a Leader in its The Forrester Wave™: Web Application Firewall Solutions, Q1 2025 report.</p></td></tr></table>
    <div>
      <h3>Data security everywhere, all the time </h3>
      <a href="#data-security-everywhere-all-the-time">
        
      </a>
    </div>
    <table><tr><td><p><b>Title</b></p></td><td><p><b>Excerpt</b></p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/scan-cloud-dlp-with-casb"><u>Detecting sensitive data and misconfigurations in AWS and GCP with Cloudflare One</u></a></p></td><td><p>Using Cloudflare’s CASB, integrate, scan, and detect sensitive data and misconfigurations in your cloud storage accounts.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/browser-based-rdp"><u>RDP without the risk: Cloudflare's browser-based solution for secure third-party access</u></a></p></td><td><p>Cloudflare now provides clientless, browser-based support for the Remote Desktop Protocol (RDP). It natively enables secure, remote Windows server access without VPNs or RDP clients, to support third-party access and BYOD security.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/improving-data-loss-prevention-accuracy-with-ai-context-analysis"><u>Improving Data Loss Prevention accuracy with AI-powered context analysis</u></a></p></td><td><p>Cloudflare’s Data Loss Prevention is reducing false positives by using a self-improving AI-powered algorithm, built on Cloudflare’s Developer Platform, to improve detection accuracy through AI context analysis.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/enhance-data-protection-in-microsoft-outlook-with-cloudflare-ones-new-dlp"><u>Enhance data protection in Microsoft Outlook with Cloudflare One’s new DLP Assist</u></a></p></td><td><p>Customers can now easily safeguard sensitive data in Microsoft Outlook with our new DLP Assist feature.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/lattice-crypto-primer"><u>Prepping for post-quantum: a beginner’s guide to lattice cryptography</u></a></p></td><td><p>This post is a beginner's guide to lattices, the math at the heart of the transition to post-quantum (PQ) cryptography. It explains how to do lattice-based encryption and authentication from scratch.</p></td></tr><tr><td><p><a href="https://blog.cloudflare.com/irap-protected-assessment"><u>Cloudflare is now IRAP assessed at the PROTECTED level, furthering our commitment to the global public sector</u></a></p></td><td><p>Cloudflare is now assessed at the IRAP PROTECTED level, bringing our products and services to the Australian Public Sector.</p></td></tr></table>
    <div>
      <h2>Tune in to the latest on Cloudflare TV</h2>
      <a href="#tune-in-to-the-latest-on-cloudflare-tv">
        
      </a>
    </div>
    <p>For a deeper dive on many of the great announcements from Security Week, <a href="https://www.cloudflare.com/security-week-2025/cloudflare-tv/"><u>check out our CFTV segments</u></a> where our team shares even more details on our latest updates. </p><div>
  
</div>
<p></p>
    <div>
      <h2>See you for our next Innovation Week</h2>
      <a href="#see-you-for-our-next-innovation-week">
        
      </a>
    </div>
    <p>We appreciate everyone who’s taken the time to read Cloudflare’s Security Week blog posts or engage with us on these topics via social media. Our next innovation week, <a href="https://www.cloudflare.com/developer-week-2024/updates/"><u>Developer Week</u></a>, is right around the corner in April. We look forward to seeing you then!</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Application Security]]></category>
            <category><![CDATA[Zero Trust]]></category>
            <category><![CDATA[Email Security]]></category>
            <category><![CDATA[AI]]></category>
            <guid isPermaLink="false">57bTt5UYhnjdF2MwuEePqb</guid>
            <dc:creator>Kim Blight</dc:creator>
            <dc:creator>Adam Martinetti</dc:creator>
            <dc:creator>Alex Dunbrack</dc:creator>
        </item>
        <item>
            <title><![CDATA[Detecting sensitive data and misconfigurations in AWS and GCP with Cloudflare One]]></title>
            <link>https://blog.cloudflare.com/scan-cloud-dlp-with-casb/</link>
            <pubDate>Fri, 21 Mar 2025 13:10:00 GMT</pubDate>
            <description><![CDATA[ Using Cloudflare’s CASB, integrate, scan, and detect sensitive data and misconfigurations in your cloud storage accounts. ]]></description>
            <content:encoded><![CDATA[ <p>Today is the final day of Security Week 2025, and after a great week of blog posts across a variety of topics, we’re excited to share the latest on Cloudflare’s data security products.</p><p>This announcement takes us to Cloudflare’s SASE platform, <a href="https://www.cloudflare.com/zero-trust/products/"><u>Cloudflare One</u></a>, used by enterprise security and IT teams to manage the security of their employees, applications, and third-party tools, all in one place.</p><p>Starting today, Cloudflare One users can now use the <a href="https://www.cloudflare.com/zero-trust/products/casb/"><u>CASB</u></a> (Cloud Access Security Broker) product to integrate with and scan Amazon Web Services (AWS) S3 and Google Cloud Storage, for posture- and Data Loss Prevention (DLP)-related security issues. <a href="https://dash.cloudflare.com/sign-up"><u>Create a free account</u></a> to check it out.</p><p>Scanning both point-in-time and continuously, users can identify misconfigurations in Identity and Access Management (IAM), bucket, and object settings, and detect sensitive information, like Social Security numbers, credit card numbers, or any other pattern using regex, in cloud storage objects.</p>
    <div>
      <h3>Cloud DLP</h3>
      <a href="#cloud-dlp">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1R1bE9TRmTdHDTg1XeLS60/8269b687ec65e70bcaee437f30d5f590/1.png" />
          </figure><p>Over the last few years, our customers — predominantly security and IT teams — have told us about their appreciation for CASB’s simplicity and effectiveness as a SaaS security product. Its number of <a href="https://developers.cloudflare.com/cloudflare-one/applications/casb/casb-integrations/"><u>supported integrations</u></a>, its ease of setup, and speed in identifying critical issues across popular SaaS platforms, like files shared publicly in Microsoft 365 and exposed sensitive data in Google Workspace, has made it a go-to for many.</p><p>However, as we’ve engaged with customers, one thing became clear: the risks of unmonitored or exposed data at-rest go far beyond just SaaS environments. Sensitive information – whether intellectual property, customer data, or personal identifiers – can wreak havoc on an organization’s reputation and its obligations to its customers if it falls into the wrong hands. For many of our customers, the security of data stored in cloud providers like AWS and GCP is even more critical than the security of data in their SaaS tools.</p><p>That’s why we’ve extended Cloudflare CASB to include <a href="https://developers.cloudflare.com/cloudflare-one/policies/data-loss-prevention/"><u>Cloud DLP (Data Loss Prevention)</u></a> functionality, enabling users to scan objects in Amazon S3 buckets and Google Cloud Storage for sensitive data matches​.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5TKXiAkQKxw3GFQBCuQLjX/198e4620da8239280eff669b7b62678b/2.png" />
          </figure><p>With <a href="https://www.cloudflare.com/zero-trust/products/dlp/"><u>Cloudflare DLP</u></a>, you can choose from pre-built detection profiles that look for common data types (such as Social Security Numbers or credit card numbers) or create your own custom profiles using regular expressions​. As soon as an object matching a DLP profile is detected, you can dive into the details, understanding the file’s context, seeing who owns it, and more. These capabilities provide the insight needed to quickly protect data and prevent exposure in real time.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4cyOaQJ0ZyPO8r7LyeU6ON/30b8453888d6cb13dcb15225f875a0cd/3.png" />
          </figure><p>And as with all CASB integrations, this new functionality also comes with <a href="https://www.cloudflare.com/learning/cloud/what-is-dspm/">posture management features</a>, meaning whether you’re using AWS or GCP, we’ll help you identify misconfigurations and other cloud security issues that could leave your data vulnerable​, like buckets that are publicly-accessible or have critical logging settings disabled, access keys needing rotation, or users without <a href="https://www.cloudflare.com/learning/access-management/what-is-multi-factor-authentication/"><u>multi-factor authentication (MFA)</u></a>. It’s all included.</p>
    <div>
      <h3>Simple by default, configurable where you want it</h3>
      <a href="#simple-by-default-configurable-where-you-want-it">
        
      </a>
    </div>
    <p>Cloudflare CASB and DLP are simple to use by default, making it easy to get started right away. But it’s also highly configurable, giving you the flexibility to fine-tune the scanning profiles to suit your specific needs.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5MLh3y7SMHnX52cjuu4pmE/b7bb67497fc21bc9d3f3f740a9b3fe52/4.png" />
          </figure><p>For example, you can adjust which storage buckets or file types to scan, and even sample only a percentage of objects for analysis​. The scanning also runs within your own cloud environment, so your data never leaves your infrastructure​. This approach keeps your cloud storage secure and your costs managed while allowing you to tailor the solution to your organization’s unique compliance and security requirements.</p><p>Looking ahead, our roadmap also includes expanding support to additional cloud storage environments, such as Azure Blob Storage and Cloudflare R2, further extending our comprehensive, multi-cloud security strategy. Stay tuned for more on that!</p>
    <div>
      <h3>How it works</h3>
      <a href="#how-it-works">
        
      </a>
    </div>
    <p>From the start, we knew that to deliver DLP capabilities across cloud environments, it would require an efficient and scalable design to enable real-time detection of sensitive data exposure.</p>
    <div>
      <h4>Serverless architecture for streamlined processing</h4>
      <a href="#serverless-architecture-for-streamlined-processing">
        
      </a>
    </div>
    <p>An early design decision was made to leverage a serverless architecture approach to ensure sensitive data discovery is both efficient and scalable. Here’s how it works:</p><ul><li><p><b>Compute Account</b>: The entire process runs within a cloud account owned by your organization, known as a Compute Account. This design ensures your data remains within your boundaries, avoiding costly cloud egress fees. The Compute Account can be launched in under 15 minutes using a provided Terraform template.</p></li><li><p><b>Controller function</b>: Every minute, a lightweight, serverless controller function in your cloud environment communicates with Cloudflare’s APIs, fetching the latest DLP configurations and security profiles from your Cloudflare One account.</p></li><li><p><b>Crawler process</b>: The controller triggers an object discovery task, which is processed by a second serverless function known as the Crawler. The Crawler queries cloud storage accounts, like AWS S3 or Google Cloud Storage, via API to identify new objects. Redis is used within the Compute Account to track which objects have yet to be evaluated.</p></li><li><p><b>Scanning for sensitive data</b>: Newly discovered objects are sent through a queue to a third serverless function called the Scanner. This function downloads the objects and streams their contents to the DLP engine in the Compute Account, which scans for matches against predefined or custom DLP Profiles.</p></li><li><p><b>Finding generation and alerts</b>: If a DLP match is found, metadata about the object, such as context and ownership details, is published to a queue. This data is ingested by a Cloudflare-hosted service and presented in the Cloudflare Dashboard as findings, giving security teams the visibility needed to take swift action.</p></li></ul>
    <div>
      <h4>Scalable and secure design</h4>
      <a href="#scalable-and-secure-design">
        
      </a>
    </div>
    <p>The DLP pipeline ensures that sensitive data never leaves your cloud environment — a privacy-first approach. All communication between the Compute Account and Cloudflare's APIs are initiated by the controller, also meaning there is no need to perform any extra configuration to allow ingress traffic.</p>
    <div>
      <h3>How to get started</h3>
      <a href="#how-to-get-started">
        
      </a>
    </div>
    <p>To get started, reach out to your account team to learn more about this new data security functionality and our roadmap. If you want to try this out on your own, you can login to the Cloudflare One dashboard (create a free account <a href="https://www.cloudflare.com/zero-trust/products/"><u>here</u></a> if you don’t have one) and navigate to the CASB page to set up your first integration.</p>
    <div>
      <h3>Watch on Cloudflare TV</h3>
      <a href="#watch-on-cloudflare-tv">
        
      </a>
    </div>
    <div>
  
</div><p></p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Cloudflare One]]></category>
            <category><![CDATA[CASB]]></category>
            <category><![CDATA[DLP]]></category>
            <category><![CDATA[AWS]]></category>
            <category><![CDATA[Google Cloud]]></category>
            <category><![CDATA[Zero Trust]]></category>
            <guid isPermaLink="false">2hlOlV28pXRFpnmnkqbbhw</guid>
            <dc:creator>Alex Dunbrack</dc:creator>
            <dc:creator>Michael Leslie </dc:creator>
        </item>
        <item>
            <title><![CDATA[RDP without the risk: Cloudflare's browser-based solution for secure third-party access]]></title>
            <link>https://blog.cloudflare.com/browser-based-rdp/</link>
            <pubDate>Fri, 21 Mar 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare now provides clientless, browser-based support for the Remote Desktop Protocol (RDP). It enables secure, remote Windows server access without VPNs or RDP clients. ]]></description>
            <content:encoded><![CDATA[ <p><a href="https://blog.cloudflare.com/intro-access-for-infrastructure-ssh/"><u>Short-lived SSH access</u></a> made its debut on Cloudflare’s <a href="https://www.cloudflare.com/learning/access-management/what-is-sase"><u>SASE</u></a> platform in October 2024. Leveraging the knowledge gained through the <a href="https://blog.cloudflare.com/cloudflare-acquires-bastionzero/"><u>BastionZero acquisition</u></a>, short-lived SSH access enables organizations to apply <a href="https://www.cloudflare.com/learning/security/glossary/what-is-zero-trust/">Zero Trust</a> controls in front of their Linux servers. That was just the beginning, however, as we are thrilled to announce the release of a long-requested feature: clientless, browser-based support for the <a href="https://www.cloudflare.com/learning/access-management/what-is-the-remote-desktop-protocol/"><u>Remote Desktop Protocol</u></a> (RDP). Built on top of Cloudflare’s modern proxy architecture, our RDP proxy offers a secure and performant solution that, critically, is also easy to set up, maintain, and use.</p>
    <div>
      <h3>Security challenges of RDP </h3>
      <a href="#security-challenges-of-rdp">
        
      </a>
    </div>
    <p><a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/use-cases/rdp/"><u>Remote Desktop Protocol (RDP)</u></a> was born in 1998 with <a href="https://news.microsoft.com/1998/06/16/microsoft-releases-windows-nt-server-4-0-terminal-server-edition/"><u>Windows NT 4.0 Terminal Server Edition</u></a>. If you have never heard of that Windows version, it’s because, well, there’s been 16 major Windows releases since then. Regardless, RDP is still used across thousands of organizations to enable remote access to Windows servers. It’s a bit of a strange protocol that relies on a graphical user interface to display screen captures taken in very close succession in order to emulate the interactions on the remote Windows server. (There’s more happening here beyond the screen captures, including drawing commands, bitmap updates, and even video streams. Like we said — it’s a bit strange.) Because of this complexity, RDP can be computationally demanding and poses a challenge for running at high performance over traditional <a href="https://www.cloudflare.com/learning/access-management/what-is-a-vpn/">VPNs</a>.</p><p>Beyond its quirks, RDP has also had a rather <a href="https://www.cloudflare.com/learning/access-management/rdp-security-risks/"><u>unsavory reputation</u></a> in the security industry due to early vulnerabilities with the protocol. The two main offenders are weak user sign-in credentials and unrestricted port access. Windows servers are commonly protected by passwords, which often have inadequate security to start, and worse still, may be shared across multiple accounts. This leaves these RDP servers open to brute force or credential stuffing attacks. </p><p>Bad actors have abused RDP’s default port, 3389, to carry out on-path attacks. One of the most severe RDP vulnerabilities discovered is called BlueKeep. Officially known as <a href="https://nvd.nist.gov/vuln/detail/CVE-2019-0708"><i>CVE-2019-0708</i></a>, BlueKeep is a vulnerability that allows <a href="https://www.cloudflare.com/learning/security/what-is-remote-code-execution/">remote code execution (RCE) </a>without authentication, as long as the request adheres to a specific format and is sent to a port running RDP. Worse still, it is wormable, meaning that BlueKeep can spread to other machines within the network with no user action. Because bad actors can compromise RDP to gain unauthorized access, attackers can then <a href="https://www.cloudflare.com/learning/security/glossary/what-is-lateral-movement/">move laterally</a> within the network, escalating privileges, and installing <a href="https://www.cloudflare.com/learning/ddos/glossary/malware/">malware</a>. RDP has also been used to deploy <a href="https://www.cloudflare.com/learning/security/ransomware/what-is-ransomware/">ransomware</a> such as Ryuk, Conti, and DoppelPaymer, earning it the nickname “Ransomware Delivery Protocol.” </p><p>This is a subset of vulnerabilities in RDP’s history, but we don’t mean to be discouraging. Thankfully, due to newer versions of Windows, CVE patches, improved password hygiene, and better awareness of privileged access, many organizations have reduced their <a href="https://www.cloudflare.com/learning/security/what-is-an-attack-surface/">attack surface</a>. However, for as many secured Windows servers that exist, there are still countless unpatched or poorly configured systems online, making them easy targets for ransomware and botnets. </p>
    <div>
      <h3>The need for a browser-based RDP solution</h3>
      <a href="#the-need-for-a-browser-based-rdp-solution">
        
      </a>
    </div>
    <p>Despite its <a href="https://www.cloudflare.com/learning/access-management/rdp-security-risks/">security risks</a>, RDP remains essential for many organizations, particularly those with distributed workforces and third-party contractors. It provides value for compute-intensive tasks that require high-powered Windows servers with CPU/GPU resources greater than users’ machines can offer. For security-focused organizations, RDP grants better visibility into who is accessing Windows servers and what actions are taken during those sessions. </p><p>Because issuing corporate devices to contractors is costly and cumbersome, many organizations adopt a bring-your-own-device (BYOD) policy. This decision instead requires organizations to provide contractors with a means to RDP to a Windows server with the necessary corporate resources to fulfill their role.</p><p>Traditional RDP requires client software on user devices, so this is not an appropriate solution for contractors (or any employees) using personal machines or unmanaged devices. Previously, Cloudflare customers had to rely on self-hosted third-party tools like <a href="https://guacamole.apache.org/"><u>Apache Guacamole</u></a> or <a href="https://devolutions.net/gateway/"><u>Devolutions Gateway</u></a> to enable browser-based RDP access. This created several operational pain points:</p><ul><li><p><b>Infrastructure complexity:</b> Deploying and maintaining RDP gateways increases operational overhead.</p></li><li><p><b>Maintenance burden:</b> Commercial and open-source tools may require frequent updates and patches, sometimes even necessitating custom forks.</p></li><li><p><b>Compliance challenges:</b> Third-party software requires additional security audits and risk management assessments, particularly for regulated industries.</p></li><li><p><b>Redundancy, but not the good kind</b> - Customers come to Cloudflare to reduce the complexity of maintaining their infrastructure, <i>not add to it</i>.</p></li></ul><p>We’ve been listening. Cloudflare has architectured a high-performance RDP proxy that leverages the modern security controls already part of our <a href="https://www.cloudflare.com/learning/access-management/what-is-ztna/"><u>Zero Trust Network Access (ZTNA)</u></a> service. We feel that the “security/performance tradeoff” the industry commonly touts is a dated mindset. With the right underlying network architecture, we can help mitigate RDP’s most infamous challenges.</p>
    <div>
      <h3>Introducing browser-based RDP with Access</h3>
      <a href="#introducing-browser-based-rdp-with-access">
        
      </a>
    </div>
    <p>Cloudflare's browser-based RDP solution is the newest addition to <a href="https://www.cloudflare.com/zero-trust/products/access/"><u>Cloudflare Access</u></a> alongside existing <a href="https://developers.cloudflare.com/cloudflare-one/applications/non-http/browser-rendering/"><u>clientless SSH and VNC offerings</u></a>, enabling secure, remote Windows server access without VPNs or RDP clients. Built natively within Cloudflare’s global network, it requires no additional infrastructure.</p><p>Our browser-based RDP access combines the power of self-hosted Access applications with the additional flexibility of <a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/use-cases/ssh/ssh-infrastructure-access/#4-add-a-target">targets</a>, introduced with <a href="https://developers.cloudflare.com/cloudflare-one/applications/non-http/infrastructure-apps/"><u>Access for Infrastructure</u></a>. Administrators can enforce:</p><ul><li><p><b>Authentication</b>: Control how users authenticate to your internal RDP resources with <a href="https://www.cloudflare.com/learning/access-management/what-is-sso/">SSO</a>, <a href="https://www.cloudflare.com/learning/access-management/what-is-multi-factor-authentication/">MFA</a>, and device posture.</p></li><li><p><b>Authorization:</b> Use <a href="https://www.cloudflare.com/learning/access-management/what-is-access-control/">policy-based access control </a>to determine who can access what target and when. </p></li><li><p><b>Auditing:</b> Provide Access logs to support regulatory compliance and visibility in the event of a security breach.</p></li></ul><p>Users only need a web browser — no native RDP client is necessary! RDP servers are accessed through our app connector, <a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/"><u>Cloudflare Tunnel</u></a>, using a common deployment model of existing Access customers. There is no need to provision user devices to access particular RDP servers, making for minimal setup to adopt this new functionality.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6vAxzxVY1RXc0batsTEdfn/23322d79ac68cfa0da698bdb2113db2c/unnamed__4_.png" />
          </figure>
    <div>
      <h4>How it works</h4>
      <a href="#how-it-works">
        
      </a>
    </div>
    
    <div>
      <h5>The client</h5>
      <a href="#the-client">
        
      </a>
    </div>
    <p>Cloudflare’s implementation leverages <a href="https://github.com/Devolutions/IronRDP"><u>IronRDP</u></a>, a high-performance RDP client that runs in the browser. It was selected because it is a modern, well-maintained, RDP client implementation that offers an efficient and responsive experience. Unlike Java-based Apache Guacamole, another popular RDP client implementation, IronRDP is built with Rust and integrates very well with Cloudflare’s development ecosystem.</p><p>While selecting the right tools can make all the difference, using a browser to facilitate an RDP session faces some challenges. From a practical perspective, browsers just can't send RDP messages. RDP relies directly on the Layer 4 Transmission Control Protocol (TCP) for communication, and while browsers can use TCP as the underlying protocol, they do not expose APIs that would let apps build protocol support directly on raw TCP sockets.</p><p>Another challenge is rooted in a security consideration: the username and password authentication mechanism that is native to RDP leaves a lot to be desired in the modern world of Zero Trust.</p><p>In order to tackle both of these challenges, the IronRDP client encapsulates the RDP session in a WebSocket connection. Wrapping the Layer 4 TCP traffic in HTTPS enables the client to use native browser APIs to communicate with Cloudflare’s RDP proxy. Additionally, it enables Cloudflare Access to secure the entire session using identity-aware policies. By attaching a Cloudflare Access authorization JSON Web Token (JWT) via cookie to the WebSocket connection, every inter-service hop of the RDP session is verified to be coming from the authenticated user.  </p><p>A brief aside into how security and performance is optimized: in conventional client-based RDP traffic, the client and server negotiate a <a href="https://www.cloudflare.com/learning/ssl/transport-layer-security-tls/">TLS</a> connection to secure and verify the session. However, because the browser WebSocket connection is already secured with TLS to Cloudflare, we employ IronRDP’s RDCleanPath protocol extension to eliminate this second encapsulation of traffic. Removing this redundancy avoids unnecessary performance degradation and increased complexity during session handshakes.</p>
    <div>
      <h5>The server</h5>
      <a href="#the-server">
        
      </a>
    </div>
    <p>The IronRDP client initiates a WebSocket connection to a dedicated WebSocket proxy, which is responsible for authenticating the client, terminating the WebSocket connection, and proxying tunneled RDP traffic deeper into Cloudflare’s infrastructure to facilitate connectivity. The seemingly simple task of determining how this WebSocket proxy should be built turned out to be the most challenging<b> </b>decision in the development process. </p><p>Our initial proposal was to develop a new service that would run on every server within our network. While this was feasible, operating a new service would introduce a non-trivial maintenance burden, which ultimately turned out to be more overhead than value-add in this case. The next proposal was to build it into <a href="https://blog.cloudflare.com/upgrading-one-of-the-oldest-components-in-cloudflare-software-stack/"><u>Front Line</u></a> (FL), one of Cloudflare’s oldest services that is responsible for handling tens of millions of HTTP requests per second. This approach would have sidestepped the need to expose new IP addresses and benefitted from the existing scaffolding to let the team move quickly. Despite being promising at first, this approach was decided against because FL is undergoing significant investment, and the team didn't want to build on shifting sands.</p><p>Finally, we identified a solution that implements the proxy service using <a href="https://workers.cloudflare.com/"><u>Cloudflare Workers</u></a>! Fortunately, Workers automatically scales to massive request rates, which eliminates some of the groundwork we’d lay if we had chosen to build a new service. Candidly, this approach was not initially preferred due to some ambiguities around how Workers communicates with internal Cloudflare services, but with support from the Workers team, we found a path forward. </p><p>From the WebSocket proxy Worker, the tunneled RDP connection is sent to the Apollo service, which is responsible for routing traffic between on-ramps and off-ramps for <a href="https://www.cloudflare.com/zero-trust/">Cloudflare Zero Trust</a>. Apollo centralizes and abstracts these complexities to let other services focus on application-specific functionality. Apollo determines which Cloudflare colo is closest to the target Cloudflare Tunnel and establishes a connection to an identical Apollo instance running in that colo. The egressing Apollo instance can then facilitate the final connection to the Cloudflare Tunnel. By using Cloudflare's global network to traverse the distance between the ingress colo and the target Cloudflare Tunnel, network disruptions and congestion is managed.</p><p>Apollo connects to the RDP server and passes the ingress and egress connections to <a href="https://blog.cloudflare.com/from-ip-packets-to-http-the-many-faces-of-our-oxy-framework/"><u>Oxy</u></a>-teams, the service responsible for inspecting and proxying the RDP traffic. It functions as a pass-through (strictly enabling traffic connectivity) as the web client authenticates to the RDP server. Our initial release makes use of <a href="https://learn.microsoft.com/en-us/windows-server/security/kerberos/ntlm-overview"><u>NT Lan Manager (NTLM)</u></a> authentication, a challenge-response authentication protocol requiring username and password entry. Once the client has authenticated with the server, Oxy-teams is able to proxy all subsequent RDP traffic!</p><p>This may sound like a lot of hops, but every server in our network runs every service. So believe it or not, this complex dance takes place on a single server and by using UNIX domain sockets for communication, we also minimize any performance impact. If any of these servers become overloaded, experience a network fault, or have a hardware problem, the load is automatically shifted to a neighboring server with the help of <a href="https://blog.cloudflare.com/unimog-cloudflares-edge-load-balancer/"><u>Unimog</u></a>, Cloudflare’s L4 load balancer.</p>
    <div>
      <h4>Putting it all together</h4>
      <a href="#putting-it-all-together">
        
      </a>
    </div>
    <ol><li><p><b>User initiation:</b> The user selects an RDP server from Cloudflare’s <a href="https://developers.cloudflare.com/cloudflare-one/applications/app-launcher/"><u>App Launcher</u></a> (or accesses it via a direct URL). Each RDP server is associated with a public hostname secured by Cloudflare. </p></li><li><p><b>Ingress:</b> This request is received by the closest data center within <a href="https://www.cloudflare.com/network/"><u>Cloudflare’s network</u></a>. </p></li><li><p><b>Authentication:</b> Cloudflare Access authenticates the session by validating that the request contains a valid JWT. This token certifies that the user is authorized to access the selected RDP server through the specified domain.</p></li><li><p><b>Web client delivery:</b> <a href="https://developers.cloudflare.com/workers/"><u>Cloudflare Workers</u></a> serves the IronRDP web client to the user’s browser.</p></li><li><p><b>Secure tunneling:</b> The client tunnels RDP traffic from the user’s browser over a TLS-secured WebSocket to another Cloudflare Worker. </p></li><li><p><b>Traffic routing:</b> The Worker that receives the IronRDP connection terminates the WebSocket and initiates a connection to <a href="https://blog.cloudflare.com/extending-local-traffic-management-load-balancing-to-layer-4-with-spectrum/#how-we-enabled-spectrum-to-support-private-networks"><u>Apollo</u></a>. From there, Apollo creates a connection to the RDP server.</p></li><li><p><b>Authentication relay:</b> With a connection established, Apollo relays RDP authentication messages between the web client and the RDP server. </p></li><li><p><b>Connection establishment:</b> Upon successful authentication, Cloudflare serves as an RDP proxy between the web browser and the RDP server, connecting the user to the RDP server with free-flowing traffic. </p></li><li><p><b>Policy enforcement:</b> Cloudflare's secure web gateway, <a href="https://blog.cloudflare.com/from-ip-packets-to-http-the-many-faces-of-our-oxy-framework/"><u>Oxy</u></a>-teams, applies Layer 4 policy enforcement and logging of the RDP traffic. </p></li></ol>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2wWryOYY69cHw5cDmQHAqi/cb40a492b1e194cd572018eb4a5792ba/3.png" />
          </figure><p>Key benefits of this architecture:</p><ul><li><p><b>No additional software:</b> Access Windows servers directly from a browser.</p></li><li><p><b>Low latency:</b> Cloudflare’s global network minimizes performance overhead.</p></li><li><p><b>Enhanced security:</b> RDP access is protected by Access policies, preventing lateral movement.</p></li><li><p><b>Integrated logging and monitoring:</b> Administrators can observe and control RDP traffic.</p></li></ul><p>To learn more about Cloudflare's proxy capabilities, take a look at our <a href="https://blog.cloudflare.com/introducing-oxy/"><u>related blog post</u></a> explaining our proxy framework.</p>
    <div>
      <h3>Selective, modern RDP authentication</h3>
      <a href="#selective-modern-rdp-authentication">
        
      </a>
    </div>
    <p>Cloudflare’s browser-based RDP solution exclusively supports modern RDP authentication mechanisms, enforcing best practices for secure access. Our architecture ensures that RDP traffic using outdated or weak legacy security features from older versions of the RDP standard, such as unsecured password-based authentication or RC4 encryption, are never allowed to reach customer endpoints.</p><p>Cloudflare supports secure session negotiation using the following principles:</p><ol><li><p>TLS-based WebSocket connection for transport security.</p></li><li><p>Fine-grained policies that enforce single sign on (SSO), multi-factor authentication (MFA), and dynamic authorization.</p></li><li><p>Integration with enterprise identity providers via SAML (Security Assertion Markup Language) and OIDC (OpenID Connect).</p></li></ol><p>Every RDP session that passes through Cloudflare’s network is encrypted and authenticated.</p>
    <div>
      <h4>What’s next? </h4>
      <a href="#whats-next">
        
      </a>
    </div>
    <p>This is only the beginning for our browser-based RDP solution! We have already identified a few areas for continued focus:</p><ul><li><p><b>Enhanced visibility and control for administrators:</b> Because RDP traffic passes through Cloudflare Workers and proxy services, browser-based RDP will expand to include session monitoring. We are also evaluating <a href="https://www.cloudflare.com/learning/access-management/what-is-dlp/">data loss prevention (DLP) </a>support, such as restricting actions like file transfers and clipboard use, to prevent unauthorized <a href="https://www.cloudflare.com/learning/security/what-is-data-exfiltration/">data exfiltration</a> without compromising performance. </p></li><li><p><b>Advanced authentication:</b> Long-lived credentials are a thing of the past. Future iterations of browser-based RDP will include <a href="https://www.cloudflare.com/learning/security/threats/what-is-passwordless-authentication/">passwordless</a> functionality, eliminating the need for end users to remember passwords and administrators from having to manage them. To that end, we are evaluating methods such as client certificate authentication, passkeys and smart cards, and integration with third-party authentication providers via Access.</p></li></ul>
    <div>
      <h5>Compliance and FedRAMP High certification</h5>
      <a href="#compliance-and-fedramp-high-certification">
        
      </a>
    </div>
    <p>We plan to include browser-based RDP in our <a href="https://www.cloudflare.com/learning/privacy/what-is-fedramp/">FedRAMP</a> High offering for enterprise and government organizations, a high-priority initiative <a href="https://blog.cloudflare.com/cloudflares-commitment-to-advancing-public-sector-security-worldwide/"><u>we announced in early February</u></a>. This certification will validate that our solution meets the highest standards for:</p><ul><li><p><b>Data protection</b></p></li><li><p><b>Identity and access management</b></p></li><li><p><b>Continuous monitoring</b></p></li><li><p><b>Incident response</b></p></li></ul><p>Seeking FedRAMP High compliance demonstrates Cloudflare’s commitment to securing sensitive environments, such as those in the <a href="https://www.cloudflare.com/public-sector/">federal government</a>, <a href="https://www.cloudflare.com/healthcare/">healthcare</a>, and <a href="https://www.cloudflare.com/banking-and-financial-services/">financial</a> sectors.</p><p>By enforcing a modern, opinionated, and secure implementation of RDP, Cloudflare provides a secure, scalable, and compliant solution tailored to the needs of organizations with critical security and compliance mandates.</p>
    <div>
      <h3>Get started today</h3>
      <a href="#get-started-today">
        
      </a>
    </div>
    <p>At Cloudflare, we are committed to providing the most comprehensive solution for ZTNA, which now also includes privileged access to sensitive infrastructure like Windows servers over browser-based RDP. Cloudflare’s browser-based RDP solution is in closed beta with new customers being onboarded each week. You can <a href="http://www.cloudflare.com/lp/browser-based-rdp-beta"><u>request access here</u></a> to try out this exciting new feature.</p><p>In the meantime, check out our<a href="https://developers.cloudflare.com/cloudflare-one/applications/non-http/infrastructure-apps/"> <u>Access for Infrastructure</u></a> documentation to learn more about how Cloudflare protects privileged access to sensitive infrastructure. Access for Infrastructure is currently <a href="https://dash.cloudflare.com/sign-up/teams"><u>available free</u></a> to teams of under 50 users, and at no extra cost to existing pay-as-you-go and Contract plan customers through an Access or Zero Trust subscription. Stay tuned as we continue to natively rebuild BastionZero’s technology into Cloudflare’s Access for Infrastructure service!</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Zero Trust]]></category>
            <category><![CDATA[Cloudflare Zero Trust]]></category>
            <category><![CDATA[Acquisitions]]></category>
            <category><![CDATA[Cloudflare Access]]></category>
            <category><![CDATA[Cloudflare One]]></category>
            <category><![CDATA[Clientless]]></category>
            <category><![CDATA[Remote Work]]></category>
            <category><![CDATA[VDI]]></category>
            <category><![CDATA[Remote Desktop Protocol ]]></category>
            <guid isPermaLink="false">2P5rqqGRcQQFywmNmp85oM</guid>
            <dc:creator>Ann Ming Samborski</dc:creator>
            <dc:creator>Gabriel Bauman</dc:creator>
            <dc:creator>Athanasios Filippidis</dc:creator>
            <dc:creator>Mike Borkenstein</dc:creator>
        </item>
        <item>
            <title><![CDATA[Enhance data protection in Microsoft Outlook with Cloudflare One’s new DLP Assist]]></title>
            <link>https://blog.cloudflare.com/enhance-data-protection-in-microsoft-outlook-with-cloudflare-ones-new-dlp/</link>
            <pubDate>Fri, 21 Mar 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ Customers can now easily safeguard sensitive data in Microsoft Outlook with our new DLP Assist feature. ]]></description>
            <content:encoded><![CDATA[ <p><a href="https://developers.cloudflare.com/cloudflare-one/email-security/"><u>Cloudflare Email Security</u></a> customers using Microsoft Outlook can now enhance their data protection using our new <a href="https://developers.cloudflare.com/cloudflare-one/email-security/outbound-dlp/"><u>DLP Assist</u></a> capability. This application scans emails in real time as users compose them, identifying potential <a href="https://www.cloudflare.com/learning/access-management/what-is-dlp/"><u>data loss prevention (DLP)</u></a> violations, such as Social Security or credit card numbers. Administrators can instantly alert users of violations and take action downstream, whether by blocking or encrypting messages, to prevent sensitive information from leaking. DLP Assist is lightweight, easy to deploy, and helps organizations maintain compliance without disrupting workflow.</p>
    <div>
      <h3>Making DLP more accessible</h3>
      <a href="#making-dlp-more-accessible">
        
      </a>
    </div>
    <p>After speaking with our customers, we discovered a common challenge: many wanted to implement a data loss prevention policy for Outlook, but found existing solutions either too complex to set up or too costly to adopt.</p><p>That’s why we created DLP Assist to be a lightweight application that can be installed in minutes. Unlike other solutions, it doesn’t require changes to outbound email connectors or provide concerns about IP reputation to customers. By fully leveraging the Microsoft ecosystem, DLP Assist makes email DLP accessible to all organizations, whether they have dedicated IT teams or none at all.</p><p>We also recognized that traditional DLP solutions often demand significant financial investment in not just software but also in team members to configure and monitor them. DLP Assist aims to eliminate these barriers. Customers can use the application as part of our Email Security product, avoiding the need for additional purchases. Plus, with our DLP engine powered by optical character recognition (OCR), confidence levels, and other detection mechanisms, organizations don’t need a dedicated team to constantly oversee it. </p><p>By eliminating the complexities of legacy DLP and email systems, we allow customers to quickly begin preventing the unauthorized egress of sensitive data. With DLP Assist, organizations can be confident in controlling and protecting the information that leaves their environment.</p>
    <div>
      <h3>How does it work?</h3>
      <a href="#how-does-it-work">
        
      </a>
    </div>
    <p>Our DLP Assist is an application that integrates with the Desktop (Mac and Windows) and Web Outlook clients, passively scanning emails as they are composed. Running in the background within Microsoft Outlook, DLP Assist continuously monitors new text and attachments added to emails that users are drafting. </p><p>When a customer downloads and installs the application, Cloudflare creates a unique client ID specifically for emails read from the DLP Assist application, which serves as an identifier solely for use by DLP Assist within Cloudflare’s backend. When a user begins drafting a message, the DLP Assist application invokes several Microsoft Outlook APIs to gather information about how the message is changing. These APIs let the Cloudflare application continuously access different parts of the message like subject, body, attachments, etc. While the application is reading the changes within the message, it also establishes a secure, encrypted connection with a Cloudflare Worker. </p><p>As raw data about the email and attachments is sent to the Worker, the Worker relays the information to our DLP engine, which is at the heart of our scanning process. It leverages OCR technology to analyze attachments, extract text from images, and detect DLP violations across both email content and embedded data. It also examines raw text to ensure a comprehensive analysis of every part of the email and its attachments. While our engine supports most attachment types, it currently does not process video or audio files.</p><p>The DLP engine runs on all of our servers, and we also store the customer DLP profile configuration data on all of our servers. By keeping DLP policy configuration data on all servers alongside our analysis engine, we eliminate the need to reroute requests across our network allowing for low-latency, real-time DLP checks. The customer's client ID enables us to find and apply their defined DLP profiles and accurately determine policy violations, delivering results directly to the Cloudflare Worker. If a violation is found, the Worker responds to the application to take action within Outlook. </p><p>Our architecture ensures real-time scanning with minimal latency, as end users are always near a Cloudflare Worker, regardless of their location. Additionally, this design provides built-in resilience — if a Cloudflare Worker becomes unavailable, another can take over, allowing for uninterrupted DLP enforcement. By scanning in real time, this allows us to provide immediate feedback to the user about any DLP violations that they have within their email, rather than the user having to wait till the message has been sent. </p><p>If a violation is detected, the application first displays an insight message — a ribbon notification at the top of the email — alerting the user to the issue. Administrators have full control over this message and can customize it to provide specific guidance or warnings. We find that most of our customers point users to documentation reminding them what is allowed to be sent outside of the organization. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4X9uiCNNus3Y9t1hNNK1vi/d6782435b13f06719f7d75cb306b2231/image3.png" />
          </figure><p>When a DLP violation occurs, DLP Assist also injects a header into the <a href="https://www.adobe.com/acrobat/resources/document-files/eml.html"><u>EML file</u></a> to indicate the violation. If the user removes the content that is in violation, the header is automatically removed as well.</p><p>If the violation remains unchanged, DLP Assist invokes a Microsoft Outlook API which prompts the user with a final warning, giving them another opportunity to revise the message before sending.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2If0U9oDTYW5j5mbm4Gt5r/e7297064f8f1e7e820c962c1bfd7e673/image6.png" />
          </figure><p>If the user proceeds without making changes, the email will be sent from the client with headers embedded into the EML showing that message contains a DLP violation. Organizations can configure their outbound <a href="https://www.cloudflare.com/learning/email-security/what-is-a-mail-server/"><u>mail transfer agent (MTA)</u></a> to take appropriate action based on these headers. For those with Microsoft as their outbound MTA, Cloudflare’s DLP Assist integrates with <a href="https://learn.microsoft.com/en-us/purview/purview"><u>Microsoft Purview</u></a>, enabling organizations to block, encrypt, or require approval before sending.</p><p>For example, if an organization configures Purview to block the email, users will receive a notification similar to this one.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1FIuUhcuMC0kQPivQRIA5V/459a4acbaaa04bc007dc3829c4ed8d14/image5.png" />
          </figure><p>Violations detected by the DLP Assist application can also be sent externally through our <a href="https://developers.cloudflare.com/logs/about/"><u>Logpush</u></a> feature. Customers have the flexibility to integrate this data with SIEM or SOAR platforms for deeper analysis, or store it in bucket storage solutions like Cloudflare <a href="https://developers.cloudflare.com/r2/"><u>R2</u></a>. Additionally, customers can enhance their reporting capabilities by viewing block data directly within their outbound gateway.</p><p>As we continue to improve our DLP engine, we're introducing more advanced ways to analyze messages. During Security Week 2025, we’re unveiling new AI methodologies that automatically fine-tune DLP confidence levels using machine learning models. Initially, these enhancements will be rolled out for Gateway violations, but we plan to extend them to email scanning in the near future. For more details, see the associated <a href="https://blog.cloudflare.com/improving-data-loss-prevention-accuracy-with-ai-context-analysis/"><u>blog post</u></a>. </p><p>Cloudflare One’s DLP Assist is designed for quick deployment, enabling organizations to implement a data loss prevention solution with minimal effort. It allows customers to immediately begin scanning emails for sensitive data and take action to prevent unauthorized sharing, ensuring compliance and security from day one.</p>
    <div>
      <h3>How can I start using it?</h3>
      <a href="#how-can-i-start-using-it">
        
      </a>
    </div>
    <p>To get started, navigate to the Zero Trust dashboard and click on the Email Security tab. From there, select the Outbound DLP tab.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1FMrBrIsDS15sdUU9HUW56/1b25031717fde5411c286e27f2836f6a/image2.png" />
          </figure><p>To install DLP Assist, organizations can download the manifest file, which provides Microsoft with the necessary instructions to install the application within Outlook. Administrators can then upload this manifest file by going to Integrated Apps within the Microsoft 365 Admin Center and selecting Upload Custom Apps:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3twUf3WW6eb7GsNdxNG6w6/f5244c2c9d801bd78a33537abd5fd9c4/image4.png" />
          </figure><p><i><sup>This application is best suited for use with OWA (Outlook Web Access) and the desktop (Mac and Windows) Outlook client. Due to Microsoft limitations, a stable experience on mobile devices is not yet available.</sup></i></p><p>More information can be found within our <a href="https://developers.cloudflare.com/cloudflare-one/email-security/outbound-dlp/"><u>developer documentation</u></a>. </p>
    <div>
      <h3>What's next?</h3>
      <a href="#whats-next">
        
      </a>
    </div>
    <p>We’re continuously expanding our solutions to help organizations protect their data. Exciting new DLP and Email Security features are on the way throughout 2025, so stay tuned for upcoming announcements.</p><p>To learn more about our DLP and Email Security solutions, reach out to your Cloudflare representative. Want to see our detections in action? Run a free <a href="https://blog.cloudflare.com/threats-lurking-office-365-cloudflare-email-retro-scan/"><u>Retro Scan</u></a> to uncover any potentially malicious messages hiding in your inbox.</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Email Security]]></category>
            <category><![CDATA[Data Loss]]></category>
            <category><![CDATA[Data Loss Prevention]]></category>
            <guid isPermaLink="false">tNeYTGhykKxYbzGItvS5M</guid>
            <dc:creator>Ayush Kumar</dc:creator>
            <dc:creator>Noelle Kagan</dc:creator>
            <dc:creator>Warnessa Weaver</dc:creator>
        </item>
        <item>
            <title><![CDATA[Prepping for post-quantum: a beginner’s guide to lattice cryptography]]></title>
            <link>https://blog.cloudflare.com/lattice-crypto-primer/</link>
            <pubDate>Fri, 21 Mar 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ This post is a beginner's guide to lattices, the math at the heart of the transition to post-quantum (PQ) cryptography. It explains how to do lattice-based encryption and authentication from scratch. ]]></description>
            <content:encoded><![CDATA[ <p>The cryptography that secures the Internet is evolving, and it's time to catch up. This post is a tutorial on lattice cryptography, the paradigm at the heart of the post-quantum (PQ) transition.</p><p>Twelve years ago (in 2013), the <a href="https://en.wikipedia.org/wiki/Edward_Snowden"><u>revelation of mass surveillance in the US</u></a> kicked off the widespread adoption of <a href="https://www.cloudflare.com/learning/ssl/transport-layer-security-tls/"><u>TLS</u></a> for encryption and authentication on the web. This transition was buoyed by the standardization and implementation of new, more efficient public-key cryptography based on <a href="https://blog.cloudflare.com/a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography/"><u>elliptic curves</u></a>. Elliptic curve cryptography was both faster and required less communication than its predecessors, including <a href="https://en.wikipedia.org/wiki/RSA_(cryptosystem)"><u>RSA</u></a> and <a href="https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange"><u>Diffie-Hellman</u></a> over finite fields.</p><p>Today's transition to <a href="https://www.cloudflare.com/learning/ssl/quantum/what-is-post-quantum-cryptography/"><u>PQ cryptography</u></a> addresses a looming threat for TLS and beyond: once built, a sufficiently large quantum computer can be used to break all <a href="https://www.cloudflare.com/learning/ssl/how-does-public-key-encryption-work/">public-key cryptography</a> in use today. And we continue to see <a href="https://blog.google/technology/research/google-willow-quantum-chip/"><u>advancements</u></a> in quantum-computer engineering that bring us closer to this threat becoming a reality.</p><p>Fortunately, this transition is well underway. The research and standards communities have spent the last several years developing alternatives that resist quantum cryptanalysis. For its part, Cloudflare has contributed to this process and is an early adopter of newly developed schemes. In fact, PQ encryption has been available at our edge <a href="https://blog.cloudflare.com/post-quantum-for-all/"><u>since 2022</u></a> and is <a href="https://radar.cloudflare.com/adoption-and-usage#post-quantum-encryption-adoption"><u>used in over 35% of non-automated HTTPS traffic today (2025)</u></a>. And this year we're beginning a major push towards PQ authentication for the TLS ecosystem.</p><p>Lattice-based cryptography is the first paradigm that will replace <a href="https://blog.cloudflare.com/a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography/"><u>elliptic curves</u></a>. Apart from being PQ secure, lattices are often as fast, and sometimes faster, in terms of CPU time. However, this new paradigm for public key crypto has one major cost: <b>lattices require much more communication than elliptic curves.</b> For example, establishing an encryption key using lattices requires 2272 bytes of communication between the client and the server (<a href="https://csrc.nist.gov/pubs/fips/203/final"><u>ML-KEM-768</u></a>), compared to just 64 bytes for a key exchange using a modern elliptic-curve-based scheme (<a href="https://datatracker.ietf.org/doc/html/rfc7748"><u>X25519</u></a>). Accommodating such costs requires a significant amount of engineering, from dealing with <a href="https://blog.cloudflare.com/sizing-up-post-quantum-signatures/"><u>TCP packet fragmentation</u></a>, to reworking <a href="https://blog.cloudflare.com/pq-2024/#two-migrations"><u>TLS and its public key infrastructure</u></a>. Thus, the PQ transition is going to require the participation of a large number of people with a variety of backgrounds, not just cryptographers.</p><p>The primary audience for this blog post is those who find themselves involved in the PQ transition and want to better understand what's going on under the hood. However, more fundamentally, we think it's important for everyone to understand lattice cryptography on some level, especially if we're going to trust it for our security and privacy.</p><p>We'll assume you have a software-engineering background and some familiarity with concepts like TLS, encryption, and authentication. We'll see that the math behind lattice cryptography is, at least at the highest level, not difficult to grasp. Readers with a crypto-engineering background who want to go deeper might want to start with the excellent <a href="https://eprint.iacr.org/2024/1287"><u>tutorial by Vadim Lyubashevsky</u></a> on which this blog post is based. We also recommend <a href="https://keymaterial.net/2023/09/01/learning-but-with-errors/"><u>Sophie Schmieg's blog</u></a> on this subject.</p><p>While the transition to lattice cryptography incurs costs, it also creates opportunities. Many things we can build with elliptic curves we can also build with lattices, though not always as efficiently; but there are also things we can do with lattices that we don't know how to do efficiently with anything else. We'll touch on some of these applications at the very end.</p><p>We're going to cover a lot of ground in this post. If you stick with it, we hope you'll come away feeling empowered, not only to tackle the engineering challenges the PQ transition entails, but to solve problems you didn't know how to solve before.</p><p>Strap in — let's have some fun!</p>
    <div>
      <h3>Encryption</h3>
      <a href="#encryption">
        
      </a>
    </div>
    <p>The most pressing problem for the PQ transition is to ensure that tomorrow's quantum computers don't break today's encryption. An attacker today can store the packets exchanged between your laptop and a website you visit, and then, some time in the future, decrypt those packets with the help of a quantum computer. This means that much of the sensitive information transiting the Internet today — everything from <a href="https://blog.cloudflare.com/https-only-for-cloudflare-apis-shutting-the-door-on-cleartext-traffic/"><u>API tokens</u></a> and passwords to database encryption keys — may one day be unlocked by a quantum computer.</p><p>In fact, today's encryption in TLS is <i>mostly</i> PQ secure: <b>what's at risk is the process by which your browser and a server establish an encryption key</b>. Today this is usually done with elliptic-curve-based schemes, which are not PQ secure; our goal for this section is to understand how to do key exchange with lattices-based schemes, which are.</p><p>We will work through and implement a simplified version of <a href="https://csrc.nist.gov/pubs/fips/203/final"><u>ML-KEM</u></a>, a.k.a. Kyber, the most widely deployed PQ key exchange in use today. Our code will be less efficient and secure than a <a href="https://pkg.go.dev/github.com/cloudflare/circl@v1.6.0/kem/mlkem"><u>spec-compliant, production-quality implementation</u></a>, but will be good enough to grasp the main ideas.</p><p>Our starting point is a protocol that looks an awful lot like <a href="https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange"><u>Diffie-Hellman (DH)</u></a> key exchange. For those readers unacquainted with DH, the goal is for Alice and Bob to establish a shared secret over an insecure network. To do so, each picks a random secret number, computes the corresponding "key share", and sends the key share to the other:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5yWJO1Sem97PfhwqiKZRLm/bfacc44ca4f7187f4212b7b4616dd86d/image7.png" />
          </figure><p>Alice's secret number is $s$ and her key share is $g^s$; Bob's secret number is $r$ and his key share is $g^r$. Then given their secret and their peer's key share, each can compute $g^{rs}$. The security of this protocol comes from how we choose $g$, $s$, and $r$ and how we do arithmetic. The most efficient instantiation of DH uses elliptic curves.</p><p>In ML-KEM we replace operations on elliptic curves with <b>matrix </b>operations. It's not quite a drop-in replacement, so we'll need a little linear algebra to make sense of it. But don't worry: we're going to work with Python so we have running code to play with, and we'll use <a href="https://numpy.org/"><u>NumPy</u></a> to keep things high level.</p>
    <div>
      <h4>All the math we'll need</h4>
      <a href="#all-the-math-well-need">
        
      </a>
    </div>
    <p>A matrix is just a two-dimensional array of numbers. In NumPy, we can create a matrix as follows (importing <code>numpy</code> as <code>np</code>):</p>
            <pre><code>A = np.matrix([[1, 2, 3],
               [4, 5, 6],
               [7, 8, 9]])</code></pre>
            <p>This defines <code>A</code> to be the <code>3</code>-by-<code>3</code> matrix with entries <code>A[0,0]==1, A[0,1]==2, A[0,2]==3, A[1,0]==4</code>, and so on.</p><p>For the purposes of this post, the entries of our matrices will always be integers. Furthermore, whenever we add, subtract, or multiply two integers, we then <b>reduce</b> the result, just like we do with hours on a clock, so that we end up with a number in <code>range(Q)</code> for some positive number <code>Q</code>, called the modulus. The exact value doesn’t really matter now, but for ML-KEM it’s <code>Q=3329</code>, so let's go with that for now. (The modulus for a clock would be <code>Q=12</code>.)</p><p>In Python, we write multiplication of integers <code>a</code> and <code>b</code> modulo <code>Q</code> as<code> c = a*b % Q</code>. Here we compute <code>a*b</code>, divide the result by <code>Q</code>, then set <code>c</code> to the remainder. For example, <code>42*1337</code> <code>% Q</code> is equal to <code>2890</code> rather than <code>56154</code>. Modular addition and subtraction are done analogously. For the rest of this blog, we will sometimes omit "<code>% Q</code>" when it's clear in context that we mean modular arithmetic.</p><p>Next, we'll need three operations on matrices.</p><p>The first is <b>matrix transpose</b>, written <code>A.T </code>in NumPy. This operation flips the matrix along its diagonal so that <code>A.T[j,i] == A[i,j]</code> for all rows <code>i</code> and columns <code>j</code>:</p>
            <pre><code>print(A.T)
# [[1 4 7]
#  [2 5 8]
#  [3 6 9]]</code></pre>
            <p>To visualize this, imagine writing down a matrix on a translucent piece of paper. Draw a line from the top left corner to the bottom right corner of that paper, then rotate the paper 180° around that line:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2x3qNDptBldEKCgQBbmNPr/ad174561910e6c90753024625f16fd68/image3.png" />
          </figure><p>The second operation we'll need is <b>matrix multiplication</b>. Normally, we will multiply a matrix by a <b>column vector</b>, which is just a matrix with one column. For example, the following <code>3</code>-by-<code>1</code> matrix is a column vector:</p>
            <pre><code>s = np.matrix([[0],
               [1],
               [0]])</code></pre>
            <p>We can also write <code>s </code>more concisely as <code>np.matrix([[0,1,0]]).T</code>.  To multiply a square matrix <code>A</code> by a column vector <code>s</code>, we compute the <b>dot product</b> of each row of <code>A</code> with <code>s</code>. That is, if <code>t = A*s % Q</code>, then <code>t[i] == (A[i,0]*s[0,0] + A[i,1]*s[1,0] + A[i,2]*s[2,0]) % Q </code>for each row <code>i</code>. The output will always be a column vector:</p>
            <pre><code>print(A*s % Q)
# [[2]
#  [5]
#  [8]]</code></pre>
            <p>The number of rows of this column vector is equal to the number of rows of the matrix on the left hand side. In particular, if we take our column vector <code>s</code>, transpose it into a <code>1</code>-by-<code>3</code> matrix, and multiply it by a <code>3</code>-by-<code>1</code> matrix <code>r</code>, then we end up with a <code>1</code>-by-<code>1 </code>matrix:</p>
            <pre><code>r = np.matrix([[1,2,3]]).T
print(s.T*r % Q)
# [[2]]</code></pre>
            <p>The final matrix operation we'll need is <b>matrix addition</b>. If <code>A</code> and <code>B</code> are both <code>N</code>-by-<code>M</code> matrices, then <code>C = (A+B) % Q</code> is the <code>N</code>-by-<code>M</code> matrix for which <code>C[i,j] == (A[i,j]+B[i,j]) % Q</code>. Of course, this only works if the matrices we're adding have the same dimensions.</p>
    <div>
      <h4>Warm up</h4>
      <a href="#warm-up">
        
      </a>
    </div>
    <p>Enough maths — let's get to exchanging some keys. We start with the DH diagram from before and swap out the computations with matrix operations. Note that this protocol is not secure, but will be the basis of a secure key exchange mechanism we'll develop in the next section:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3qRFXuCjStyX8IdRgHogJi/0ea04a675e6b8b52fc74a2375827890c/image6.png" />
          </figure><ul><li><p>Alice and Bob agree on a public, <code>N</code>-by-<code>N</code> matrix <code>A</code>. This is analogous to the number $g$ that Alice and Bob agree on in the DH diagram.</p></li><li><p>Alice chooses a random length<code>-N</code> vector <code>s</code> and sends <code>t = A*s % Q</code> to Bob.</p></li><li><p>Bob chooses a random length<code>-N</code>  vector <code>r</code> and sends <code>u = r.T*A % Q</code> to Alice. You can also compute this as <code>(A.T*r).T % Q.</code></p></li></ul><p>The vectors <code>t</code> and <code>u</code> are analogous to DH key shares. After the exchange of these key shares, Alice and Bob can compute a shared secret. Alice computes the shared secret as <code>u*s % Q</code> and Bob computes the shared secret as <code>r.T*t % Q</code>. To see why they compute the same key, notice that <code>u*s == (r.T*A)*s == r.T*(A*s) == r.T*t.</code></p><p>In fact, this key exchange is essentially what happens in ML-KEM. However, we don't use this directly, but rather as part of a <b>public key encryption scheme</b>. Public key encryption involves three algorithms:</p><ul><li><p><code>key_gen():</code> The key generation algorithm that outputs a public encryption key <code>pk</code> and the corresponding secret decryption key <code>sk</code>.</p></li><li><p><code>encrypt()</code>: The encryption algorithm that takes the public key and a plaintext and outputs a ciphertext.</p></li><li><p><code>decrypt()</code>: The decryption algorithm that takes the secret key and a ciphertext and outputs the underlying plaintext. That is, <code>decrypt(sk, encrypt(pk, ptxt)) == ptxt</code> for any plaintext <code>ptxt</code>.</p></li></ul><p>We'll say the scheme is secure if, given a ciphertext and the public key used to encrypt it, no attacker can discern any information about the underlying plaintext without knowledge of the secret key. Once we have this encryption scheme, we then transform it into a <b>key-encapsulation mechanism</b> (the "KEM" in "ML-KEM") in the last step. A KEM is very similar to encryption except that the plaintext is always a randomly generated key.</p><p>Our encryption scheme is as follows:</p><ul><li><p><code>key_gen()</code>: To generate a key pair, we choose a random, square matrix <code>A</code> and a random column vector <code>s</code>. We set our public key to <code>(A,t=A*s % Q)</code> and our secret key to <code>s</code>. Notice that <code>t </code>is Alice's  key share from the key exchange protocol above.</p></li><li><p><code>encrypt()</code>: Suppose our plaintext <code>ptxt </code>is an integer in <code>range(Q)</code>. To encrypt <code>ptxt</code>, Bob generates his key share <code>u</code>. He then derives the shared secret and adds it to <code>ptxt</code>. The ciphertext has two components:</p></li></ul><blockquote><p><code>u = r.T*A % Q</code></p><p><code>v = (r.T*t + m) % Q</code></p></blockquote><p>Here <code>m </code>is a <code>1</code>-by-<code>1 </code>matrix containing the plaintext, i.e., <code>m = np.matrix([[ptxt]])</code>, and <code>r</code> is a random column vector.</p><ul><li><p><code>decrypt()</code>: To decrypt, Alice computes the shared secret and subtracts it from <code>v</code>:</p></li></ul><blockquote><p><code>m = (v - u*s) % Q</code></p></blockquote><p>Some readers will notice that this looks an awful lot like <a href="https://en.wikipedia.org/wiki/ElGamal_encryption"><u>El Gamal</u></a> encryption. This isn't a coincidence. Good cryptographers roll their own crypto; great cryptographers steal from good cryptographers.</p><p>Let's now put this together into code. The last thing we'll need is a method of generating random matrices and column vectors. We call this function <code>gen_mat() </code>below. Take a crack at implementing this yourself. Our scheme has two parameters: the modulus <code>Q</code>; and the dimension of <code>N</code> of the matrix and column vectors. The choice of <code>N</code> matters for security, but for now feel free to pick whatever value you want.</p>
            <pre><code>def key_gen():
    # Here `gen_mat()` returns an N-by-N matrix with entries
    # randomly chosen from `range(0, Q)`.
    A = gen_mat(N, N, 0, Q)
    # Like above except the matrix is N-by-1.
    s = gen_mat(N, 1, 0, Q)
    t = A*s % Q
    return ((A, t), s)

def encrypt(pk, ptxt):
    (A, t) = pk
    m = np.matrix([[ptxt]])
    r = gen_mat(N, 1, 0, Q)
    u = r.T*A % Q
    v = (r.T*t + m) % Q
    return (u, v)

def decrypt(sk, ctxt):
    s = sk
    (u, v) = ctxt
    m = (v - u*s) % Q
    return m[0,0]

# Test
assert decrypt(sk, encrypt(pk, 1)) == 1</code></pre>
            
    <div>
      <h4>Making the scheme secure (or "What is a lattice?")</h4>
      <a href="#making-the-scheme-secure-or-what-is-a-lattice">
        
      </a>
    </div>
    <p>By now, you might be wondering what on Earth a lattice even is. We promise we'll define it, but before we do, it'll help to understand why our warm-up scheme is insecure and what it'll take to fix it.</p><p>Readers familiar with linear algebra may already see the problem: in order for this scheme to be secure, it should be impossible for the attacker to recover the secret key <code>s</code>; but given the public <code>(A,t)</code>, we can immediately solve for <code>s</code> using <a href="https://en.wikipedia.org/wiki/Gaussian_elimination"><u>Gaussian elimination</u></a>.</p><p>In more detail, if <code>A</code> is invertible, we can write the secret key as <code>A</code><code><sup>-1</sup></code><code>*t == A</code><code><sup>-1</sup></code><code>*(A*s) == (A</code><code><sup>-1</sup></code><code>*A)*s == s,</code> where <code>A</code><code><sup>-1</sup></code> is the inverse of <code>A</code>. (When you multiply a matrix by its inverse, you get the identity matrix <code>I</code>, which simply takes a column vector to itself, i.e., <code>I*s == s.</code>) We can use Gaussian elimination to compute this matrix. Intuitively, all we're doing is solving a set of linear equations, where the entries of <code>s</code> are the unknown variables. (Note that this is possible even if <code>A</code> is not invertible.)</p><p>In order to make this encryption scheme secure, we need to make it a little... “messier”.</p>
    <div>
      <h5>Let's get messy</h5>
      <a href="#lets-get-messy">
        
      </a>
    </div>
    <p>For starters, we need to make it hard to recover the secret key from the public key. Let's try the following: generate another random vector <code>e</code> and add it into <code>A*</code>s. Our key generation algorithm becomes:</p>
            <pre><code>def key_gen():
    A = gen_mat(N, N, 0, Q)
    s = gen_mat(N, 1, 0, Q)
    e = gen_mat(N, 1, 0, Q)
    t = (A*s + e) % Q
    return ((A, t), s)</code></pre>
            <p>Our formula for the column vector component of the public key, <code>t</code>, now includes an additive term <code>e</code>, which we'll call the <b>error</b>. Like the secret key, the error is just a random vector. </p><p>Notice that the previous attack no longer works: since <code>A</code><code><sup>-1</sup></code><code>*t == A</code><code><sup>-1</sup></code><code>*(A*s + e) == A</code><code><sup>-1</sup></code><code>*(A*s) + A</code><code><sup>-1</sup></code><code>*e == s + A</code><code><sup>-1</sup></code><code>*e</code>, we need to know <code>e</code> in order to compute <code>s</code>.</p><p>Great, but this patch creates another problem. Take a second to plug in this new key generation algorithm into your implementation and test it out. What happens?</p><p>You should see that <code>decrypt()</code> now outputs garbage. We can see why using a little algebra:</p><blockquote><p>	<code>(v - u*s) == (r.T*t + m) - (r.T*A)*s</code></p><p><code>                == r.T*(A*s + e) + m - (r.T*A)*s</code></p><p><code>                == r.T*(A*s) + r.T*e + m - r.T*(A*s)</code></p><p><code>                == r.T*e + m</code></p></blockquote><p>The entries of <code>r</code> and <code>e</code> are sampled randomly, so <code>r.T*e</code> is also uniformly random. It's as if we encrypted <code>m</code> with a <a href="https://en.wikipedia.org/wiki/One-time_pad"><u>one-time pad</u></a>, then threw away the one-time pad!</p><h6>Handling decryption errors</h6><p>What can we do about this? First, it would help if <code>r.T*e</code> were small so that decryption yields something that's close to the plaintext. Imagine we could generate <code>r</code> and<code> e</code> in such a way that <code>r.T*e</code> were in <code>range(-epsilon, epsilon+1)</code> for some small <code>epsilon</code>. Then <code>decrypt</code> would output a number in <code>range(ptxt-epsilon, ptxt+epsilon+1)</code>, which would be pretty close to the actual plaintext.</p><p>However, we need to do better than get close. Imagine your browser failing to load your favorite website one-third of the time because of a decryption error. Nobody has time for that.</p><p>ML-KEM reduces the probability of decryption errors by being clever about how we encode the plaintext. Suppose all we want to do is encrypt a single bit, i.e., <code>ptxt </code>is either <code>0</code> or <code>1</code>. Consider the numbers in <code>range(Q)</code>, and split the number line into four chunks of roughly equal length:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3xojaMtl881io3pH4BdXNe/d47aede96c751942b82fedf0ca396450/image2.png" />
          </figure><p>Here we've labeled the region around zero (<code>-Q/4</code> to <code>Q/4</code> modulo <code>Q</code>) with <code>ptxt=0</code> and the region far away from zero with <code>ptxt=1</code>. To encode the bit, we set it to the integer corresponding to the middle of its range, i.e., <code>m = np.matrix([[ptxt * Q//2]])</code>. (Note the double "<code>//</code>" — this denotes integer division in Python.) To decode, we choose the <code>ptxt</code> corresponding to whatever range<code> m[0,0] </code>is in. That way if the decryption error is small, then we're highly likely to end up in the correct range.</p><p>Now all that's left is to ensure the decryption error, <code>r.T*e</code>, is small. We do this by sampling <b>short vectors </b><code>r</code> and <code>e</code>. By "short" we mean the entries of these vectors are sampled from a range that is much smaller than <code>range(Q)</code>. In particular, we'll pick some small positive integer <code>beta</code> and sample entries <code>range(-beta,beta+1)</code>.</p><p>How do we choose <code>beta</code>? Well, it should be small enough that decryption succeeds with overwhelming probability, but not so small that <code>r</code> and <code>e</code> are easy to guess and our scheme is broken. Take a minute or two to play with this. The parameters we can vary are:</p><ul><li><p>the modulus <code>Q</code></p></li><li><p>the dimension of the column vectors <code>N</code></p></li><li><p>the shortness parameter <code>beta</code></p></li></ul><p>For what ranges of these parameters is the decryption error low but the secret vectors are hard to guess? For what ranges is our scheme most efficient, in terms of runtime and communication cost (size of the public key plus the ciphertext)? We'll give a concrete answer at the end of this section, but in the meantime, we encourage you to play with this a bit.</p><h6>Gauss strikes back</h6><p>At this point, we have a working encryption scheme that mitigates at least one key-recovery attack. We've come pretty far, but we have at least one more problem.</p><p>Take another look at our formula for the ciphertext  <code>ctxt = (u,v)</code>. What would happen if we managed to recover the random vector <code>r</code>? That would be catastrophic, since <code>v == r.T*t + m</code>, and we already know <code>t</code> (part of the public key) and<code> v </code>(part of the ciphertext).</p><p>Just as we were able to compute the secret key from the public key in our initial scheme, we can recover the encryption randomness <code>r</code> from the ciphertext component <code>u</code> using Gaussian elimination. Again, this is just because <code>r</code> is the solution to a system of linear equations.</p><p>We can mitigate this plaintext-recovery attack just as before, by adding some noise. In particular, we'll generate a short vector according to <code>gen_mat(N,1,-beta,beta+1)</code> and add it into <code>u</code>. We also need to add noise to <code>v</code> in the same way, for reasons that we'll discuss in the next section.</p><p>Once again, adding noise increases the probability of a decryption error, but this time the magnitude of the error also depends on the secret key <code>s</code>. To see this, recall that during decryption, we multiply <code>u</code> by <code>s</code> (to compute the shared secret), and the error vector is an additive term. We'll therefore need <code>s</code> to be a short vector as well.</p><p>Let's now put together everything we've learned into an updated encryption scheme. Our scheme now has three parameters, <code>Q</code>, <code>N</code>, and <code>beta</code>, and can be used to encrypt a single bit:</p>
            <pre><code>def key_gen():
    A = gen_mat(N, N, 0, Q)
    s = gen_mat(N, 1, -beta, beta+1)
    e1 = gen_mat(N, 1, -beta, beta+1)
    t = (A*s + e1) % Q
    return ((A, t), s)

def encrypt(pk, ptxt):
    (A, t) = pk
    m = np.matrix([[ptxt*(Q//2) % Q]])
    r = gen_mat(N, 1, -beta, beta+1)
    e2 = gen_mat(N, 1, -beta, beta+1)
    e3 = gen_mat(1, 1, -beta, beta+1)
    u = (r.T*A + e2) % Q
    v = (r.T*t + e3 + m) % Q
    return (u, v)

def decrypt(sk, ctxt):
    s = sk
    (u, v) = ctxt
    m = (v - u*s) % Q
    if m[0,0] in range(Q//4, 3*Q//4):
        return 1
    return 0

# Test
assert decrypt(sk, encrypt(pk, 0)) == 0
assert decrypt(sk, encrypt(pk, 1)) == 1</code></pre>
            <p>Before moving on, try to find parameters for which the scheme works and for which the secret and error vectors seem hard to guess.</p>
    <div>
      <h5>Learning with errors</h5>
      <a href="#learning-with-errors">
        
      </a>
    </div>
    <p>So far we have a functioning encryption scheme for which we've mitigated two attacks, one a key-recovery attack and the other a plaintext-recovery attack. There seems to be no other obvious way of breaking our scheme, unless we choose parameters that are so weak that an attacker can easily guess the secret key s or ciphertext randomness r. Again, these vectors need to be short in order to prevent decryption errors, but not so short that they are easy to guess. (Likewise for the error terms.)</p><p>Still, there may be other attacks that require a little more sophistication to pull off. For instance, there might be some mathematical analysis we can do to recover, or at least make a good guess of, a portion of the ciphertext randomness. This raises a more fundamental question: in general, how do we establish that cryptosystems like this are actually secure?</p><p>As a first step, cryptographers like to try and reduce the attack surface. <b>Modern cryptosystems are designed so that the problem of attacking the scheme reduces to solving some other problem that is easier to reason about.</b></p><p>Our public key encryption scheme is an excellent illustration of this idea. Think back to the key- and plaintext-recovery attacks from the previous section. What do these attacks have in common?</p><p>In both instances, the attacker knows some public vector that allowed it to recover a secret vector:</p><ul><li><p>In the key-recovery attack, the attacker knew <code>t</code> for which <code>A*s == t.</code></p></li><li><p>In the plaintext-recovery attack, the attacker knew <code>u</code> for which <code>r.T*A == u </code>(or, equivalently,<code> A.T*r == u.T</code>).</p></li></ul><p>The fix in both cases was to construct the public vector in such a manner that it is hard to solve for the secret, namely, by adding an error term. However, ideally the public vector would reveal no information about the secret whatsoever. This ideal is formalized by the <b>Learning With Errors (LWE)</b> problem.</p><p>The LWE problem asks the attacker to distinguish between two distributions. Concretely, imagine we flip a coin, and if it comes up heads, we sample from the first distribution and give the sample to the attacker; and if the coin comes up tails, we sample from the second distribution and give the sample to the attacker. The distributions are as follows:</p><ul><li><p><code>(A,t=A*s + e</code>) where <code>A</code> is a random matrix generated with <code>gen_mat(N,N,0,Q)</code> and <code>s</code> and <code>e</code> are short vectors generated with <code>gen_mat(N,1,-beta,beta+1)</code>.</p></li><li><p><code>(A,t) </code>where <code>A</code> is a random matrix generated with <code>gen_mat(N,N,0,Q)</code> and <code>t</code> is a random vector generated with <code>gen_mat(N,1,0,Q)</code>.</p></li></ul><p>The first distribution corresponds to what we actually do in the encryption scheme; in the second, <code>t</code> is just a random vector, and no longer a secret vector at all. We say that the LWE problem is "hard" if no attacker is able to guess the coin flip with probability significantly better than one-half.</p><p>Our encryption is <i>passively </i>secure — meaning the ciphertext doesn't leak any information about the plaintext — if the LWE problem is hard for the parameters we chose. To see why, notice that both the public key and ciphertext look like LWE instances; if we can replace each instance with an instance of the random distribution, then the ciphertext would be completely independent of the plaintext and therefore leak no information about it at all. Note that, for this argument to go through, we also have to add the error term <code>e3</code> to the ciphertext component <code>v</code>.</p>
    <div>
      <h5>Choosing the parameters</h5>
      <a href="#choosing-the-parameters">
        
      </a>
    </div>
    <p>We've established that if solving the LWE problem is hard for parameters <code>N</code>, <code>Q</code>, and <code>beta</code>, then so is breaking our public key encryption scheme. What's left for us to do is tune the parameters so that solving LWE is beyond the reach of any attacker we can think of. This is where lattices come in.</p><h6>Lattices</h6><p>A <b>lattice </b>is an infinite grid of points in high-dimensional space. A two-dimensional lattice might look something like this:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5Js1SkG7bWyCNwPxKaYf3i/277a665f0e44ec7594e7e11b35958bc8/image4.png" />
          </figure><p>The points always follow a clear pattern that resembles "lattice work" you might see in a garden:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5kOimwlM1guY2YMj9Gn9xu/62ee11ddde1e18ba0cf3151a0b87092e/image5.jpg" />
          </figure><p><sup><i>(Source: https://picryl.com/media/texture-wood-vintage-backgrounds-textures-8395bb)</i></sup></p><p>For cryptography, we care about a special class of lattices, those defined by a matrix <code>P</code> that "recognizes" points in the lattice. That is, the lattice recognized by <code>P</code> is the set of vectors <code>v</code> for which <code>P*v == 0</code>, where "<code>0</code>" denotes the all-zero vector. The all-zero vector is <code>np.zeros((N,1), dtype=int)</code> in NumPy.</p><p>Readers familiar with linear algebra may have a different definition of lattices in mind: in general, a lattice is the set of points obtained by taking linear combinations of some basis. Our lattices can also be formulated in this way, i.e., for a matrix <code>P</code> that recognizes a lattice, we can compute the basis vectors that generate the lattice. However, we don't much care about this representation here.</p><p>The LWE problem boils down to distinguishing a set of points that are "close to" the lattice from a set of points that are "far away from" the lattice. We construct these points from an LWE instance and a random <code>(A,t)</code> respectively. Here we have an LWE sample (left) and a sample from the random distribution (right):</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/45bmYu3jdn8g7cI1i7WC3t/c82617991463169ecd83b1b944aa879a/image10.png" />
          </figure><p>What this shows is that the points of the LWE instance are much closer to the lattice than the random instance. This is indeed the case on average. However, while distinguishing LWE instances from random is easy in two dimensions, it gets harder in higher dimensions.</p><p>Let's take a look at how we construct these points. First, let's take an LWE instance <code>(A,t=(A*s + e) % Q</code>) and consider the lattice recognized by the matrix <code>P</code> we get by concatenating <code>A</code> with the identity matrix <code>I</code>. This might look something like this (<code>N=3</code>):</p>
            <pre><code>A = gen_mat(N, N, 0, Q)
P = np.concatenate((A, np.identity(N, dtype=int)), axis=1)
print(P)
# [[1570  634  161	1	0	0]
#  [1522 1215  861	0	1	0]
#  [ 344 2651 1889	0	0	1]]</code></pre>
            <p>Notice that we can compute <code>t</code> by multiplying <code>P</code> by the vector we get by concatenating <code>s</code> and <code>e</code> (<code>beta=2</code>):</p>
            <pre><code>s = gen_mat(N, 1, -beta, beta+1)
e = gen_mat(N, 1, -beta, beta+1)
t = (A*s + e) % Q
z = np.concatenate((s, e))
print(z)
# [[-2]
#  [ 0]
#  [-2]
#  [ 0]
#  [-1]
#  [ 2]]
assert np.array_equal(t, P*z % Q)</code></pre>
            <p>Let <code>z</code> denote this vector and consider the set of points <code>v</code> for which <code>P*v == t</code>. By definition, we say this set of points is "close to" the lattice because <code>z</code> is a short vector. (Remember: by "short" we mean its entries are bounded around <code>0</code> by <code>beta</code>.)</p><p>Now consider a random<code> (A,t)</code> and consider the set of points <code>v</code> for which <code>P*v == t</code>. We won't prove it, but it is a fact that this set of points is likely to be "far away from" the lattice in the sense that there is no short vector <code>z</code> for which<code> P*z == t.</code></p><p>Intuitively, solving LWE gets harder as <code>z</code> gets longer. Indeed, increasing the average length of <code>z</code> (by making <code>beta</code> larger) increases the average distance to the lattice, making it look more like a random instance: </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4oN8fydfP54b6EDLIOTYjI/85813f716b48164077b8f6d27586f768/unnamed__1_.png" />
          </figure><p>On the other hand, making <code>z</code> too long creates another problem.</p><h6>Breaking lattice cryptography by finding short vectors</h6><p>Given a random matrix <code>A</code>, the <b>Short Integer Solution (SIS)</b> problem is to find short vectors (i.e., whose entries are bounded by <code>beta</code>) <code>z1</code> and <code>z2</code> for which <code>(A*z1 + z2) % Q</code> is zero. Notice that this is equivalent to finding a short vector <code>z</code> in the lattice recognized by <code>P</code>:</p>
            <pre><code>z = np.concatenate((z1, z2))
assert np.array_equal((A*z1 + z2) % Q, P*z % Q)</code></pre>
            <p>If we had a (quantum) computer program for solving SIS, then we could use this program to solve LWE as well: if <code>(A,t) </code>is an LWE instance, then <code>z1.T*t </code>will be small; otherwise, if <code>(A,t)</code> is random, then <code>z1.T*t </code>will be uniformly random. (You can convince yourself of this using a little algebra.) Therefore, in order for our encryption scheme to be secure, it must be hard to find short vectors in the lattice defined by those parameters.</p><p>Intuitively, finding long vectors in the lattice is easier than finding short ones, which means that solving the SIS problem gets easier as <code>beta </code>gets closer to <code>Q</code>. On the other hand, as <code>beta </code> gets closer to <code>0</code>, it gets easier to distinguish LWE instances from random!</p><p><b>This suggests a kind of Goldilocks zone for LWE-based encryption</b>: if the secret and noise vectors are too short, then LWE is easy; but if the secret and noise vectors are too long, then SIS is easy. The optimal choice is somewhere in the middle.</p><h6>Enough math, just give me my parameters!</h6><p>To tune our encryption scheme, we want to choose parameters for which the most efficient known algorithms (quantum or classical) for solving LWE are out of reach for any attacker with as many resources as we can imagine (and then some, in case new algorithms are discovered). But how do we know which attacks to look out for?</p><p>Fortunately, the community of expert lattice cryptographers and cryptanalysts maintains a tool called <a href="https://github.com/malb/lattice-estimator"><u>lattice-estimator</u></a> that estimates the complexity of the best known (quantum) algorithms for lattice problems relevant to cryptography. Here's what we get when we run this tool for ML-KEM (this requires <a href="https://www.sagemath.org/"><u>Sage</u></a> to run):</p>
            <pre><code>sage: from estimator import *
sage: res = LWE.estimate.rough(schemes.Kyber768)
usvp        :: rop: ≈2^182.2, red: ≈2^182.2, δ: 1.002902, β: 624, d: 1427, tag: usvp
dual_hybrid :: rop: ≈2^174.3, red: ≈2^174.3, guess: ≈2^162.5, β: 597, p: 4, ζ: 10, t: 60, β': 597, N: ≈2^122.7, m: 768</code></pre>
            <p>The number that we're most interested in is "<code>rop</code>", which estimates the amount of computation the attack would consume. Playing with this tool a bit, we eventually find some parameters for our scheme for which the "<code>usvp</code>" and "<code>dual_hybrid</code>" attacks have comparable complexity. However, lattice-estimator identifies an attack it calls "<code>arora-gb</code>" that applies to our scheme, but not to ML-KEM, that has much lower complexity.  (<code>N=600</code>, <code>Q=3329</code>, and <code>beta=4</code>):</p>
            <pre><code>sage: res = LWE.estimate.rough(LWE.Parameters(n=600, q=3329, Xs=ND.Uniform(-4,4), Xe=ND.Uniform(-4,4)))
usvp        :: rop: ≈2^180.2, red: ≈2^180.2, δ: 1.002926, β: 617, d: 1246, tag: usvp
dual_hybrid :: rop: ≈2^226.2, red: ≈2^225.4, guess: ≈2^224.9, β: 599, p: 3, ζ: 10, t: 0, β': 599, N: ≈2^174.8, m: 600
arora-gb    :: rop: ≈2^129.4, dreg: 9, mem: ≈2^129.4, t: 4, m: ≈2^64.7</code></pre>
            <p>We'd have to bump the parameters even further to the scheme to a regime that has comparable security to ML-KEM.</p><p>Finally, a word of warning: when designing lattice cryptography, determining whether our scheme is secure requires a lot more than estimating the cost of generic attacks on our LWE parameters. In the absence of a mathematical proof of security in a realistic adversarial model, we can't rule out other ways of breaking our scheme. Tread lightly, fair traveler, and bring a friend along for the journey.</p>
    <div>
      <h4>Making the scheme efficient</h4>
      <a href="#making-the-scheme-efficient">
        
      </a>
    </div>
    <p>Now that we understand how to encrypt with LWE, let's take a quick look at how to make our scheme efficient.</p><p>The main problem with our scheme is that we can only encrypt a bit at a time. This is because we had to split the  <code>range(Q)</code> into two chunks, one that encodes <code>1</code> and another that encodes <code>0</code>. We could improve the bit rate by splitting the range into more chunks, but this would make decryption errors more likely.</p><p>Another problem with our scheme is that the runtime depends heavily on our security parameters. Encryption requires <code>O(N</code><code><sup>2</sup></code><code>)</code> multiplications (multiplication is the most expensive part of a secure implementation of modular arithmetic), and in order for our scheme to be secure, we need to make <code>N</code> quite large.</p><p>ML-KEM solves both of these problems by replacing modular arithmetic with arithmetic over a <a href="https://en.wikipedia.org/wiki/Polynomial_ring"><b><u>polynomial ring</u></b></a>. This means the entries of our matrices will be polynomials rather than integers. We need to define what it means to add, subtract, and multiply polynomials, but once we've done that, everything else about the encryption scheme is the same.</p><p>In fact, you probably learned polynomial arithmetic in grade school. The only thing you might not be familiar with is polynomial modular reduction. To multiply two polynomials $f(X)$ and $g(X)$, we start by multiplying $f(X)\cdot g(X)$ as usual. Then we're going to <b>divide </b>$f(X)\cdot g(X)$ by some special polynomial — ML-KEM uses $X^{256}+1$ — and take the remainder. We won't try to explain this algorithm, but the takeaway is that the result is a polynomial with $256$ coefficients, each of which is an integer in <code>range(Q)</code>.</p><p>The main advantage of using a polynomial ring for arithmetic is that we can pack more bits into the ciphertext. Our formula for the ciphertext is exactly the same (<code>u=r.T*A + e2, v=r.T*t + e3 + m</code>), but this time the plaintext <code>m </code>encodes a polynomial. Each coefficient of the polynomial encodes a bit, and we'll handle decryption errors just as we did before, by splitting <code>range(Q)</code> into two chunks, one that encodes <code>1</code> and another that encodes <code>0</code>. This allows us to reliably encrypt 256 bits (32 bytes) per ciphertext.</p><p>Another advantage of using polynomials is that it significantly reduces the dimension of the matrix without impacting security. Concretely, the most widely used variant of ML-KEM, ML-KEM-768, uses a <code>3</code>-by-<code>3</code> matrix <code>A</code>, so just <code>9 </code>polynomials in total. (Note that $256 \cdot 3 = 768$, hence the name "ML-KEM-768".) However, note that we have to be careful in how we choose the modulus: $X^{256}+1$ is special in that it does not exhibit any algebraic structure that is known to permit attacks.</p><p>The choices of <code>Q=3329</code> for the coefficient modulus and $X^{256}+1$ for the polynomial modulus have one more benefit. They allow polynomial multiplication to be carried out using the <a href="https://eprint.iacr.org/2024/585"><u>NTT algorithm</u></a>, which massively reduces the number of multiplications and additions we have to perform. In fact, this optimization is a major reason why ML-KEM is sometimes faster in terms of CPU time than key exchange with elliptic curves.</p><p>We won't get into how NTT works here, except to say that the algorithm will look familiar to you if you've ever implemented RSA. In both cases we use the <a href="https://en.wikipedia.org/wiki/Chinese_remainder_theorem"><u>Chinese Remainder Theorem</u></a> to split multiplication up into multiple, cheaper multiplications with smaller moduli.</p>
    <div>
      <h4>From public key encryption to ML-KEM</h4>
      <a href="#from-public-key-encryption-to-ml-kem">
        
      </a>
    </div>
    <p>The last step to build ML-KEM is to make the scheme secure against chosen ciphertext attacks (CCA). Currently, it's only secure against chosen plaintext attacks (CPA), which basically means that the ciphertext leaks no information about the plaintext, regardless of the distribution of plaintexts. CCA security is stronger in that it gives the attacker access to <a href="https://en.wikipedia.org/wiki/Adaptive_chosen-ciphertext_attack#Practical_attacks"><u>decryptions of ciphertexts of its choosing</u></a>. (Of course, it's not allowed to decrypt the target ciphertext itself.) The specific transform used in ML-KEM results in a CCA-secure KEM ("Key-Encapsulation Mechanism").</p><p>Chosen ciphertext attacks might seem a bit abstract, but in fact they formalize a realistic threat model for many applications of KEMs (and public key encryption for that matter). For example, suppose we use the scheme in a protocol in which the server authenticates itself to a client by proving it was able to decrypt a ciphertext generated by the client. In this kind of protocol, the server acts as a sort of "decryption oracle" in which its responses to clients depend on the secret key. Unless the scheme is CCA secure, this oracle can be abused by an attacker to leak information about the secret key over time, allowing it to eventually impersonate the server.</p><p>ML-KEM incorporates several more optimizations to make it as fast and as compact as possible. For example, instead of generating a random matrix <code>A</code>, we can derive it from a random, 32-byte string (called a "seed") using a hash-based primitive called a XOF ("eXtendable Output Function"), in the case of ML-KEM this XOF is <a href="https://pycryptodome.readthedocs.io/en/latest/src/hash/shake128.html"><u>SHAKE128</u></a>. This significantly reduces the size of the public key.</p><p>Another interesting optimization is that the polynomial coefficients (integers in <code>range(Q)</code>) in the ciphertext are compressed by rounding off the least significant bits of each coefficient, thereby reducing the overall size of the ciphertext.</p><p>All told, for the most widely deployed parameters (ML-KEM-768), the public key is 1184 bytes and the ciphertext is 1088 bytes. There's no obvious way to reduce this, except by reducing the size of the encapsulated key or the size of the public matrix <code>A</code>. The former would make ML-KEM useful for fewer applications, and the latter would reduce the security margin.</p><p>Note that there are <a href="https://eprint.iacr.org/2022/031"><u>other lattice schemes</u></a> that are smaller, but they are based on different hardness assumptions and are still undergoing analysis.</p>
    <div>
      <h3>Authentication</h3>
      <a href="#authentication">
        
      </a>
    </div>
    <p>In the previous section, we learned about ML-KEM, the algorithm already in use to make encryption PQ-secure. However, encryption is only one piece of the puzzle: establishing a secure connection also requires <b>authenticating</b> the server — and sometimes the client, depending on the application.</p><p>Authentication is usually provided by a <b>digital signature scheme</b>, which uses a secret key to sign a message and a public key to verify the signature. The signature schemes used today aren't PQ-secure: a quantum computer can be used to compute the secret key corresponding to a server's public key, then use this key to impersonate the server.</p><p>While this threat is less urgent than the threat to encryption, mitigating it is going to be more complicated. Over the years, we've bolted a number of signatures onto the <a href="https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/">TLS handshake</a> in order to meet the evolving requirements of the web <a href="https://en.wikipedia.org/wiki/Public_key_infrastructure"><u>PKI</u></a>. We have PQ alternatives for these signatures, one of which we'll study in this section, but so far these signatures and their public keys are too large (i.e., take up too many bytes) to make comfortable replacements for today's schemes. Barring some breakthrough in <a href="https://blog.cloudflare.com/another-look-at-pq-signatures/"><u>NIST's ongoing standardization effort</u></a>, we will have to re-engineer TLS and the web PKI to use fewer signatures.</p><p>For now, let's dive into the PQ signature scheme we're likely to see deployed first: <a href="https://csrc.nist.gov/pubs/fips/204/final"><u>ML-DSA</u></a>, a.k.a. Dillithium. The design of ML-DSA follows a similar template as ML-KEM. We start by building some intermediate primitive, then we transform that primitive into the primitive we want, in this case a signature scheme.</p><p>ML-DSA is quite a bit more involved than ML-KEM, so we're going to try to boil it down even further and just try to get across the main ideas.</p>
    <div>
      <h4>Warm up</h4>
      <a href="#warm-up">
        
      </a>
    </div>
    <p>Whereas ML-KEM is basically El Gamal encryption with elliptic curves replaced with lattices, ML-DSA is basically the <a href="https://www.zkdocs.com/docs/zkdocs/zero-knowledge-protocols/schnorr/"><u>Schnorr identification protocol</u></a> with elliptic curves replaced with lattices. Schnorr's protocol is used by a <b>prover </b>to convince a <b>verifier</b> that it knows the secret key associated with its public key without revealing the secret key itself. The protocol has three moves and is executed with four algorithms:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7lV5fU3j9rRQ2j2Y4lpW8r/a12908c078ec46e0fa35ef674fcfdb07/image8.png" />
          </figure><ol><li><p><code>initialize()</code>: The prover initializes the protocol and sends a <b>commitment</b> to the verifier</p></li><li><p><code>challenge()</code>:  The verifier receives the commitment and sends the prover a <b>challenge</b></p></li><li><p><code>finish()</code>: The prover receives the challenge and sends the verifier the <b>proof</b> </p></li><li><p><code>verify()</code>:  Finally, the verifier uses the proof to decide whether the prover knows the secret key</p></li></ol><p>We get the high-level structure of ML-DSA by making this protocol non-interactive. In particular, the prover derives the challenge itself by hashing the commitment together with the message to be signed. The signature consists of the commitment and proof: to verify the signature, the verifier recomputes the challenge from the commitment and message and runs <code>verify()</code>as usual.</p><p>Let's jump right in to building Schnorr's identification protocol from lattices. If you've never seen this protocol before, then this will look a little like black magic at first. We'll go through it slowly enough to see how and why it works.</p><p>Just like for ML-KEM, our public key is an LWE instance <code>(A,t=A*s1 + s2)</code>. However, this time our secret key is the <i>pair</i> of short vectors <code>(s1,s2)</code>, i.e., it includes the error term. Otherwise, key generation is exactly the same:</p>
            <pre><code>def key_gen():
    A = gen_mat(N, N, 0, Q)
    s1 = gen_mat(N, 1, -beta, beta+1)
    s2 = gen_mat(N, 1, -beta, beta+1)
    t = (A*s1 + s2) % Q
    return ((A, t), (s1, s2))</code></pre>
            <p>To initialize the protocol, the prover generates another LWE instance <code>(A,w=A*y1 + y2)</code>. You'll see why in just a moment. The prover sends the <i>hash</i> of <code>w</code> as its commitment:</p>
            <pre><code>def initialize(A):
    y1 = gen_mat(N, 1, -beta, beta+1)
    y2 = gen_mat(N, 1, -beta, beta+1)
    w = (A*y1 + y2) % Q
    return (H(w), (y1, y2))</code></pre>
            <p>Here <code>H </code>is some cryptographic hash function, like <a href="https://en.wikipedia.org/wiki/SHA-3"><u>SHA-3</u></a>. The prover stores the secret vectors<code> (y1,y2)</code> for use in its next move.</p><p>Now it's time for the verifier's challenge. The challenge is just an integer, but we need to be careful about how we choose it. For now let's just pick it at random:</p>
            <pre><code>def challenge():
    return random.randrange(0, Q)</code></pre>
            <p>Remember: when we turn this protocol into a digital signature, the challenge is derived from the commitment, <code>H(w)</code>, and the message. The range of this hash function must be the same as the set of outputs of <code>challenge()</code>.</p><p>Now comes the fun part. The proof is a pair of vectors<code> (z1,z2)</code> satisfying <code>A*z1 + z2 == c*t + w</code>. We can easily produce this proof if we know the secret key:</p><p>	<code>z1 = (c*s1 + y1) % Q</code></p><p>        <code>z2 = (c*s2 + y2) % Q</code></p><p>Then <code>A*z1 + z2 == A*(c*s1 + y1) + (c*s2 + y2) == c*(A*s1 + s2) + (A*y1 + y2) == c*t + w</code>. Our goal is to design the protocol such that it's hard to come up with <code>(z1,z2)</code> without knowing <code>(s1,s2)</code>, even after observing many executions of the protocol.</p><p>Here are the <code>finish() </code>and <code>verify() </code>algorithms for completeness:</p>
            <pre><code>def finish(s1, s2, y1, y2, c):
    z1 = (c*s1 + y1) % Q
    z2 = (c*s2 + y2) % Q
    return (z1, z2)

def verify(A, t, hw, c, z1, z2):
	return H((A*z1 + z2 - c*t) % Q) == hw

# Test
((A, t), (s1, s2)) = key_gen()
(hw, (y1, y2)) = initialize(A)        # hw: prover -&gt; verifier
c = challenge()                       # c: verifier -&gt; prover
(z1, z2) = finish(s1, s2, y1, y2, c)  # (z1, z2): prover -&gt; verifier
assert verify(A, t, hw, c, z1, z2)    # verifier</code></pre>
            <p>Notice that the verifier doesn't actually check <code>A*z1 + z2 == c*t + w</code> directly; we have to rearrange the equation so that we can set the commitment to <code>H(w)</code> rather than <code>w</code>. We'll explain the need for hashing in the next section.</p>
    <div>
      <h4>Making this scheme secure</h4>
      <a href="#making-this-scheme-secure">
        
      </a>
    </div>
    <p>The question of whether this protocol is secure boils down to whether it's possible to impersonate the prover without knowledge of the secret key. Let's put our attacker hat on and poke around.</p><p>Perhaps there's a way to compute the secret key, either from the public key directly or by eavesdropping on executions of the protocol with the honest prover. If LWE is hard, then clearly there's no way we're going to extract the secret key from the public key <code>t</code>. Likewise, the commitment <code>H(w)</code>doesn't leak any information that would help us extract the secret key from the proof<code> (z1,z2)</code>.</p><p>Let's take a closer look at the proof. Notice that the vectors <code>(y1,y2)</code> "mask" the secret key vectors, sort of how the shared secret masks the plaintext in ML-KEM. However, there's one big exception: we also scale the secret key vectors by the challenge <code>c</code>.</p><p>What's the effect of scaling these vectors? If we squint at a few proofs, we start to see a pattern emerge. Let's look at <code>z1</code> first (<code>N=3, Q=3329, beta=4</code>):</p>
            <pre><code>((A, t), (s1, s2)) = key_gen()
print('s1={}'.format(s1.T % Q))
for _ in range(10):
    (w, (y1, y2)) = initialize(A)
    c = challenge()
    (z1, z2) = finish(s1, s2, y1, y2, c)
    print('c={}, z1={}'.format(c, z1.T))
# s1=[[   1	0 3326]]
# c=1123, z1=[[1121 3327 3287]]
# c=1064, z1=[[1060	4  137]]
# c=1885, z1=[[1884 3327  999]]
# c=269, z1=[[ 270 3325 2524]]
# c=1506, z1=[[1510 3325 2141]]
# c=3147, z1=[[3149	4  547]]
# c=703, z1=[[ 700	4 1219]]
# c=1518, z1=[[1518 3327 2104]]
# c=1726, z1=[[1726	0 1478]]
# c=2591, z1=[[2589	4 2217]]</code></pre>
            <p>Indeed, with enough proof samples, we should be able to make a pretty good guess of the value of <code>s1</code>. In fact, for these parameters, there is a simple statistical analysis we can do to compute <code>s1</code> exactly. (Hint: <code>Q</code> is a prime number, which means <code>c*pow(c,-1,Q)==1 </code>whenever <code>c&gt;0</code>.) We can also apply this analysis to <code>s2</code>, or compute it directly from <code>t</code>, <code>s1</code>, and <code>A</code>.</p><p>The main flaw in our protocol is that, although our secret vectors are short, scaling them makes them so long that they're not completely masked by<code> (y1,y2)</code>. Since <code>c</code> spans the entire <code>range(Q)</code>, so do the entries of <code>c*s1.</code> and <code>c*s2,</code> which means in order to mask these entries, we need the entries of <code>(y1,y2) </code>to span <code>range(Q)</code> as well. However, doing this would make solving LWE for <code>(A,w)</code> easy, by solving SIS. We somehow need to strike a balance between the length of the vectors of our LWE instances and the leakage induced by the challenge.</p><p>Here's where things get tricky. Let's refer to the set of possible outputs of <code>challenge() </code>as the <b>challenge space. </b>We need the challenge space to be fairly large, large enough that the probability of outputting the same challenge twice is negligible.</p><p>Why would such a collision be a problem? It's a little easier to see in the context of digital signatures. Let's say an attacker knows a valid signature for a message <code>m</code>. The signature includes the commitment <code>H(m)</code>, so the attacker also knows the challenge is <code>c == H(H(w),m)</code>. Suppose it manages to find a different message <code>m</code><code><sup>*</sup></code> for which <code>c == H(H(w),m</code><code><sup>*</sup></code><code>)</code>. Then the signature is also valid for m! And this attack is easy to pull off if the challenge space, that is, the set of possible outputs of <code>H</code>, is too small.</p><p>Unfortunately, we can't make the challenge space larger simply by increasing the size of the modulus <code>Q</code>: the larger the challenge might be, the more information we'd leak about the secret key. We need a new idea.</p>
    <div>
      <h5>The best of both worlds</h5>
      <a href="#the-best-of-both-worlds">
        
      </a>
    </div>
    <p>Remember that the hardness of LWE depends on the ratio between <code>beta</code> and <code>Q</code>. This means that <code>y1</code> and <code>y2</code> don't need to be short in absolute terms, but short relative to random vectors.</p><p>With that in mind, consider the following idea. Let's take a larger modulus, say <code>Q=2**31 - 1</code>, and we'll continue to sample from the same challenge space, <code>range(2**16)</code>.</p><p>First, notice that <code>z1</code> is now "relatively" short, since its entries are now in <code>range(-gamma, gamma+1)</code>, where <code>gamma = beta*(2**16-1),</code> rather than uniform over <code>range(Q)</code>. Let's also modify <code>initialize()</code> to sample the entries of <code>(y1,y2)</code> from the same range and see what happens:</p>
            <pre><code>def initialize(A):
	y1 = gen_mat(N, 1, -gamma, gamma+1)
	y2 = gen_mat(N, 1, -gamma, gamma+1)
	w = (A*y1 + y2) % Q
	return (H(w), (y1, y2))

((A, t), (s1, s2)) = key_gen()
print('s1={}'.format(s1.T % Q))
for _ in range(10):
    (w, (y1, y2)) = initialize(A)
    c = challenge()
    (z1, z2) = finish(s1, s2, y1, y2, c)
    print('c={}, z1={}'.format(c, z1.T))
# s1=[[3 0 1]]
# c=31476, z1=[[175933 141954  93186]]
# c=27360, z1=[[    136404 2147438807     283758]]
# c=33536, z1=[[2147430945 2147377022     190671]]
# c=23283, z1=[[186516  73400   4955]]
# c=24756, z1=[[    328377 2147438906 2147388768]]
# c=12428, z1=[[2147340715     188675      90282]]
# c=24266, z1=[[    175498 2147261581 2147301553]]
# c=45331, z1=[[357595 185269 177155]]
# c=45641, z1=[[     21592 2147249191 2147446200]]
# c=57893, z1=[[297750 113335 144894]]</code></pre>
            <p>This is definitely going in the right direction, since there are no obvious correlations between <code>z1</code> and <code>s1</code>. (Likewise for <code>z2</code> and <code>s2</code>.) However, we're not quite there.</p><p>One problem is that the challenge space is still quite small. With only <code>2**16 </code>challenges to choose from, we're likely to see a collision even after only a handful of protocol executions. We need the challenge space to be much, much larger, say around <code>2**256</code>. But then <code>Q</code> has to be an insanely large number in order for the <code>beta</code> to <code>Q</code> ratio to be secure.</p><p>ML-DSA is able to side step this problem due to its use of arithmetic over polynomial rings. It uses the same modulus polynomial as ML-KEM, so the challenge is a polynomial with 256 coefficients. The coefficients are chosen carefully so that the challenge space is large, but multiplication by the challenge scales the secret vector by a small amount. Note that we still end up using a slightly larger modulus (<code>Q=8380417</code>) for ML-DSA than for ML-KEM, but only by about twelve bits.</p><p>However, there is a more fundamental problem here, which is that we haven't completely ruled out that signatures may leak information about the secret key.</p>
    <div>
      <h5>Cause and effect</h5>
      <a href="#cause-and-effect">
        
      </a>
    </div>
    <p>Suppose we run the protocol a number of times, and in each run, we happen to choose a relatively small value for some entry of <code>y1</code>. After enough runs, this would eventually allow us to reconstruct the corresponding entry of <code>s1</code>. To rule this out as a possibility, we need to make <code>y1 </code>even longer. (Likewise for <code>y2</code>.) But how long?</p><p>Suppose we know that the entries of <code>z1</code> and <code>z2</code> are always in <code>range(-beta_loose,beta_loose+1) </code>for some <code>beta_loose &gt; beta</code>. Then we can <b>simulate </b>an honest run of the protocol as follows:</p>
            <pre><code>def simulate(A, t):
    z1 = gen_mat(N, 1, -beta_loose, beta_loose+1)
    z2 = gen_mat(N, 1, -beta_loose, beta_loose+1)
    c = challenge()
    w = (A*z1 + z2 - c*t) % Q
    return (H(w), c, (z1, z2))

# Test
((A, t), (s1, s2)) = key_gen()
(hw, c, (z1, z2)) = simulate(A, t)
assert verify(A, t, hw, c, z1, z2)</code></pre>
            <p>This procedure perfectly simulates honest runs of the protocol, in the sense that the output of <code>simulate() </code>is indistinguishable from the transcript of a real run of the protocol with the honest prover. To see this, notice that the <code>w</code>,<code> c</code>, <code>z1</code>, and <code>z2 </code>all have the same mathematical relationship (the verification equation still holds) and have the same distribution.</p><p>And here's the punch line: since this procedure doesn't use the secret key, it follows that the attacker learns nothing from eavesdropping on the honest prover that it can't compute from the public key itself. Pretty neat!</p><p>What's left to do is arrange for <code>z1</code> and <code>z2</code> to fall in this range. First, we modify <code>initialize() </code>by increasing the range of <code>y1 </code>and<code> y2 </code>by<code> beta_loose</code>:</p>
            <pre><code>def initialize(A):
    y1 = gen_mat(N, 1, -gamma+beta_loose, gamma+beta_loose+1)
    y2 = gen_mat(N, 1, -gamma+beta_loose, gamma+beta_loose+1)
    w = (A*y1 + y2) % Q
    return (H(w), (y1, y2))</code></pre>
            <p>This ensures the proof vectors <code>z1</code> and <code>z2 </code>are roughly uniform over r<code>ange(-beta_loose, beta_loose+1)</code>. However, they may fall slightly outside of this range, so need to modify <code>finalize() </code>to <b>abort </b>if not. Correspondingly, <code>verify() </code>should reject proof vectors that are out of range:</p>
            <pre><code>def finish(s1, s2, y1, y2, c):
    z1 = (c*s1 + y1) % Q
    z2 = (c*s2 + y2) % Q
    if not in_range(z1, beta_loose) or not in_range(z2, beta_loose):
        return (None, None)
    return (z1, z2)

def verify(A, t, hw, c, z1, z2):
    if not in_range(z1, beta_loose) or not in_range(z2, beta_loose):
        return False
    return H((A*z1 + z2 - c*t) % Q) == hw</code></pre>
            <p>If <code>finish()</code> returns <code>(None,None)</code>, then the prover and verifier are meant to abort the protocol and retry until the protocol succeeds:</p>
            <pre><code>((A, t), (s1, s2)) = key_gen()
while True:
    (hw, (y1, y2)) = initialize(A)        # hw: prover -&gt; verifier
    c = challenge()                       # c: verifier -&gt; prover
    (z1, z2) = finish(s1, s2, y1, y2, c)  # (z1, z2): prover -&gt; verifier
    if z1 is not None and z2 is not None:
        break
assert verify(A, t, hw, c, z1, z2)</code></pre>
            <p>Interestingly, we should expect aborts to be quite common. The parameters of ML-DSA are tuned so that the protocol runs five times on average before it succeeds.</p><p>Another interesting point is that the security proof requires us to simulate not only successful protocol runs, but aborted protocol runs as well. More specifically, the protocol simulator must abort with the same probability as the real protocol, which implies that the rejection probability is <i>independent </i>of the secret key.</p><p>The simulator also needs to be able to produce realistic looking commitments for aborted transcripts. This is exactly why the prover commits to the <i>hash</i> of <code>w </code>rather than <code>w </code> itself: in the security proof, we can easily simulate hashes of random inputs.</p>
    <div>
      <h4>Making this scheme efficient</h4>
      <a href="#making-this-scheme-efficient">
        
      </a>
    </div>
    <p>ML-DSA benefits from many of the same optimizations as ML-KEM, including using polynomial rings, NTT for polynomial multiplication, and encoding polynomials with a fixed number of bits. However, ML-DSA has a few more tricks to make things smaller.</p><p>First, in ML-DSA, instead of the pair of short vectors <code>z1 </code>and <code>z2</code>, the proof consists of a single vector <code>z=c*s1 + y,</code> where <code>y</code> was committed to in the previous step. In turn, we only end up with a single proof vector <code>z</code> rather than two as before. Getting this to work requires a special encoding of the commitment so that we can't compute <code>y</code> from it. ML-DSA uses a related trick to reduce the size of the <code>t</code> vector of the public key, but the details are more complicated.</p><p>For the parameters we expect to deploy first (ML-DSA-44), the public key is 1312 bytes long and the signature is a whopping 2420 bytes. In contrast to ML-KEM, it is possible to shave off some more bytes. This does not come for free and requires complicating the scheme. An example is <a href="https://eprint.iacr.org/2023/624.pdf"><u>HAETAE</u></a>, which changes the distributions used. <a href="https://github.com/pornin/rust-fn-dsa"><u>Falcon</u></a> takes it a step further with even smaller signatures, using a completely different approach, which although elegant is also more complex to implement.</p>
    <div>
      <h3>Wrap up</h3>
      <a href="#wrap-up">
        
      </a>
    </div>
    <p>Lattice cryptography underpins the first generation of PQ algorithms to get widely deployed on the Internet. ML-KEM is already widely used today to protect encryption from quantum computers, and in the coming years we expect to see ML-DSA deployed to get ahead of the threat of quantum computers to authentication.</p><p>Lattices are also the basis of a new frontier for cryptography: computing on encrypted data.</p><p>Suppose you wanted to aggregate some metrics submitted by clients without learning the metrics themselves. <a href="https://eprint.iacr.org/2024/936"><u>With LWE-based encryption</u></a>, you can arrange for each client to encrypt their metrics before submission, aggregate the ciphertexts, then decrypt to get the aggregate.</p><p>Suppose instead that a server has a database that it wants to provide clients access to without revealing to the server which rows of the database the client wants to query. <a href="https://eprint.iacr.org/2022/949"><u>LWE-based encryption</u></a> allows the database to be encoded in a manner that permits encrypted queries.</p><p>These applications are special cases of a paradigm known as <a href="https://en.wikipedia.org/wiki/Homomorphic_encryption"><u>FHE</u></a> ("Fully Homomorphic Encryption"), which allows for arbitrary computations on encrypted data. FHE is an extremely powerful primitive, and the only way we know how to build it today is with lattices. However, for most applications, FHE is far less practical than a special-purpose protocol would be (lattice-based or not). Still, over the years we've seen FHE get better and better, and for many applications it is already a decent option. Perhaps we'll dig into this and other lattice schemes in a future blog post.</p><p>We hope you enjoyed this whirlwind tour of lattices. Thanks for reading!</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Cryptography]]></category>
            <category><![CDATA[Post-Quantum]]></category>
            <category><![CDATA[Research]]></category>
            <guid isPermaLink="false">01euRoOpkvsq16eKrMZ6hu</guid>
            <dc:creator>Christopher Patton</dc:creator>
            <dc:creator>Peter Schwabe (Guest Author)</dc:creator>
        </item>
        <item>
            <title><![CDATA[Improving Data Loss Prevention accuracy with AI-powered context analysis]]></title>
            <link>https://blog.cloudflare.com/improving-data-loss-prevention-accuracy-with-ai-context-analysis/</link>
            <pubDate>Fri, 21 Mar 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare’s Data Loss Prevention is reducing false positives by using a self-improving AI-powered algorithm, built on Cloudflare’s Developer Platform. ]]></description>
            <content:encoded><![CDATA[ <p>We are excited to announce our latest innovation to Cloudflare’s <a href="https://www.cloudflare.com/zero-trust/products/dlp/"><u>Data Loss Prevention</u></a> (DLP) solution: a self-improving AI-powered algorithm that adapts to your organization’s unique traffic patterns to reduce false positives. </p><p>Many customers are plagued by the shapeshifting task of identifying and protecting their sensitive data as it moves within and even outside of their organization. Detecting this data through deterministic means, such as regular expressions, often fails because they cannot identify details that are categorized as personally identifiable information (PII) nor intellectual property (IP). This can generate a high rate of false positives, which contributes to noisy alerts that subsequently may lead to review fatigue. Even more critically, this less than ideal experience can turn users away from relying on our DLP product and result in a reduction in their overall security posture. </p><p>Built into Cloudflare’s DLP Engine, AI enables us to intelligently assess the contents of a document or HTTP request in parallel with a customer’s historical reports to determine context similarity and draw conclusions on data sensitivity with increased accuracy.</p><p>In this blog post, we’ll explore <a href="https://developers.cloudflare.com/cloudflare-one/policies/data-loss-prevention/dlp-profiles/advanced-settings/"><u>DLP AI Context Analysis</u></a>, its implementation using <a href="https://www.cloudflare.com/developer-platform/products/workers-ai/"><u>Workers AI</u></a> and <a href="https://www.cloudflare.com/developer-platform/products/vectorize/"><u>Vectorize</u></a>, and future improvements we’re developing. </p>
    <div>
      <h3>Understanding false positives and their impact on user confidence</h3>
      <a href="#understanding-false-positives-and-their-impact-on-user-confidence">
        
      </a>
    </div>
    <p>Data Loss Prevention (DLP) at Cloudflare detects sensitive information by scanning potential sources of data leakage across various channels such as web, cloud, email, and SaaS applications. While we leverage several detection methods, pattern-based methods like regular expressions play a key role in our approach. This method is effective for many types of sensitive data. However, certain information can be challenging to classify solely through patterns. For instance, U.S. Social Security Numbers (SSNs), structured as <a href="https://en.wikipedia.org/wiki/Social_Security_number#Structure"><u>AAA-GG-SSSS</u></a>, sometimes with dashes omitted, are often confused with other similarly formatted data, such as U.S. taxpayer identification numbers, bank account numbers, or phone numbers. </p><p>Since <a href="https://blog.cloudflare.com/inline-data-loss-prevention/"><u>announcing</u></a> our DLP product, we have introduced new capabilities like <a href="https://developers.cloudflare.com/cloudflare-one/policies/data-loss-prevention/dlp-profiles/advanced-settings/#confidence-levels"><u>confidence thresholds</u></a> to reduce the number of false positives users receive. This method involves examining the surrounding context of a pattern match to assess Cloudflare’s confidence in its accuracy. With confidence thresholds, users specify a threshold (low, medium, or high) to signify a preference for how tolerant detections are to false positives. DLP uses the chosen threshold as a minimum, surfacing only those detections with a confidence score that meets or exceeds the specified threshold.  </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1EOKyJisPTPWcSOep9Se7F/22c1bf40cbd0d698b0e24095826548cd/1.png" />
          </figure><p>However, implementing context analysis is also not a trivial task. A straightforward approach might involve looking for specific keywords near the matched pattern, such as "SSN" near a potential SSN match, but this method has its limitations. Keyword lists are often incomplete, users may make typographical errors, and many true positives do not have any identifying keywords nearby (e.g., bank accounts near routing numbers or SSNs near names).</p>
    <div>
      <h3>Leveraging AI/ML for enhanced detection accuracy</h3>
      <a href="#leveraging-ai-ml-for-enhanced-detection-accuracy">
        
      </a>
    </div>
    <p>To address the limitations of a hardcoded strategy for context analysis, we have developed a dynamic, self-improving algorithm that learns from customer feedback to further improve their future experience. Each time a customer reports a false positive via <a href="https://developers.cloudflare.com/cloudflare-one/policies/data-loss-prevention/dlp-policies/logging-options/#4-view-payload-logs"><u>decrypted payload logs</u></a>, the system reduces its future confidence for hits in similar contexts. Conversely, reports of true positives increase the system's confidence for hits in similar contexts. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4h84zJ0SNtfhTVGzwxVyk0/bbdcce73d4538619abb296617d793bff/2.png" />
          </figure><p>To determine context similarity, we leverage Workers AI. Specifically, <a href="https://developers.cloudflare.com/workers-ai/models/bge-base-en-v1.5/"><u>a pretrained language model</u></a> that converts the text into a high-dimensional vector (i.e. text embedding). These embeddings capture the meaning of the text, ensuring that two sentences with the same meaning but different wording map to vectors that are close to each other. </p><p>When a pattern match is detected, the system uses the AI model to compute the embedding of the surrounding context. It then performs a nearest neighbor search to find previously logged false or true positives with similar meanings. This allows the system to identify context similarities even if the exact wording differs, but the meaning remains the same. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/z8yLmrAXES70MzTn2GdQE/0845b35884535843fa01e4f1a92a3f41/3.png" />
          </figure><p>In our experiments using Cloudflare employee traffic, this approach has proven robust, effectively handling new pattern matches it hadn't encountered before. When the DLP admin reports false and true positives through the Cloudflare dashboard while viewing the payload log of a <a href="https://developers.cloudflare.com/cloudflare-one/policies/data-loss-prevention/dlp-policies/"><u>policy</u></a> match, it helps DLP continue to improve, leading to a significant reduction in false positives over time. </p>
    <div>
      <h3>Seamless integration with Workers AI and Vectorize</h3>
      <a href="#seamless-integration-with-workers-ai-and-vectorize">
        
      </a>
    </div>
    <p>In developing this new feature, we used components from Cloudflare's developer platform — <a href="https://developers.cloudflare.com/workers-ai/"><u>Workers AI</u></a> and <a href="https://developers.cloudflare.com/vectorize/"><u>Vectorize</u></a> — which helps simplify our design. Instead of managing the underlying infrastructure ourselves, we leveraged <a href="https://www.cloudflare.com/developer-platform/products/workers/"><u>Cloudflare Workers</u></a> as the foundation, using Workers AI for text embedding, and Vectorize as the vector database. This setup allows us to focus on the algorithm itself without the overhead of provisioning underlying resources.  </p><p>Thanks to Workers AI, converting text into embeddings couldn’t be easier. With just a single line of code we can transform any text into its corresponding vector representation.</p>
            <pre><code>const result = await env.AI.run(model, {text: [text]}).data;</code></pre>
            <p>This handles everything from tokenization to GPU-powered inference, making the process both simple and scalable.</p><p>The nearest neighbor search is equally straightforward. After obtaining the vector from Workers AI, we use Vectorize to quickly find similar contexts from past reports. In the meantime, we store the vector for the current pattern match in Vectorize, allowing us to learn from future feedback. </p><p>To optimize resource usage, we’ve incorporated a few more clever techniques. For example, instead of storing every vector from pattern hits, we use online clustering to group vectors into clusters and store only the cluster centroids along with counters for tracking hits and reports. This reduces storage needs and speeds up searches. Additionally, we’ve integrated <a href="https://www.cloudflare.com/developer-platform/products/cloudflare-queues/"><u>Cloudflare Queues</u></a> to separate the indexing process from the DLP scanning hot path, ensuring a robust and responsive system.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6e6krasQ5t5ekp1TK0kJ0A/414f74fd48ef10a16e369775ead189b7/4.png" />
          </figure><p>Privacy is a top priority. We redact any matched text before conversion to embeddings, and all vectors and reports are stored in customer-specific private namespaces across <a href="https://www.cloudflare.com/developer-platform/products/vectorize/"><u>Vectorize</u></a>, <a href="https://www.cloudflare.com/developer-platform/products/d1/"><u>D1</u></a>, and <a href="https://www.cloudflare.com/developer-platform/products/workers-kv/"><u>Workers KV</u></a>. This means each customer’s learning process is independent and secure. In addition, we implement data retention policies so that vectors that have not been accessed or referenced within 60 days are automatically removed from our system.  </p>
    <div>
      <h3>Limitations and continuous improvements</h3>
      <a href="#limitations-and-continuous-improvements">
        
      </a>
    </div>
    <p>AI-driven context analysis significantly improves the accuracy of our detections. However, this comes at the cost of some increase in latency for the end user experience.  For requests that do not match any enabled DLP entries, there will be no latency increase.  However, requests that match an enabled entry in a profile with AI context analysis enabled will typically experience an increase in latency of about 400ms. In rare extreme cases, for example requests that match multiple entries, that latency increase could be as high as 1.5 seconds. We are actively working to drive the latency down, ideally to a typical increase of 250ms or better. </p><p>Another limitation is that the current implementation supports English exclusively because of our choice of the language model. However, Workers AI is developing a multilingual model which will enable DLP to increase support across different regions and languages.</p><p>Looking ahead, we also aim to enhance the transparency of AI context analysis. Currently, users have no visibility on how the decisions are made based on their past false and true positive reports. We plan to develop tools and interfaces that provide more insight into how confidence scores are calculated, making the system more explainable and user-friendly.  </p><p>With this launch, AI context analysis is only available for Gateway HTTP traffic. By the end of 2025, AI context analysis will be available in both <a href="https://www.cloudflare.com/zero-trust/products/casb/"><u>CASB</u></a> and <a href="https://www.cloudflare.com/zero-trust/products/email-security/"><u>Email Security</u></a> so that customers receive the same AI enhancements across their entire data landscape.</p>
    <div>
      <h3>Unlock the benefits: start using AI-powered detection features today</h3>
      <a href="#unlock-the-benefits-start-using-ai-powered-detection-features-today">
        
      </a>
    </div>
    <p>DLP’s AI context analysis is in closed beta. Sign up <a href="https://www.cloudflare.com/lp/dlp-ai-context-analysis/"><u>here</u></a> for early access to experience immediate improvements to your DLP HTTP traffic matches. More updates are coming soon as we approach general availability!</p><p>To get access to DLP via Cloudflare One, contact your account manager.</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Zero Trust]]></category>
            <category><![CDATA[DLP]]></category>
            <category><![CDATA[SASE]]></category>
            <category><![CDATA[Data Protection]]></category>
            <category><![CDATA[Cloudflare One]]></category>
            <category><![CDATA[Workers AI]]></category>
            <guid isPermaLink="false">qBn1L12sUXNIbkTPY5HyK</guid>
            <dc:creator>Warnessa Weaver</dc:creator>
            <dc:creator>Tom Shen</dc:creator>
            <dc:creator>Joshua Johnson</dc:creator>
        </item>
        <item>
            <title><![CDATA[Cloudflare is now IRAP assessed at the PROTECTED level, furthering our commitment to the global public sector]]></title>
            <link>https://blog.cloudflare.com/irap-protected-assessment/</link>
            <pubDate>Fri, 21 Mar 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare is now assessed at the IRAP PROTECTED level, bringing our products and services to the Australian Public Sector. ]]></description>
            <content:encoded><![CDATA[ <p>We are excited to announce our public sector suite of services for Australia, Cloudflare for Government - Australia, has been assessed under the <a href="https://www.cyber.gov.au/irap"><u>Infosec Registered Assessor Program (IRAP)</u></a> at the PROTECTED level in Australia.</p><p>IRAP, established by the Australian government, provides a rigorous, standardized approach to security assessment for cloud products and services. Achieving IRAP PROTECTED assessment reinforces our commitment to providing secure, high-performance solutions for government agencies and highly regulated industries across the globe.  </p><p>Obtaining our IRAP assessment is one part of our broader strategy to scale out our <a href="https://www.cloudflare.com/cloudflare-for-government/"><u>Cloudflare for Government</u></a> offering to as many areas of the world as possible. Cloudflare’s global network offers governments and highly regulated customers a unique capability to be within 50ms of 95% of Internet users globally, while also offering robust security for data processing, key management, and metadata storage. Earlier this year, we announced that we completed our <a href="https://blog.cloudflare.com/cloudflares-commitment-to-advancing-public-sector-security-worldwide/"><u>ENS certification in Spain</u></a>, and we are well underway on the development of our <a href="https://www.fedramp.gov/understanding-baselines-and-impact-levels/"><u>FedRAMP High</u></a> systems in the United States. </p><p><a href="https://www.cloudflare.com/network"><u>Cloudflare’s network</u></a> spans more than 330 cities in over 120 countries, where we interconnect with approximately 13,000 network providers in order to provide a broad range of services to millions of customers. Our network is our greatest strength to provide resiliency, security, and performance. So, instead of creating a siloed government network that has limited access to our products and services, we decided to build the unique government compliance capabilities directly into our platform from the very beginning. We accomplished this by delivering critical controls in three key areas: traffic processing, management, and metadata storage.</p><p>The benefit of running the same software across our entire network is that it enables us to leverage our global footprint, and then make smart choices about how to handle traffic. For instance, Regional Services (our system that ensures that traffic is processed in the correct region) runs globally. Regional Services allows us to do global Layer 3 (network layer) DDoS attack prevention, while still only decrypting traffic inside our IRAP boundary, which includes both US and Australian facilities. This software-defined regionalization approach allows us to get the full benefits of the global network running anycast, while offering highly specific regionalization on the same hardware. We get similar advantages for key management and metadata storage locality. </p><p>Network and security services can dramatically improve user experiences, but only when they run as close to the user as possible, even if the user doesn’t live close to a major hub. Leveraging our global network of over 300 data centers to ingest traffic to our network, our private backbone can move traffic to the closest certified processing location that is within the scope of our IRAP system. This enables you to meet the most stringent controls of the IRAP assessment without trading off user experience.</p><p>Our single platform strategy enables almost every Cloudflare product and service across all of our solution areas to be included in scope with Cloudflare for Government - Australia. This includes our application security products like our CDN, WAF, API Shield, Rate Limiting, and Bot Management. Our Zero Trust Products like Secure Web Gateway, CASB, Magic Transit, Magic WAN, and Remote Browser Isolation are also in scope, as are developer platform components including Workers, R2, Durable Objects, Stream, and Cache Reserve. </p><p>We invite all of our Cloudflare for Government public and private partners to learn more about our capabilities and work with us to develop solutions to meet the security demands required in complex environments. Please reach out to us at <a><u>publicsector@cloudflare.com</u></a> with any questions.</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Compliance]]></category>
            <category><![CDATA[Public Sector]]></category>
            <category><![CDATA[IRAP]]></category>
            <guid isPermaLink="false">1dhrjh3QJmujurTsOE2fqW</guid>
            <dc:creator>Wesley Evans</dc:creator>
            <dc:creator>Damien Lhuilier</dc:creator>
        </item>
        <item>
            <title><![CDATA[Cloudflare named a leader in Web Application Firewall Solutions in 2025 Forrester report]]></title>
            <link>https://blog.cloudflare.com/cloudflare-named-leader-waf-forrester-2025/</link>
            <pubDate>Thu, 20 Mar 2025 14:00:00 GMT</pubDate>
            <description><![CDATA[ Forrester Research has recognized Cloudflare as a Leader in its The Forrester Wave™: Web Application Firewall Solutions, Q1 2025 report. ]]></description>
            <content:encoded><![CDATA[ <p>Forrester Research has recognized Cloudflare as a Leader in its <i>The Forrester Wave™: Web Application Firewall Solutions, Q1 2025</i> report. This market analysis helps security and risk professionals select the right solution for their needs. According to Forrester: </p><blockquote><p><i>“Cloudflare is a strong option for customers that want to manage an easy-to-use, unified web application protection platform that will continue to innovate.”</i></p></blockquote><p>In this evaluation, Forrester assessed 10 Web Application Firewall (WAF) vendors across 22 criteria, including product security and vision. We believe this recognition is due to our continued investment in our product offering. Get a complimentary copy of the report <a href="https://www.cloudflare.com/lp/forrester-wave-waf-2025/"><u>here</u></a>.</p><p>Since introducing our <a href="https://blog.cloudflare.com/heuristics-and-rules-why-we-built-a-new-old-waf/"><u>first WAF</u></a> in 2013, Cloudflare has transformed it into a robust, enterprise-grade Application Security platform. Our fully integrated suite includes WAF, bot mitigation, API security, client-side protection, and DDoS mitigation, all built on our expansive global network. By leveraging AI and machine learning, we deliver industry-leading security while enhancing application performance through our content delivery and optimization solutions.</p><p>According to the Forrester report, <i>“Cloudflare stands out with features that help customers work more efficiently.”</i> Unlike other solutions in the market, Cloudflare’s WAF, API Security, bot detection, client-side security, and DDoS protection are natively <a href="https://blog.cloudflare.com/new-application-security-experience/"><u>integrated within a single platform</u></a>, running on a unified engine. Our integrated solution empowers a seamless user experience and enables advanced threat detection across multiple vectors to meet the most demanding security requirements.</p>
    <div>
      <h3>Cloudflare: a standout in Application Security</h3>
      <a href="#cloudflare-a-standout-in-application-security">
        
      </a>
    </div>
    <p>Forrester’s evaluation of Web Application Firewall solutions is one of the most comprehensive assessments in the industry. We believe this report highlights Cloudflare’s integrated global cloud platform and our ability to deliver enterprise-grade security without added complexity. We don’t just offer a WAF — we provide a flexible, customizable security toolkit designed to address your unique application security challenges.</p><p>Cloudflare continuously leads the WAF market through our strategic vision and the breadth of our capabilities. We center our approach on relentless innovation, delivering industry-leading security features, and ensuring a seamless management experience with enterprise processes and tools such as Infrastructure as Code (IaC) and DevOps. Our predictable cadence of major feature releases, powered by annual initiatives like Security Week and Birthday Week, ensures that customers always have access to the latest security advancements.</p><p>We believe Forrester also highlighted Cloudflare’s extensive security capabilities, with particular recognition of the significant improvements in our API security offerings.</p>
    <div>
      <h3>Cloudflare’s top-ranked criteria</h3>
      <a href="#cloudflares-top-ranked-criteria">
        
      </a>
    </div>
    <p>In the report, Cloudflare received the highest possible scores in 15 out of 22 criteria, reinforcing, in our opinion, our commitment to delivering the most advanced, flexible and easy-to-use web application protection in the industry. Some of the key criteria include:</p><ul><li><p><b>Detection models</b>: Advanced AI and machine learning models that continuously evolve to detect new threats.</p></li><li><p><b>Layer 7 DDoS protection</b>: Industry-leading mitigation of sophisticated application-layer attacks.</p></li><li><p><b>Rule creation and modification:</b> Simple, easy to use rule creation experience, propagating within seconds globally.</p></li><li><p><b>Management UI:</b> An intuitive and efficient user interface that simplifies security management.</p></li><li><p><b>Product security</b>: A robust architecture that ensures enterprise-grade security.</p></li><li><p><b>Infrastructure-as-code support</b>: Seamless integration with DevOps workflows for automated security policy enforcement.</p></li><li><p><b>Innovation</b>: A forward-thinking approach to security, consistently pushing the boundaries of what’s possible.</p></li></ul>
    <div>
      <h3>What sets Cloudflare apart?</h3>
      <a href="#what-sets-cloudflare-apart">
        
      </a>
    </div>
    <p>First, Cloudflare’s WAF goes beyond traditional rule-based protections, offering a comprehensive suite of detection mechanisms to identify attacks and vulnerabilities across web and API traffic while also safeguarding client environments. We leverage AI and machine learning to detect threats such as attacks, automated traffic, anomalies, and compromised JavaScript, among others. Our industry-leading application-layer DDoS protection makes volumetric attacks a thing of the past.</p><p>Second, Cloudflare has also made significant strides in <a href="https://developers.cloudflare.com/api-shield/"><u>API security</u></a>. Our WAF can be supercharged with features such as: API discovery, schema validation &amp; sequence mitigation, volumetric detection, and JWT authentication. </p><p>Third, Cloudflare simplifies security management with an intuitive dashboard that is easy to use while still offering powerful configurations for advanced practitioners. All features are Terraform-supported, allowing teams to manage the entire Cloudflare platform as code. With Security Analytics, customers gain a comprehensive view of all traffic, whether mitigated or not, and can run what-if scenarios to test new rules before deployment. This analytic capability ensures that businesses can dynamically adapt their security posture while maintaining high performance. To make security management even more seamless, our<a href="https://www.cloudflare.com/learning/ai/what-is-agentic-ai/"> AI agent,</a> powered by Natural Language Processing (NLP), helps users craft and refine custom rules and create powerful visualizations within our analytics engine.</p>
    <div>
      <h3>Cloudflare: the clear choice for modern security</h3>
      <a href="#cloudflare-the-clear-choice-for-modern-security">
        
      </a>
    </div>
    <p>We are confident that Forrester’s report validates what our customers already know: Cloudflare is a leading WAF vendor, offering unmatched security, innovation, and ease of use. As threats continue to evolve, we remain committed to pushing the boundaries of web security to protect organizations worldwide.</p><p>If you’re looking for a powerful, scalable, and easy-to-manage web application firewall, Cloudflare is the best choice for securing your applications, <a href="https://www.cloudflare.com/the-net/api-security/">APIs</a>, and infrastructure.</p>
    <div>
      <h3>Ready to enhance your security?</h3>
      <a href="#ready-to-enhance-your-security">
        
      </a>
    </div>
    <p>Learn more about Cloudflare WAF by <a href="https://dash.cloudflare.com/sign-up"><u>creating an account</u></a> today and see why Forrester has recognized us as a leader in the market. </p><p><i>Forrester does not endorse any company, product, brand, or service included in its research publications and does not advise any person to select the products or services of any company or brand based on the ratings included in such publications. Information is based on the best available resources. Opinions reflect judgment at the time and are subject to change. For more information, read about Forrester’s objectivity </i><a href="https://www.forrester.com/about-us/objectivity/"><i><u>here </u></i></a>.</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Application Security]]></category>
            <category><![CDATA[WAF]]></category>
            <category><![CDATA[Web Application Firewall]]></category>
            <category><![CDATA[API Security]]></category>
            <category><![CDATA[Forrester]]></category>
            <guid isPermaLink="false">6oqVUC4QLYuEBImzaJo8eu</guid>
            <dc:creator>Daniele Molteni</dc:creator>
        </item>
        <item>
            <title><![CDATA[HTTPS-only for Cloudflare APIs: shutting the door on cleartext traffic]]></title>
            <link>https://blog.cloudflare.com/https-only-for-cloudflare-apis-shutting-the-door-on-cleartext-traffic/</link>
            <pubDate>Thu, 20 Mar 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ We are closing the cleartext HTTP ports entirely for Cloudflare API traffic. This prevents the risk of clients unintentionally leaking their secret API keys in cleartext during the initial request.  ]]></description>
            <content:encoded><![CDATA[ <p>Connections made over cleartext HTTP ports risk exposing sensitive information because the data is transmitted unencrypted and can be intercepted by network intermediaries, such as ISPs, Wi-Fi hotspot providers, or malicious actors on the same network. It’s common for servers to either <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections"><u>redirect</u></a> or return a <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403"><u>403 (Forbidden)</u></a> response to close the HTTP connection and enforce the use of HTTPS by clients. However, by the time this occurs, it may be too late, because sensitive information, such as an API token, may have already been <a href="https://jviide.iki.fi/http-redirects"><u>transmitted in cleartext</u></a> in the initial client request. This data is exposed before the server has a chance to redirect the client or reject the connection.</p><p>A better approach is to refuse the underlying cleartext connection by closing the <a href="https://developers.cloudflare.com/fundamentals/reference/network-ports/"><u>network ports</u></a> used for plaintext HTTP, and that’s exactly what we’re going to do for our customers.</p><p><b>Today we’re announcing that we’re closing all of the </b><a href="https://developers.cloudflare.com/fundamentals/reference/network-ports/#network-ports-compatible-with-cloudflares-proxy:~:text=HTTP%20ports%20supported%20by%20Cloudflare"><b><u>HTTP ports</u></b></a><b> on api.cloudflare.com.</b> We’re also making changes so that api.cloudflare.com can change IP addresses dynamically, in line with on-going efforts to <a href="https://blog.cloudflare.com/addressing-agility/"><u>decouple names from IP addresses</u></a>, and reliably <a href="https://blog.cloudflare.com/topaz-policy-engine-design/"><u>managing</u></a> addresses in our authoritative DNS. This will enhance the agility and flexibility of our API endpoint management. Customers relying on static IP addresses for our API endpoints will be notified in advance to prevent any potential availability issues.</p><p>In addition to taking this first step to secure Cloudflare API traffic, we’ll release the ability for customers to opt-in to safely disabling all HTTP port traffic for their websites on Cloudflare. We expect to make this free security feature available in the last quarter of 2025.</p><p>We have <a href="https://blog.cloudflare.com/introducing-universal-ssl/"><u>consistently</u></a> <a href="https://blog.cloudflare.com/enforce-web-policy-with-hypertext-strict-transport-security-hsts/"><u>advocated</u></a> for <a href="https://blog.cloudflare.com/post-quantum-for-all/"><u>strong encryption standards</u></a> to safeguard users’ data and privacy online. As part of our ongoing commitment to enhancing Internet security, this blog post details our efforts to <i>enforce</i> HTTPS-only connections across our global network. </p>
    <div>
      <h3>Understanding the problem</h3>
      <a href="#understanding-the-problem">
        
      </a>
    </div>
    <p>We already provide an “<a href="https://developers.cloudflare.com/ssl/edge-certificates/additional-options/always-use-https/"><u>Always Use HTTPS</u></a>” setting that can be used to redirect all visitor traffic on our customers’ domains (and subdomains) from HTTP (plaintext) to HTTPS (encrypted). For instance, when a user clicks on an HTTP version of the URL on the site (http://www.example.com), we issue an HTTP 3XX redirection status code to immediately redirect the request to the corresponding HTTPS version (https://www.example.com) of the page. While this works well for most scenarios, there’s a subtle but important risk factor: What happens if the initial plaintext HTTP request (before the redirection) contains sensitive user information?</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2mXYZL0JRZOb8J6Tqm4mCj/1b24b76335ad9cf3f3b630ef31868f6c/1.png" />
          </figure><p><sup><i>Initial plaintext HTTP request is exposed to the network before the server can redirect to the secure HTTPS connection.</i></sup></p><p>Third parties or intermediaries on shared networks could intercept sensitive data from the first plaintext HTTP request, or even carry out a <a href="https://blog.cloudflare.com/monsters-in-the-middleboxes/"><u>Monster-in-the-Middle (MITM)</u></a> attack by impersonating the web server.</p><p>One may ask if <a href="https://developers.cloudflare.com/ssl/edge-certificates/additional-options/http-strict-transport-security/"><u>HTTP Strict Transport Security (HSTS)</u></a> would partially alleviate this concern by ensuring that, after the first request, visitors can only access the website over HTTPS without needing a redirect. While this does reduce the window of opportunity for an adversary, the first request still remains exposed. Additionally, HSTS is not applicable by default for most non-user-facing use cases, such as API traffic from stateless clients. Many API clients don’t retain browser-like state or remember HSTS headers they've encountered. It is quite <a href="https://jviide.iki.fi/http-redirects"><u>common practice</u></a> for API calls to be redirected from HTTP to HTTPS, and hence have their initial request exposed to the network.</p><p>Therefore, in line with our <a href="https://blog.cloudflare.com/dogfooding-from-home/"><u>culture of dogfooding</u></a>, we evaluated the accessibility of the Cloudflare API (<a href="https://api.cloudflare.com"><u>api.cloudflare.com</u></a>) over <a href="https://developers.cloudflare.com/fundamentals/reference/network-ports/#:~:text=ports%20listed%20below.-,HTTP,-ports%20supported%20by"><u>HTTP ports (80, and others)</u></a>. In that regard, imagine a client making an initial request to our API endpoint that includes their <i>secret API key</i>. While we outright reject all plaintext connections with a 403 Forbidden response instead of redirecting for API traffic — clearly indicating that “<i>Cloudflare API is only accessible over TLS”</i> — this rejection still happens at the <a href="https://www.cloudflare.com/learning/ddos/what-is-layer-7/">application layer</a>. By that point, the API key may have already been exposed over the network before we can even reject the request. We do have a notification mechanism in place to alert customers and rotate their API keys accordingly, but a stronger approach would be to eliminate the exposure entirely. We have an opportunity to improve!</p>
    <div>
      <h3>A better approach to API security</h3>
      <a href="#a-better-approach-to-api-security">
        
      </a>
    </div>
    <p>Any API key or token exposed in plaintext on the public Internet should be considered compromised. We can either address exposure after it occurs or prevent it entirely. The reactive approach involves continuously tracking and revoking compromised credentials, requiring active management to rotate each one. For example, when a plaintext HTTP request is made to our API endpoints, we detect exposed tokens by scanning for 'Authorization' header values.</p><p>In contrast, a preventive approach is stronger and more effective, stopping exposure before it happens. Instead of relying on the API service application to react after receiving potentially sensitive cleartext data, we can preemptively refuse the underlying connection at the <a href="https://www.cloudflare.com/learning/ddos/glossary/open-systems-interconnection-model-osi/"><u>transport layer</u></a>, before any HTTP or application-layer data is exchanged. The <i>preventative </i>approach can be achieved by closing all plaintext HTTP ports for API traffic on our global network. The added benefit is that this is operationally much simpler: by eliminating cleartext traffic, there's no need for key rotation.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1PYo3GMZjQ4LbfUHXNOVpj/2341da1d926e077624563358bd5034ef/2.png" />
          </figure><p><sup><i>The transport layer carries the application layer data on top.</i></sup></p><p>To explain why this works: an application-layer request requires an underlying transport connection, like TCP or QUIC, to be established first. The combination of a port number and an IP address serves as a transport layer identifier for creating the underlying transport channel. Ports direct network traffic to the correct application-layer process — for example, port 80 is designated for plaintext HTTP, while port 443 is used for encrypted HTTPS. By disabling the HTTP cleartext server-side port, we prevent that transport channel from being established during the initial "<a href="https://www.cloudflare.com/learning/ddos/glossary/tcp-ip/"><u>handshake</u></a>" phase of the connection — before any application data, such as a secret API key, leaves the client’s machine.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/13fKw8cHkHlsLOzlXJYenr/c9156f67ae99cfdc74dc5917ebc1e5bb/3.png" />
          </figure><p><sup><i>Both TCP and QUIC transport layer handshakes are a pre-requisite for HTTPS application data exchange on the web.</i></sup></p><p>Therefore, closing the HTTP interface entirely for API traffic gives a strong and visible <b>fast-failure</b> signal to developers that might be mistakenly accessing <code>http://… </code>instead of <code>https://…</code> with their secret API keys in the first request — a simple one-letter omission, but one with serious implications.</p><p>In theory, this is a simple change, but at Cloudflare’s global scale, implementing it required careful planning and execution. We’d like to share the steps we took to make this transition.</p>
    <div>
      <h3>Understanding the scope</h3>
      <a href="#understanding-the-scope">
        
      </a>
    </div>
    <p>In an ideal scenario, we could simply close all cleartext HTTP ports on our network. However, two key challenges prevent this. First, as shown in the <a href="https://radar.cloudflare.com/adoption-and-usage#http-vs-https"><u>Cloudflare Radar</u></a> figure below, about 2-3% of requests from “likely human” clients to our global network are over plaintext HTTP. While modern browsers prominently warn users about insecure HTTP connections and <a href="https://support.mozilla.org/en-US/kb/https-only-prefs"><u>offer features to silently upgrade to HTTPS</u></a>, this protection doesn't extend to the broader ecosystem of connected devices. IoT devices with limited processing power, automated API clients, or legacy software stacks often lack such safeguards entirely. In fact, when filtering on plaintext HTTP traffic that is “likely automated”, the share <a href="https://radar.cloudflare.com/explorer?dataSet=http&amp;groupBy=http_protocol&amp;filters=botClass%253DLikely_Automated"><u>rises to over 16%</u></a>! We continue to see a wide variety of legacy clients accessing resources over plaintext connections. This trend is not confined to specific networks, but is observable globally.</p><p>Closing HTTP ports, like port 80, across our entire IP address space would block such clients entirely, causing a major disruption in services. While we plan to cautiously start by implementing the change on Cloudflare's API IP addresses, it’s not enough. Therefore, our goal is to ensure all of our customers’ API traffic benefits from this change as well.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1OfUjwkP9iMdjymjtJX7tL/4cd278faf71f610c43239cc41d8f6fba/4.png" />
          </figure><p><sup><i>Breakdown of HTTP and HTTPS for ‘human’ connections</i></sup></p><p>The second challenge relates to limitations posed by the longstanding <a href="https://en.wikipedia.org/wiki/Berkeley_sockets"><u>BSD Sockets API</u></a> at the server-side, which we have addressed using <a href="https://blog.cloudflare.com/tubular-fixing-the-socket-api-with-ebpf/"><u>Tubular</u></a>, a tool that inspects every connection terminated by a server and decides which application should receive it. Operators historically have faced a challenging dilemma: either listen to the same ports across many IP addresses using a single socket (scalable but inflexible), or maintain individual sockets for each IP address (flexible but unscalable). Luckily, Tubular has allowed us to <a href="https://blog.cloudflare.com/its-crowded-in-here/"><u>resolve this using 'bindings'</u></a>, which decouples sockets from specific IP:port pairs. This creates efficient pathways for managing endpoints throughout our systems at scale, enabling us to handle both HTTP and HTTPS traffic intelligently without the traditional limitations of socket architecture.</p><p>Step 0, then, is about provisioning both IPv4 and IPv6 address space on our network that by default has all HTTP ports closed. Tubular enables us to configure and manage these IP addresses differently than others for our endpoints. Additionally, <a href="https://blog.cloudflare.com/addressing-agility/"><u>Addressing Agility</u></a> and <a href="https://blog.cloudflare.com/topaz-policy-engine-design/"><u>Topaz</u></a> enable us to assign these addresses dynamically, and safely, for opted-in domains.</p>
    <div>
      <h3>Moving from strategy to execution</h3>
      <a href="#moving-from-strategy-to-execution">
        
      </a>
    </div>
    <p>In the past, our legacy stack would have made this transition challenging, but today’s Cloudflare possesses the appropriate tools to deliver a scalable solution, rather than addressing it on a domain-by-domain basis.</p><p>Using Tubular, we were able to bind our new set of anycast IP prefixes to our TLS-terminating proxies across the globe. To ensure that no plaintext HTTP traffic is served on these IP addresses, we extended our global <a href="https://en.wikipedia.org/wiki/Iptables"><u>iptables</u></a> firewall configuration to reject any inbound packets on HTTP ports.</p>
            <pre><code>iptables -A INPUT -p tcp -d &lt;IP_ADDRESS_BLOCK&gt; --dport &lt;HTTP_PORT&gt; -j REJECT 
--reject-with tcp-reset

iptables -A INPUT -p udp -d &lt;IP_ADDRESS_BLOCK&gt; --dport &lt;HTTP_PORT&gt; -j REJECT 
--reject-with icmp-port-unreachable</code></pre>
            <p>As a result, any connections to these IP addresses on HTTP ports are filtered and rejected at the transport layer, eliminating the need for state management at the application layer by our web proxies.</p><p>The next logical step is to update the <a href="https://www.cloudflare.com/learning/dns/what-is-dns/"><u>DNS assignments</u></a> so that API traffic is routed over the <i>correct</i> IP addresses. In our case, we encoded a new DNS policy for API traffic for the HTTPS-only interface as a declarative <a href="https://blog.cloudflare.com/topaz-policy-engine-design/"><u>Topaz program</u></a> in our authoritative DNS server:</p>
            <pre><code>- name: https_only
 exclusive: true 
 config: |
    (config
      ([traffic_class "API"]
       [ipv4 (ipv4_address “192.0.2.1”)] # Example IPv4 address
       [ipv6 (ipv6_address “2001:DB8::1:1”)] # Example IPv6 address
       [t (ttl 300]))
  match: |
    (= query_domain_class traffic_class)
  response: |
    (response (list ipv4) (list ipv6) t)</code></pre>
            <p>The above policy encodes that for any DNS query targeting the ‘API traffic’ class, we return the respective HTTPS-only interface IP addresses. Topaz’s safety guarantees ensure <i>exclusivity</i>, preventing other DNS policies from inadvertently matching the same queries and misrouting plaintext HTTP expected domains to HTTPS-only IPs

api.cloudflare.com is the first domain to be added to our HTTPS-only API traffic class, with other applicable endpoints to follow.</p>
    <div>
      <h3>Opting-in your API endpoints</h3>
      <a href="#opting-in-your-api-endpoints">
        
      </a>
    </div>
    <p>As we said above, we've started with api.cloudflare.com and our internal API endpoints to thoroughly monitor any side effects on our own systems before extending this feature to customer domains. We have deployed these changes gradually across all data centers, leveraging Topaz’s flexibility to target subsets of traffic, minimizing disruptions, and ensuring a smooth transition.</p><p>To monitor unencrypted connections for your domains, before blocking access using the feature, you can review the relevant analytics on the Cloudflare dashboard. Log in, select your account and domain, and navigate to the "<a href="https://developers.cloudflare.com/analytics/types-of-analytics/#account-analytics-beta"><u>Analytics &amp; Logs</u></a>" section. There, under the "<i>Traffic Served Over SSL</i>" subsection, you will find a breakdown of encrypted and unencrypted traffic for your site. That data can help provide a baseline for assessing the volume of plaintext HTTP connections for your site that will be blocked when you opt in. After opting in, you would expect no traffic for your site will be served over plaintext HTTP, and therefore that number should go down to zero.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4YjvOU3XQqj1Y2Kfv2jIL3/97178a99d17f8938bc3ec53704bbc4b8/5.png" />
          </figure><p><i>Snapshot of ‘Traffic Served Over SSL’ section on Cloudflare dashboard</i></p><p>Towards the last quarter of 2025, we will provide customers the ability to opt in their domains using the dashboard or API (similar to enabling the Always Use HTTPS feature). Stay tuned!</p>
    <div>
      <h3>Wrapping up</h3>
      <a href="#wrapping-up">
        
      </a>
    </div>
    <p>Starting today, any unencrypted connection to api.cloudflare.com will be completely rejected. Developers should <b>not</b> expect a 403 Forbidden response any longer for HTTP connections, as we will prevent the underlying connection to be established by closing the HTTP interface entirely. Only secure HTTPS connections will be allowed to be established.</p><p>We are also making updates to transition api.cloudflare.com away from its static IP addresses in the future. As part of that change, we will be discontinuing support for <a href="https://developers.cloudflare.com/ssl/reference/browser-compatibility/#non-sni-support"><u>non-SNI</u></a> legacy clients for Cloudflare API specifically — currently, an average of just 0.55% of TLS connections to the Cloudflare API do not include an <a href="https://www.cloudflare.com/learning/ssl/what-is-sni/">SNI</a> value. These non-SNI connections are initiated by a small number of accounts. We are committed to coordinating this transition and will work closely with the affected customers before implementing the change. This initiative aligns with our goal of enhancing the agility and reliability of our API endpoints.</p><p>Beyond the Cloudflare API use case, we're also exploring other areas where it's safe to close plaintext traffic ports. While the long tail of unencrypted traffic may persist for a while, it shouldn’t be forced on every site.

In the meantime, a small step like this can allow us to have a big impact in helping make a better Internet, and we are working hard to reliably bring this feature to your domains. We believe security should be free for all!</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[HTTPS]]></category>
            <category><![CDATA[API]]></category>
            <category><![CDATA[Addressing]]></category>
            <category><![CDATA[Research]]></category>
            <guid isPermaLink="false">RqjV9vQoPNX8txlmrju6d</guid>
            <dc:creator>Suleman Ahmad</dc:creator>
            <dc:creator>Ash Pallarito</dc:creator>
            <dc:creator>Algin Martin</dc:creator>
        </item>
        <item>
            <title><![CDATA[Simplify allowlist management and lock down origin access with Cloudflare Aegis]]></title>
            <link>https://blog.cloudflare.com/aegis-deep-dive/</link>
            <pubDate>Thu, 20 Mar 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ Cloudflare Aegis provides dedicated egress IPs for Zero Trust origin access strategies, now supporting BYOIP and customer-facing configurability, with observability of Aegis IP utilization soon. ]]></description>
            <content:encoded><![CDATA[ <p>Today, we’re taking a deep dive into <a href="https://developers.cloudflare.com/aegis/"><u>Aegis</u></a>, Cloudflare’s origin protection product, to help you understand what the product is, how it works, and how to take full advantage of it for locking down access to your origin. We’re excited to announce the availability of <a href="https://developers.cloudflare.com/byoip/"><u>Bring Your Own IPs (BYOIP)</u></a> for Aegis, a customer-accessible Aegis API, and a gradual rollout for observability of Aegis IP utilization.</p><p>If you are new to Cloudflare Aegis, let’s take a step back and understand the product’s purpose and security benefits, process, and how it came to be. </p>
    <div>
      <h3>Origin protection then…</h3>
      <a href="#origin-protection-then">
        
      </a>
    </div>
    <p>Allowlisting a specific set of IP addresses has long existed as one of the simplest ways of restricting access to a server. This firewall mechanism is a starting state that just about every server supports. As we built Cloudflare’s network, one of the first features that customers requested was the ability to restrict access to their origin, so only Cloudflare could make requests to it. Back then, the most natural way to support this was to tell our customers which IP addresses belong to us, so they could allowlist those in their origin firewall. To that end, we have published our <a href="https://www.cloudflare.com/ips/"><u>IP address ranges</u></a>, providing an easy configuration to ensure that all traffic accessing your origin comes from Cloudflare’s network.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4I2fP03AeszxuHL78Ap9lA/bf75dcb9259b8b97b73f55831b3c019f/BLOG-2609_2.png" />
          </figure><p>However, Cloudflare’s IP ranges are used across multiple Cloudflare services and customers, so restricting access to the full list doesn’t necessarily give customers the security benefit they need. With the <a href="https://www.cloudflare.com/2024-api-security-management-report/#:~:text=Cloudflare%20serves%20over%2050%20million,billion%20cyber%20threats%20each%20day."><u>frequency</u></a> and <a href="https://blog.cloudflare.com/how-cloudflare-auto-mitigated-world-record-3-8-tbps-ddos-attack/"><u>scale</u></a> of IP-based and DDoS attacks every day, origin protection is absolutely paramount. Some customers have the need for more stringent security precautions to ensure that traffic is only coming from Cloudflare’s network and, more specifically, only coming from their zones within Cloudflare.</p>
    <div>
      <h3>Origin protection now…</h3>
      <a href="#origin-protection-now">
        
      </a>
    </div>
    <p>Cloudflare has built out additional services to lock down access to your origin, like <a href="https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/"><u>authenticated origin pulls</u></a> (mTLS) and <a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/"><u>Cloudflare Tunnels</u></a>, that no longer rely on IP addresses as an indicator of identity. These are part of a global effort towards <a href="https://www.cloudflare.com/learning/security/glossary/what-is-zero-trust/#:~:text=Zero%20Trust%20security%20means%20that,shown%20to%20prevent%20data%20breaches."><u>Zero Trust security</u></a>: whereas the Internet used to operate under a trust-but-verify model, we aim to operate as nothing is trusted, and everything is verified. </p><p>Having non-ephemeral IP addresses — upon which the firewall allowlist mechanism relies — does not quite fit the Zero Trust system. Although mTLS and similar solutions present a more modern approach to origin security, they aren’t always feasible for customers, depending on their hardware or system architecture. </p><p>We launched <a href="https://blog.cloudflare.com/cloudflare-aegis/"><u>Cloudflare Aegis</u></a> in March 2023 for customers seeking an intermediary security solution. Aegis provides a dedicated IP address, or set of addresses, from which Cloudflare sends requests, allowing you to further lock down your origin’s layer 3 firewall. Aegis also simplifies management by only requiring you to allowlist a small number of IP addresses. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3KmeBCAqzygLJWR7oMf7Mw/5303403c266e80d271160b9c32cbd764/BLOG-2609_3.png" />
          </figure><p>Normally, Cloudflare’s <a href="https://www.cloudflare.com/ips/"><u>publicly listed IP ranges</u></a> are used to egress from Cloudflare’s network to the customer origin. With these IP addresses distributed across Cloudflare’s network, the customer traffic can egress from many servers to the customer origin.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3RbmfIwMajVSjnHdEBN1Y/f99b2f41cb289df93f90c1960bf6a497/BLOG-2609_4.png" />
          </figure><p>With Aegis, a customer does not necessarily have an Aegis IP address on every server if they are using IPv4. That means requests must be routed through Cloudflare’s network to a server where Aegis IP addresses are present before the traffic can egress to the customer origin. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2TdNsZJmckJZuVCmAyCGbA/d7ed52f94c8a6fc375363bf011e40229/BLOG-2609_5.png" />
          </figure>
    <div>
      <h3>How requests are routed with Aegis</h3>
      <a href="#how-requests-are-routed-with-aegis">
        
      </a>
    </div>
    <p>A few terms, before we begin:</p><ul><li><p>Anycast: a technology where each of our data centers “announces” and can handle the same IP address ranges</p></li><li><p>Unicast: a technology where each server is given its own, unique <i>unicast</i> IP address</p></li></ul><p>Dedicated egress Aegis IPs are located in a particular set of specific data centers. This list is handpicked by the customer, in conversation with Cloudflare, to be geographically close to their origin servers for optimal security and performance in tandem. </p><p>Aegis relies on a technology called <a href="https://blog.cloudflare.com/cloudflare-servers-dont-own-ips-anymore/#soft-unicast-is-indistinguishable-from-magic"><u>soft-unicasting,</u> which allows</a> us to share a /32 egress IPv4 amongst many servers, thereby enabling us to spread a single subnet across many data centers. Then, the traffic going back from the origin servers (the return path) is routed to their closest data center. Once in Cloudflare's network, our in-house <a href="https://blog.cloudflare.com/unimog-cloudflares-edge-load-balancer/"><u>L4 XDP-based load balancer, Unimog,</u></a> ensures that the return packets make it back to the machine that connected to the origin servers at the start.</p><p>This supports fast, local, and reliable egress from Cloudflare’s network. With this configuration, we essentially use <a href="https://www.cloudflare.com/learning/cdn/glossary/anycast-network/"><u>Anycast</u></a> at the <a href="https://www.cloudflare.com/learning/security/glossary/what-is-bgp/"><u>BGP layer</u></a> before using an IP and port range to reach a specific machine in the correct data center. Across Cloudflare’s network, we use a significant range of egress IPs to cover all data centers and machines. Since Aegis customers only have a few IPv4 addresses, the range is limited to a few data centers rather than Cloudflare’s entire egress IP range.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6Y2sZmlh9uy6tRAiJhCZOp/ae186c36f30ba80500b615451952dfd7/BLOG-2609_6.png" />
          </figure>
    <div>
      <h3>The capacity issue</h3>
      <a href="#the-capacity-issue">
        
      </a>
    </div>
    <p>Every IP address has <a href="https://www.cloudflare.com/learning/network-layer/what-is-a-computer-port/#:~:text=There%20are%2065%2C535%20possible%20port,File%20Transfer%20Protocol%20(FTP)."><u>65,535 ports</u></a>. A request egresses from exactly one port on the Aegis IP address to exactly one port on the origin IP address. </p><p>Each TCP request consists of a 4-way tuple that contains:</p><ol><li><p>Source IP address</p></li><li><p>Source port</p></li><li><p>Destination IP address</p></li><li><p>Destination port</p></li></ol><p>A <a href="https://blog.cloudflare.com/everything-you-ever-wanted-to-know-about-udp-sockets-but-were-afraid-to-ask-part-1/"><u>UDP request</u></a> can also consist of a 4-way tuple (if it’s connected) or a 2-way tuple (if it’s unconnected), simply including a bind IP address and port. Aegis supports both TCP and UDP traffic — in either case, the requests rely upon IP:port pairings between the source and destination. </p><p>When a request reaches the origin, it opens a <i>connection</i>, through which data can pass between the source and destination. One source port can sustain multiple connections at a time, <i>only</i> if the destination ip:ports are different. </p><p>Normally at Cloudflare, an IP address establishes connections to a variety of different destination IP ports or addresses to support high traffic volumes. With Aegis, that is no longer the case. The challenge with Aegis IP capacity is exactly that: all the traffic is egressing to the same (or a small set of) origin IP address(es) from the same (or a small set of) source IP address(es). That means Aegis IP addresses have capacity constraints associated with them.</p><p>The number of <i>concurrent connections</i> is the number of simultaneous connections for a given 4-way tuple. Between one client and one server, the volume of concurrent connections is inherently limited by the number of ports on an IP address to 65,535 — each source ip:port can only support a single outbound connection per destination IP:port. In practice, that maximum number of concurrent connections is often lower due to assignments of port ranges across many servers and imperfect load distribution. </p><p>For planning purposes, we use an estimate of ~80% of the IP capacity (the volume of concurrent connections a source IP address can support to a destination IP address) to protect against overload, in case of traffic spikes. If every port on an IP address is maintaining a concurrent connection, that address would reach and exceed capacity — it would be overloaded with port usage exhaustion. Requests may then be dropped since no new connections can be established. To build in resiliency, we only plan to support 40k concurrent connections per Aegis IP address per origin.</p>
    <div>
      <h3>Aegis with IPv6</h3>
      <a href="#aegis-with-ipv6">
        
      </a>
    </div>
    <p>Each customer who onboards with Cloudflare Aegis receives two <a href="https://www.ripe.net/about-us/press-centre/understanding-ip-addressing/#:~:text=of%20IPv6%20addresses.-,IPv6%20Relative%20Network%20Sizes,-/128"><u>/64 prefixes</u></a> to be globally allocated and announced. That means, outside of Cloudflare’s China Network, every Cloudflare data center has hundreds or even thousands of addresses reserved for egressing your traffic directly to your origin. Without Aegis, any data center in Cloudflare’s Anycast network can serve as a point of egress – so we built Aegis with IPv6 to preserve that level of resiliency and performance. The sheer scale of IPv6, with its available address space, allows us to cushion Aegis’ capacity to a point far beyond any reasonable concern. Globally allocating and announcing your Aegis IPv6 addresses maintains all of Cloudflare’s functionality as a reverse proxy without inducing additional friction.</p>
    <div>
      <h3>Aegis with IPv4</h3>
      <a href="#aegis-with-ipv4">
        
      </a>
    </div>
    <p>Although using IPv6 with Aegis facilitates the best possible speed and resiliency for your traffic, we recognize the transition from IPv4 to IPv6 can be challenging for some customers. Moreover, some customers prefer Aegis IPv4 for granular control over their traffic’s physical egress locations. Still, IPv4 space is more limited and more expensive — while all Cloudflare Aegis customers simply receive two dedicated /64s for IPv6, enabling Aegis with IPv4 requires a touch more tailoring. When you onboard to Aegis, we work with you to determine the ideal number of IPv4 addresses for your Aegis configuration to maintain optimal performance and resiliency, while also ensuring cost efficiency. </p><p>Naturally, this introduces a bottleneck — whereas every Cloudflare data center can serve as a point of egress with Aegis IPv6, only a small fraction will have that capability with Aegis IPv4. We aim to mitigate this impact by careful provisioning of the IPv4 addresses. </p><p>Now that BYOIP for Aegis is supported, you can also onboard an entire IPv4 <a href="https://www.ripe.net/about-us/press-centre/understanding-ip-addressing/#:~:text=in%20that%20%E2%80%9Cblock%E2%80%9D.-,IPv4,-The%20size%20of"><u>/24</u></a> prefix or IPv6 /64 for Aegis, allowing for a cost-effective configuration with a much higher volume of capacity.</p><p>When we launched Aegis, each IP address was allocated to one data center, requiring at least two IPv4 addresses for appropriate resiliency. To reduce the number of IP addresses necessary in your layer 3 firewall allowlist, and to manage the cost to the customer of leasing IPs, we expanded our Aegis functionality so that one address can be announced from up to four data centers. To do this, we essentially slice the available IP port range into four subsets and provision each at a unique data center. </p><p>A quick refresher: when a request travels through Cloudflare, it first hits our network via an <i>ingress data center</i>. The ingress data center is generally near the eyeball, who is sending the request. Then, the request is routed following BGP – or <a href="https://developers.cloudflare.com/argo-smart-routing/"><u>Argo Smart Routing</u></a>, when enabled – to an <i>exit, or egress, data center</i>. The exit data center will generally fall in close geographic proximity to the request’s destination, which is the customer origin. This mitigates latency induced by the final hop from Cloudflare’s network to your origin.</p><p>With Aegis, the possible exit data centers are limited to the data centers in which an Aegis IP address has been allocated. For IPv6, this is a non-issue, since every data center outside our China Network is covered. With IPv4, however, the exit data centers are limited to a much smaller number (4 x the number of Aegis IPs). Aegis IP addresses are allocated, then, to data centers in close geographic proximity to your origin(s). This maximizes the likelihood that whichever data centers would ordinarily have been selected as the egress data center are already announcing Aegis IP addresses. Theoretically, no extra hop is necessary from the optimal exit data center to an Aegis-enabled data center – they are one and the same. In practice, this cannot be guaranteed 100% of the time because optimal routes are ever-changing. We recommend IPv6 to ensure optimal performance because of this possibility of an extra hop with IPv4.</p><p>A brief comparison, to summarize:</p><table><tr><th><p>
</p></th><th><p><b>Aegis IPv4</b></p></th><th><p><b>Aegis IPv6</b></p></th></tr><tr><td><p>Physical points of egress</p></td><td><p>4 physical data center sites (1-2 cities near origin) per IP address</p></td><td><p>All 300+ Cloudflare <a href="https://www.cloudflare.com/network/"><u>locations</u></a> (excluding China network)</p></td></tr><tr><td><p>Capacity</p></td><td><p>One IPv4 address per 40,000 concurrent connections per origin</p></td><td><p>Two /64 prefixes for all Aegis customers (&gt;36 quintillion IP addresses)</p><p>~50,000x capacity of IPv4 config</p></td></tr><tr><td><p>Pricing model</p></td><td><p>Monthly fee based on IPv4 leases or BYOIP for Aegis prefix fees</p></td><td><p>Included with product purchase or BYOIP for Aegis prefix fees</p></td></tr></table><p>Now, with Aegis analytics coming soon, customers can monitor and manage their IP address usage by Cloudflare data centers in aggregate. Every Cloudflare data center will now run a service with the sole purpose of calculating and reporting Aegis usage for each origin IP:port at regular intervals. Written to an internal database, these reports will be aggregated and exposed to customers via Cloudflare’s <a href="https://developers.cloudflare.com/analytics/graphql-api/"><u>GraphQL Analytics API</u></a>. Several aggregation functions will be available, such as average usage over a period of time, or total summed usage.</p><p>This will allow customers to track their own IP address usage to further optimize the distribution of traffic and addresses across different points of presence for IPv4. Additionally, the improved observability will support customer-created notifications via RSS feeds such that you can design your own notification thresholds for port usage.</p>
    <div>
      <h3>How Aegis benefits from connection reuse &amp; coalescence</h3>
      <a href="#how-aegis-benefits-from-connection-reuse-coalescence">
        
      </a>
    </div>
    <p>As we mentioned earlier, requests egress from the source IP address to the destination IP address only when a connection has been established between the two. In early Internet protocols, requests and connections were 1:1. Now, once that connection is open, it can remain open and support hundreds or thousands of requests between that source and destination via <i>connection reuse</i> and <i>connection coalescing</i>. </p><p>Connection reuse, implemented by <a href="https://datatracker.ietf.org/doc/html/rfc2616?cf_history_state=%7B%22guid%22%3A%22C255D9FF78CD46CDA4F76812EA68C350%22%2C%22historyId%22%3A41%2C%22targetId%22%3A%223BBCDD89688CD49F2C3350ED8037BC6F%22%7D"><u>HTTP/1.1</u></a>, allows for requests with the same source ip:port and destination IP:port to pass through the same connection to the origin. A “simple” website by modern standards can send hundreds of requests just to load initially; by streamlining these into a single origin connection, connection reuse reduces the latency derived from constantly opening and closing new connections between two endpoints. Still, any request from a different domain would need to create a new, unique connection to communicate with the origin. </p><p>As of <a href="https://datatracker.ietf.org/doc/html/rfc7540"><u>HTTP/2</u></a>, connection coalescing can group requests from different domains into one connection if the requests have the same destination IP address and the server certificate is authoritative for both domains. Depending on the traffic patterns routing from the eyeball to an Aegis IP address, the volume of connection reuse &amp; coalescence can vary. One connection most likely facilitates the traffic of many requests, but each connection requires at least one request to open it in the first place. Therefore, the worst possible ratio between concurrent connections and concurrent requests is 1:1. </p><p>In practice, a 1:1 ratio between connections and requests almost <i>never</i> happens. Connection reuse and connection coalescence are very common but highly variable, due to sporadic traffic patterns. We size our Aegis IP address allocations accordingly, erring on the conservative side to minimize risk of capacity overload. With the proper number of dedicated egress IP addresses and optimal allocation to Cloudflare points of presence, we are able to lock down your origin with IPv4 addresses to block malicious layer 7 traffic and reduce overall load to your origin. </p><p>Connection reuse and coalescence pairs well with Aegis to reduce load on the origin’s side as well. Because a request can be reused if it comes from the same source IP:port and shares a destination IP:port, routing traffic from a reduced number of source IP addresses (Aegis addresses, in this case) to your origin facilitates a smaller number of total connections. Not only does this improve security by limiting open connection access, but also it reduces latency since fewer connections need to be opened. Maintaining fewer connections is also less resource intensive — more connections means more CPU and more memory handling the inbound requests. By reducing the number of connections to the origin through reuse and coalescence, HTTP/2 lowers the overall cost of operation by optimizing resource usage. </p>
    <div>
      <h3>Recap and recommendations</h3>
      <a href="#recap-and-recommendations">
        
      </a>
    </div>
    <p>Cloudflare Aegis locks down your origin by restricting access via your origin’s layer 3 firewall. By routing traffic from Cloudflare’s network to your origin through dedicated egress IP addresses, you can ensure that requests coming from Cloudflare are legitimate customer traffic. With a simple flip-switch configuration — allow listing your Aegis IP addresses in your origin’s firewall — you can block excessive noise and bad actors from access. So, to help you take full advantage of Aegis, let’s recap:</p><ul><li><p>Concurrent connections can be, at worst, a 1:1 ratio to concurrent requests.</p></li><li><p>Cloudflare bases our IP address usage recommendations on 40,000 concurrent connections to minimize risk of capacity overload.</p></li><li><p>Each Aegis IP address supports an estimated 40,000 concurrent connections per origin IP address.</p></li></ul><p>Additionally, we’re excited to now support:</p><ul><li><p><a href="https://developers.cloudflare.com/api/resources/zones/subresources/settings/methods/edit/"><u>Public Aegis API</u></a> </p></li><li><p><a href="https://developers.cloudflare.com/aegis/setup/"><u>BYOIP for Aegis</u></a> </p></li><li><p>Customer-facing Aegis observability (coming soon via gradual rollout)</p></li></ul><p>For customers leasing Cloudflare-owned Aegis IP addresses, the Aegis API will allow you to enable and disable Aegis on zones within your parent account (parent being the account which owns the IP lease). If you deploy your Aegis IP addresses across multiple accounts, you’ll still rely on Cloudflare’s account team to enable and disable Aegis on zones within those additional accounts.</p><p>For customers who leverage BYOIP for Aegis, the Aegis API will allow you to enable and disable Aegis on zones within your parent account <i>and</i> within any accounts to which you <a href="https://developers.cloudflare.com/byoip/concepts/prefix-delegations/#:~:text=BYOIP%20supports%20prefix%20delegations%2C%20which,service%20used%20with%20the%20prefix."><u>delegate prefix permissions</u></a>. We recommend BYOIP for Aegis for improved configurability and cost efficiency. </p><table><tr><th><p>
</p></th><th><p><b>BYOIP</b></p></th><th><p><b>Cloudflare-owned IPs</b></p></th></tr><tr><td><p>Enable Aegis on zones on parent account</p></td><td><p>✓</p></td><td><p>✓</p></td></tr><tr><td><p>Enable Aegis on zones beyond parent account</p></td><td><p>✓</p></td><td><p>✗</p></td></tr><tr><td><p>Disable Aegis on zones on parent account</p></td><td><p>✓</p></td><td><p>✓</p></td></tr><tr><td><p>Disable Aegis on zones beyond parent account</p></td><td><p>✓</p></td><td><p>✗</p></td></tr><tr><td><p>Access Aegis analytics via the API</p></td><td><p>✓</p></td><td><p>✓</p></td></tr></table><p>With the improved Aegis observability, all Aegis customers will be able to monitor their port usage by IP address, account, zone, and data centers in aggregate via the API. You will also be able to ingest these metrics to configure your own, customizable alerts based on certain port usage thresholds. Alongside the new configurability of Aegis, this visibility will better equip customers to manage their Aegis deployments themselves and alert <i>us</i> to any changes, rather than the other way around.</p><p>We also have a few adjacent recommendations to optimize your Aegis configuration. We generally encourage the following best practices for security hygiene for your origin and traffic as well.</p><ol><li><p><b>IPv6 Compatibility</b>: if your origin(s) support IPv6, you will experience even better resiliency, performance, and availability with your dedicated egress IP addresses at a lower overall cost.</p></li><li><p><a href="https://www.cloudflare.com/learning/performance/http2-vs-http1.1/"><b><u>HTTP/2</u></b></a><b> or </b><a href="https://www.cloudflare.com/learning/performance/what-is-http3/"><b><u>HTTP/3</u></b></a><b> adoption</b>: by supporting connection reuse and coalescence, you will reduce overall load to your origin and latency in the path of your request.</p></li><li><p><b>Multi-level origin protection</b>: while Aegis protects your origin at the application level, it pairs well with <a href="https://blog.cloudflare.com/access-aegis-cni/"><u>Access and CNI</u></a>, <a href="https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/"><u>Authenticated Origin Pulls</u></a>, and/or other Cloudflare products to holistically protect, verify, and facilitate your traffic from edge to origin.</p></li></ol><p>If you or your organization want to enhance security and lock down your origin with dedicated egress IP addresses reach out to your account team to onboard today. </p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Aegis]]></category>
            <category><![CDATA[Egress]]></category>
            <category><![CDATA[IPv4]]></category>
            <category><![CDATA[IPv6]]></category>
            <guid isPermaLink="false">LPhv5n2cp5pkZBwAC8hN0</guid>
            <dc:creator>Mia Malden</dc:creator>
            <dc:creator>Adrien Vasseur</dc:creator>
        </item>
        <item>
            <title><![CDATA[Making Application Security simple with a new unified dashboard experience]]></title>
            <link>https://blog.cloudflare.com/new-application-security-experience/</link>
            <pubDate>Thu, 20 Mar 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ We’re introducing a new Application Security experience in the Cloudflare dashboard, with a reworked UI organized by use cases, making it easier for customers to navigate and secure their accounts. ]]></description>
            <content:encoded><![CDATA[ <p>Over the years, we have framed our Application Security features against market-defined product groupings such as Web Application Firewall (WAF), DDoS Mitigation, Bot Management, API Security (API Shield), Client Side Security (Page Shield), and so forth. This has led to unnecessary artificial separation of what is, under the hood, a well-integrated single platform.</p><p>This separation, which has sometimes guided implementation decisions that have led to different systems being built for the same purpose, makes it harder for our users to adopt our features and implement a simple effective security posture for their environment.</p><p>Today, following user feedback and our drive to constantly innovate and simplify, we are going back to our roots by breaking these artificial product boundaries and revising our dashboard, so it highlights our strengths. The ultimate goal remains: to make it shockingly easy to secure your web assets.</p><p><b>Introducing a new unified Application Security experience.</b></p><p>If you are a Cloudflare Application Security user, log in <a href="http://dash.cloudflare.com/:account/:zone/security"><u>to the dashboard</u></a> today and try out the updated dashboard interface. To make the transition easier, you can toggle between old and new interfaces.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/iyOx4HWAdpFyp0W6nECvi/5f67090ee17c9db87ce2c130f80d493a/image5.png" />
          </figure>
    <div>
      <h2>Security, simplified</h2>
      <a href="#security-simplified">
        
      </a>
    </div>
    <p>Modern applications are built using a variety of technologies. Your app might include a web interface and a mobile version, both powered by an API, each with its own unique security requirements. As these technologies increasingly overlap, traditional security categories like Web, API, client-side, and bot protection start to feel artificial and disconnected when applied to real-world application security.</p><p>Consider scenarios where you want to secure your API endpoints with proper authentication, or prevent vulnerability scanners from probing for weaknesses. These tasks often require switching between multiple dashboards, creating different policies, and managing disjointed configurations. This fragmented approach not only complicates workflows but also increases the risk of overlooking a critical vulnerability. The result? A security posture that is harder to manage and potentially less effective.</p><p>When you zoom out, a pattern emerges. Whether it’s managing bots, securing APIs, or filtering web traffic, these solutions ultimately analyze incoming traffic looking for specific patterns, and the resulting signal is used to perform actions. The primary difference between these tools is the type of signal they generate, such as identifying bots, enforcing authorization, or flagging suspicious requests. </p><p>At Cloudflare, we saw an opportunity to address this complexity by unifying our application security tools into a single platform with one cohesive UI. A unified approach means security practitioners no longer have to navigate multiple interfaces or piece together different security controls. With a single UI, you can configure policies more efficiently, detect threats faster, and maintain consistent protection across all aspects of your application. This simplicity doesn’t just save time, it ensures that your applications remain secure, even as threats evolve.</p><p>At the end of the day, attackers won’t care which product you’re using. But by unifying application security, we ensure they’ll have a much harder time finding a way in.</p>
    <div>
      <h2>Many products, one common approach</h2>
      <a href="#many-products-one-common-approach">
        
      </a>
    </div>
    <p>To redefine the experience across Application Security products, we can start by defining three concepts that commonly apply:</p><ul><li><p>Web traffic (HTTP/S), which can be generalised even further as “data”</p></li><li><p>Signals and detections, which provide intelligence about the traffic. Can be generalised as “metadata”</p></li><li><p>Security rules that let you combine any signal or detection (metadata), to block, challenge or otherwise perform an action on the web traffic (data)</p></li></ul><p>We can diagram the above as follows:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/46XB4bR8DSCZWe7PDQNDLp/4043ff4d123c4b8c5eafe0948c2fdefe/image1.png" />
          </figure><p>Using these concepts, all the product groupings that we offer can be converted to different types of signals or detections. All else remains the same. And if we are able to run and generate our signals on all traffic separately from the rule system, therefore generating all the metadata, we get what we call <a href="https://developers.cloudflare.com/waf/detections/"><b><u>always-on detections</u></b></a>, another vital benefit of a single platform approach. Also note that <a href="https://blog.cloudflare.com/traffic-sequence-which-product-runs-first/"><u>the order</u></a> in which we generate the signals becomes irrelevant.</p><p>In diagram form:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5TgbZHUYCkztCPfpbk8rYQ/d2ec02dddb61b8b708019aade73b9623/image12.png" />
          </figure><p>The benefits are twofold. First, problem spaces (such as account takeover or web attacks) become signal groupings, and therefore metadata that can be queried to answer questions about your environment.</p><p>For example, let’s take our Bot Management signal, the <a href="https://developers.cloudflare.com/bots/concepts/bot-score/"><u>bot score</u></a>, and our <a href="https://developers.cloudflare.com/waf/detections/attack-score/"><u>WAF Attack Score</u></a> signal, the attack score. These already run as always-on detections at Cloudflare. By combining these two signals and filtering your traffic against them, you can gain powerful insights on who is accessing your application<b>*</b>:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7xcSJtpZdY8L5svEob6dRW/f779872d453551b8d5ca11845a246fc5/image11.png" />
          </figure><p>Second, as everything is just a signal, the mitigation layer, driven by the optional rules, becomes detection agnostic. By providing the same signals as fields in a unified rule system, writing high level policies becomes a breeze. And as we said earlier, given the detection is <b>always-on </b>and fully separated from the mitigation rule system, exploring the data can be thought of as a powerful rule match preview engine. No need to deploy a rule in LOG mode to see what it matches!</p><p>We can now design a unified user experience that reflects Application Security as a single product.</p><p><sup><b><i>* note:</i></b></sup><sup><i> the example here is simplistic, and the use cases become a lot more powerful once you expand to the full set of potential signals that the platform can generate. Take, for example, our ability to detect file uploads. If you run a job application site, you may want to let crawlers access your site, but you may *</i></sup><sup><b><i>not</i></b></sup><sup><i>* want crawlers to submit applications on behalf of applicants. By combining the bot score signal with the file upload signal, you can ensure that rule is enforced.</i></sup></p>
    <div>
      <h2>Introducing a unified Application Security experience</h2>
      <a href="#introducing-a-unified-application-security-experience">
        
      </a>
    </div>
    <p>As signals are always-on, the user journey can now start from our <a href="https://blog.cloudflare.com/cloudflare-security-posture-management/#:~:text=protect%20what%20matters.-,Posture%20overview,-from%20attacks%20to"><u>new overview page</u></a> where we highlight security suggestions based on your traffic profile and configurations. Alternatively, you can jump straight into analytics where you can investigate your traffic using a combination of all available signals.</p><p>When a specific traffic pattern seems malicious, you can jump into the rule system to implement a security policy. As part of our new design, given the simplicity of the navigation, we also took advantage of the opportunity to introduce a <a href="https://blog.cloudflare.com/cloudflare-security-posture-management/#:~:text=Discovery%20of%20web%20assets"><u>new web assets page</u></a>, where we highlight discovery and attack surface management details.</p><p>Of course, reaching the final design required multiple iterations and feedback sessions. To best understand the balance of maintaining flexibility in the UI whilst reducing complexity, we focused on customer tasks to be done and documenting their processes while trying to achieve their intended actions in the dashboard. Reducing navigation items and using clear naming was one element, but we quickly learned that the changes needed to support ease of use for tasks across the platform.</p><p>Here is the end result:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2IFfm5Q1D6sfGzqhasl2Pb/e2f078c281a4067f5bb624b0ca37509e/image8.png" />
          </figure><p>To recap, our new dashboard now includes:</p><ul><li><p>One overview page where misconfigurations, risks, and suggestions are aggregated</p></li><li><p>Simplified and redesigned security analytics that surfaces security signals from all Application Security capabilities, so you can easily identify and act on any suspicious activity</p></li><li><p>A new web assets page, where you can manage your attack surfaces, helping improve detection relevance</p></li><li><p>A single Security Rules page that provides a unified interface to manage, prioritise, and customise all mitigation rules in your zone, significantly streamlining your security configuration</p></li><li><p>A new settings page where advanced control is based on security needs, not individual products</p></li></ul><p>Let’s dive into each one.</p>
    <div>
      <h3>Overview</h3>
      <a href="#overview">
        
      </a>
    </div>
    <p>With the unified security approach, the new overview page aggregates and prioritizes security suggestions across all your web assets, helping you <a href="https://blog.cloudflare.com/cloudflare-security-posture-management/"><u>maintain a healthy security posture</u></a>. The suggestions span from detected (ongoing) attacks if there are any, to risks and misconfigurations to further solidify your protection. This becomes the daily starting point to manage your security posture.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/19dZ0olpyIjEjywnd5zRrh/32bd0b872ab3c00f411e5287a8e2b6ae/image6.png" />
          </figure>
    <div>
      <h3>Analytics</h3>
      <a href="#analytics">
        
      </a>
    </div>
    <p>Security Analytics and Events have been redesigned to make it easier to analyze your traffic. Suspicious activity detected by Cloudflare is surfaced at the top of the page, allowing you to easily filter and review related traffic. From the Traffic Analytics Sampled Log view, further below in the page, new workflows enable you to take quick action to craft a custom rule or review related security events in context.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/16cUGVu3gqAD8sm9OaAs6x/2ef0474f3d193d95f062ed33abae2d80/image3.png" />
          </figure>
    <div>
      <h3>Web assets</h3>
      <a href="#web-assets">
        
      </a>
    </div>
    <p>Web assets is a new concept introduced to bridge your business goals with threat detection capabilities. A web asset is any endpoint, file, document, or other related entity that we normally would act on from a security perspective. Within our new web asset page, you will be able to explore all relevant discovered assets by our system.</p><p>With our unified security platform, we are able to rapidly build new <a href="https://blog.cloudflare.com/cloudflare-security-posture-management/#securing-your-web-applications:~:text=Use%2Dcase%20driven%20threat%20detection"><u>use-case driven threat detections</u></a>. For example, to block automated actions across your e-commerce website, you can instruct Cloudflare’s system to block any fraudulent signup attempts, while allowing verified crawlers to index your product pages. This is made possible by labelling your web assets, which, where possible, is automated by Cloudflare, and then using those labels to power threat detections to protect your assets.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/nKFhkuUboScRORcWHgYJR/17d23bb52e532910da6b1cc868bf702e/image9.png" />
          </figure>
    <div>
      <h3>Security rules</h3>
      <a href="#security-rules">
        
      </a>
    </div>
    <p>The unified Security rules interface brings all mitigation rule types — including WAF custom rules, rate limiting rules, API sequence rules, and client side rules — together in one centralized location, eliminating the need to navigate multiple dashboards.</p><p>The new page gives you visibility into how Cloudflare mitigates both incoming traffic and blocks potentially malicious client side resources from loading, making it easier to understand your security posture at a glance. The page allows you to create customised mitigation rules by combining any detection signals, such as Bot Score, Attack Score, or signals from Leaked Credential Checks, enabling precise control over how Cloudflare responds to potential threats.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/63A8aBq9400mKEyHAJGAuk/447447977592218fbaa418b3735754c7/image10.png" />
          </figure>
    <div>
      <h3>Settings</h3>
      <a href="#settings">
        
      </a>
    </div>
    <p>Balancing guidance and flexibility was the key driver for designing the new Settings page. As much as Cloudflare <i>guides</i> you towards the optimal security posture through recommendations and alerts, customers that want the <i>flexibility</i> to proactively adjust these settings can find all of them here.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/pz3N1v2EOCj3V9sKF009F/a106b34e0039bebf6eecdfc5c1244f41/image7.png" />
          </figure>
    <div>
      <h2>Experience it today</h2>
      <a href="#experience-it-today">
        
      </a>
    </div>
    <p>This is the first of many enhancements we plan to make to the Application Security experience in the coming months. To check out the new navigation, log in to the <a href="https://dash.cloudflare.com/"><u>Cloudflare dashboard</u></a>, click on “Security” and choose “Check it out” when you see the message below. You will still have the option of opting out, if you so prefer.</p><div>
  
</div>
<p></p><p>Let us know what you think either by sharing feedback in our <a href="https://community.cloudflare.com/"><u>community forum</u></a> or by providing feedback directly in the dashboard (you will be prompted if you revert to the old design).</p>
    <div>
      <h2>Watch on Cloudflare TV</h2>
      <a href="#watch-on-cloudflare-tv">
        
      </a>
    </div>
    <div>
  
</div><p></p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Application Security]]></category>
            <category><![CDATA[Dashboard]]></category>
            <category><![CDATA[WAF]]></category>
            <category><![CDATA[Bot Management]]></category>
            <guid isPermaLink="false">ktsrG1vJGggZ2JlL4cHxS</guid>
            <dc:creator>Michael Tremante</dc:creator>
            <dc:creator>Pete Thomas</dc:creator>
            <dc:creator>Jessica Tarasoff</dc:creator>
        </item>
        <item>
            <title><![CDATA[Improved support for private applications and reusable access policies with Cloudflare Access]]></title>
            <link>https://blog.cloudflare.com/improved-support-for-private-applications-and-reusable-access-policies-with-cloudflare-access/</link>
            <pubDate>Thu, 20 Mar 2025 05:00:00 GMT</pubDate>
            <description><![CDATA[ We are excited to introduce support for private hostname and IP address-defined applications as well as reusable access policies.
 ]]></description>
            <content:encoded><![CDATA[ 
    <div>
      <h3>Simplifying secure access for every application</h3>
      <a href="#simplifying-secure-access-for-every-application">
        
      </a>
    </div>
    <p>For years, Cloudflare has helped organizations modernize their access to internal resources by delivering identity-aware access controls through our <a href="https://www.cloudflare.com/learning/access-management/what-is-ztna/"><u>Zero Trust Network Access (ZTNA)</u></a> service, <a href="https://www.cloudflare.com/zero-trust/products/access/"><u>Cloudflare Access</u></a>. Our customers have accelerated their ZTNA implementations for web-based applications in particular, using our intuitive workflows for Access applications tied to public hostnames.</p><p>However, given our architecture design, we have primarily handled private network application access (applications tied to private IP addresses or hostnames) through the network firewall component of our <a href="https://www.cloudflare.com/learning/access-management/what-is-a-secure-web-gateway/"><u>Secure Web Gateway (SWG)</u></a> service, <a href="https://developers.cloudflare.com/cloudflare-one/policies/gateway/"><u>Cloudflare Gateway</u></a>. We provided a small wrapper from Access to connect the two experiences. While this implementation technically got the job done, there were some clear downsides, and our customers have frequently cited the inconsistency.</p><p>Today, we are thrilled to announce that we have redesigned the self-hosted private application administrative experience within Access to match the experience for web-based apps on public hostnames. We are introducing support for private hostname and IP address-defined applications directly within Access, as well as reusable access policies. Together, these updates make ZTNA even easier for our customers to deploy and streamline ongoing policy management.</p><p>In order to better understand how this feature improves the overall functionality of Access, let’s explore what makes up a “private” application, how they are typically accessed, what was possible before this feature, and what the new feature enables. If you are a networking expert or aficionado, you can skip ahead to <a href="#a-look-back-protecting-private-applications-with-cloudflare-zero-trust-before-access-private-ip-address-and-hostname-support"><u>A look back: protecting private applications with Cloudflare Zero Trust before Access Private IP Address and Hostname support</u></a>.</p>
    <div>
      <h3>Private applications</h3>
      <a href="#private-applications">
        
      </a>
    </div>
    <p>A private application in this context, is any application that is only accessible through a private IP address or hostname. </p>
    <div>
      <h4>Private IP addresses</h4>
      <a href="#private-ip-addresses">
        
      </a>
    </div>
    <p>Private IP addresses, often referred to as <a href="https://www.rfc-editor.org/rfc/rfc1918"><u>RFC 1918 IP addresses</u></a>, are scoped to a specific network and can only be reached by users on that network. While public IP addresses must be unique across the entire Internet, private IP addresses can be reused across networks. Any device or virtual machine will have a private IP address. For example, if I run <i>ipconfig</i> on my own Windows machine, I can see an address of 192.168.86.172.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/40guiajv2H8LiUIPj3I80L/392c59c79ae2cd5d1edec8eba485610f/1.png" />
          </figure><p>This is the address that any other machine on my own network can use to reference and communicate with this specific machine. Private IP addresses are useful for applications and ephemeral infrastructure (systems that spin up and down dynamically) because they can be reused and only have to be unique within their specific network. This is much easier to manage than issuing a public IPv4 address to resources – we’ve actually <a href="https://blog.cloudflare.com/cloudflare-research-two-years-in/#case-study-3-ip-address-agility"><u>run out of available public IPv4 address space</u></a>!</p><p>In order to host an application on a machine in my network, I need to make that application available to other machines in the network. Typically, this is done by assigning the application to a specific port. A request to that application might then look something like this: <a href="http://10.128.0.6:443"><u>http://10.128.0.6:443</u></a> which in plain English is saying “Using the hypertext transfer protocol, reach out to the machine at an address of 10.128.0.6 in my network, and connect to port 443.” Connecting to an application can be done in a browser, over <a href="https://www.cloudflare.com/learning/access-management/what-is-ssh/">SSH</a>, over <a href="https://www.cloudflare.com/learning/access-management/what-is-the-remote-desktop-protocol/">RDP</a>, through a thick client application, or many other methods of accessing a resource over an IP address.</p><p>In this case, we have an Apache2 example web server, running at that address and port combination.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/zmLj88okpYkIdg6FmBYow/5a07a43478ede91223f42960a9539251/2.png" />
          </figure><p>If I attempt to access this IP address outside of the same network as this machine running the web server, then I will either get no result, or a completely different application, if I have something else running on that IP address/port combination in that other network.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/46reRgnUQMGTx7BO4yYgYh/f46096a704b24789e6ceba6c400b72a2/3.png" />
          </figure>
    <div>
      <h4>Private hostnames</h4>
      <a href="#private-hostnames">
        
      </a>
    </div>
    <p>We don’t want to remember 10.128.0.6 every time we want to access this application. Just like the Internet, we can use <a href="https://www.cloudflare.com/learning/dns/what-is-dns/">DNS</a> in our private network. While public DNS serves as the phone book for the entire Internet, private DNS is more like a school directory that is only valid for phone numbers within the campus.</p><p>For a private application, I can configure a DNS record, very similar to how I might expose a public website to the world. But instead, I will map my DNS record to a private IP address that is only accessible within my own network. Additionally, private DNS does not require registering a domain with a <a href="https://www.cloudflare.com/learning/dns/glossary/what-is-a-domain-name-registrar/">registrar</a> or adhering to defined top level domains. I can host an application on <i>application.mycompany</i>, and it is a valid internal DNS record. </p><p>In this example, I am running my web server on Google Cloud and will call the application <i>kennyapache.local</i>. In my local DNS, <i>kennyapache.local</i> has an A record mapping it to an IPv4 address within my private network on Google Cloud (GCP).</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2OhO8VmCvfQ0H0ks1qUIir/74f5f4f764cef89393abf4989f0203e3/4.png" />
          </figure><p>This means that any machine within my network can use <i>https://kennyapache.local</i> instead of having to remember the explicit IP address.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/43nfcR2QZ6DtIhVGcdxlu4/2e72db9cdea772c15abf6a061926f531/5.png" />
          </figure>
    <div>
      <h3>Accessing private applications outside the private network</h3>
      <a href="#accessing-private-applications-outside-the-private-network">
        
      </a>
    </div>
    <p>Private networks require your machine, or virtual machine, to be connected directly to the same network as the target private IP address or hostname. This is a helpful property to keep unauthorized users from accessing applications, but presents a challenge if the application you want to use is outside your local network. </p><p><a href="https://www.cloudflare.com/learning/access-management/what-is-a-vpn/">Virtual Private Networks (VPNs)</a>, forward proxies, and proxy protocols (aka “<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_PAC_file"><u>PAC files</u></a>”) are all methods to enable a machine outside your private network to reach a private IP address/hostname within the private network. These tools work by adding an additional network interface to the machine and specifying that certain requests need to be routed through a remote private network, not the local network the machine is currently connected to, or out to the public Internet.</p><p>When I connect my machine to a forward proxy, in this case Cloudflare’s device client, <a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/"><u>WARP</u></a>, and run <i>ipconfig </i>I can see a new network interface and IP address added to the list:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5ETxtHA0R29eZkPMGXQiKA/3a698067576e625491695ea31f9aae77/6.png" />
          </figure><p>This additional network interface will take control of specific network requests and route those to an external private network instead of the default behavior of my machine, which would be to route to that IP address on my own local network.</p>
    <div>
      <h3>A look back: protecting private applications with Cloudflare Zero Trust <i>before</i> Access Private IP Address and Hostname support</h3>
      <a href="#a-look-back-protecting-private-applications-with-cloudflare-zero-trust-before-access-private-ip-address-and-hostname-support">
        
      </a>
    </div>
    <p>We will continue to use our Apache2 server hosted on a GCP private domain as an example private application. We will briefly touch on how Cloudflare Zero Trust was previously used to protect private applications and why this new feature is a huge step forward. Cloudflare Zero Trust has two primary components used to protect application traffic: Cloudflare Access and Gateway.</p>
    <div>
      <h4>Cloudflare Access</h4>
      <a href="#cloudflare-access">
        
      </a>
    </div>
    <p><a href="https://www.cloudflare.com/zero-trust/products/access/"><u>Cloudflare Access</u></a> is designed to protect internal applications and resources without the need for a traditional VPN. Access allows organizations to authenticate and authorize users through identity providers — such as Okta, Azure AD, or Google Workspace — before granting them entry to internal systems or web-based applications. </p><p>Until now, Access required that an application had to be defined using a public DNS record. This means that a user had to expose their application to the Internet in order to leverage Access and use all of its granular security features. This isn’t quite as scary as it sounds, because Access allows you to enforce strong user, device, and network security controls. In fact, <a href="https://www.nist.gov/"><u>NIST</u></a> and many other major security organizations support this model.</p><p>In practice, an administrator would map their internal IP address or hostname to a public URL using our app connector, <a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/"><u>Cloudflare Tunnel</u></a>. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2A5ipHt6Fle2B0va6u800e/aec1cc48f17d5599ea24259ea2724854/7.png" />
          </figure><p>Then, the administrator would create an Access application corresponding to that public URL. Cloudflare then sends a user through a single sign-on flow for any request made to that application.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3lJup7iAXJn4spQ9c1FdxA/d66d0e2e0139021c4a28c6498cd6e1b4/image2.png" />
          </figure><p>However, this approach does not work for organizations that have strict requirements to never expose an application over public DNS. Additionally, this does not work for applications outside the browser like SSH, RDP, FTP and other thick client applications, which are all options to connect to private applications.</p><p>If I tried to SSH to my Access-protected public hostname, I would get an error message with no way to authenticate, since there is no easy way to do a single sign-on through the browser in conjunction with SSH.</p>
    <div>
      <h4>Access Private Network applications</h4>
      <a href="#access-private-network-applications">
        
      </a>
    </div>
    <p>Until now, because Access operated using public hostnames, we have handled private network access for our customers using the network firewall piece of Cloudflare Gateway. A few years ago, we <a href="https://blog.cloudflare.com/zero-trust-private-networking-rules/"><u>launched</u></a> Access Private Network applications, which automatically generate the required Gateway block policies. However, this was a limited approach that was ultimately just a wrapper in front of two Gateway policies. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3Cyudmxym7VXQ5wLvslHqV/cc6bde76f33bcdddaea69e7f62e69ab0/9.png" />
          </figure>
    <div>
      <h4>Cloudflare Gateway</h4>
      <a href="#cloudflare-gateway">
        
      </a>
    </div>
    <p><a href="https://www.cloudflare.com/zero-trust/products/gateway/"><u>Cloudflare Gateway</u></a> is a secure web gateway that protects users from threats on the public Internet by filtering and securing DNS and web traffic. Gateway acts as a protective layer between end users and online resources by enforcing security controls, like blocking malicious domains, restricting access to risky categories of sites, and preventing <a href="https://www.cloudflare.com/learning/security/what-is-data-exfiltration/"><u>data exfiltration</u></a>. </p><p>Gateway is also used to route user traffic into private networks and acts as a forward proxy. It allows customers to create policies for private IP addresses and hostnames. This is because Gateway relies on traffic being proxied from the user’s machine to the Gateway service itself. This is most commonly done with the Cloudflare WARP client. WARP enables the configuration of which IP addresses and hostnames to send to Gateway for filtering and routing.</p><p>Once connected to a private network, through Gateway, a user can directly connect to private IP addresses and hostnames that are configured for that network.</p><p>I can then configure specific network firewall policies to allow or block traffic destined to private IP addresses.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4EtfhktReyry4NLabqunR/cb81b20c2e916c39fbd388ec3b8cbc8a/10.png" />
          </figure><p>Great! Looks like we’ve solved protecting private applications using Gateway. Not quite, unfortunately, as there are a few components of Gateway that are not an ideal model for an application-focused security model. While not discussed above, a few of the challenges we encountered when using Gateway for application access control included:</p><ul><li><p>Private applications were mixed in with general Gateway network firewall rules, complicating configuration and maintenance</p></li><li><p>Defining and managing private applications was not possible in Terraform</p></li><li><p>Application access logs were buried in general network firewall logs (these logs can contain all Internet traffic for an organization!)</p></li><li><p>Enforcement within Gateway relied on specific WARP client sessions, which lacked granular identity details</p></li><li><p>Administrators couldn’t use Access Rule Groups or other Access features built specifically for managing application access controls</p></li></ul><p>We knew we could do better.</p>
    <div>
      <h3>A unified approach to application access</h3>
      <a href="#a-unified-approach-to-application-access">
        
      </a>
    </div>
    <p>Knowing these limitations, we set out to extend Access to support any application, regardless of whether it is public or private. This principle guided our efforts to create a unified application definition in Cloudflare Access. Any self-hosted application, regardless of whether it is public or privately routable, should be defined in a single application type. The result is quite straightforward: <b>Access Applications now support </b><a href="https://developers.cloudflare.com/cloudflare-one/applications/non-http/self-hosted-private-app/"><b><u>private IP addresses and hostnames</u></b></a>.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6H0E6kyDN9Cm1f5R7OAPBm/c9630a990c52ab553c062deb14c6bd48/11.png" />
          </figure><p>However, the engineering work was not as simple as adding a private IP address and hostname option to Cloudflare Access. Given our platform’s architecture, Access does not have any way to route private requests by itself. We still have to rely on Gateway and the WARP client for that component.</p>
    <div>
      <h4>An application-aware firewall</h4>
      <a href="#an-application-aware-firewall">
        
      </a>
    </div>
    <p>This meant that we needed to add an application-specific phase to Gateway’s <a href="https://www.cloudflare.com/learning/security/what-is-a-firewall/">firewall</a>. The new phase detects whether a user’s traffic matches a defined application, and if so it sends the traffic to Access for authentication and authorization of a user and their session. This required extending Gateway’s network firewall to have knowledge of which private IP addresses and hostnames are defined as applications.</p><p>Thanks to this new firewall phase, now an administrator can configure exactly where they want their private applications to be evaluated in their overall network firewall.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6ruRjFqas4YtimtubJ2JH7/14f3a539536ffda5e7054e7bbff8638c/12.png" />
          </figure>
    <div>
      <h4>Private application sessions</h4>
      <a href="#private-application-sessions">
        
      </a>
    </div>
    <p>The other component we had to solve was per-application session management. In an Access public application, we issue a JSON Web Token (JWT) as a cookie which conveniently has an expiration associated. That acts as a session expiration. For private applications, we do not always have the ability to store a cookie. If the request is not over a browser, there is nowhere to put a <a href="https://www.cloudflare.com/learning/privacy/what-are-cookies/">cookie</a>.</p><p>For browser-based private applications, we follow the exact same pattern as a public application and issue a JWT as a means to track the session. App administrators get the additional benefit of being able to do <a href="https://www.bing.com/ck/a?!&amp;&amp;p=034518a2a9cf39217e3915ed984384030a9abdb4123d9e9e96cf917622fcd122JmltdHM9MTc0MDcwMDgwMA&amp;ptn=3&amp;ver=2&amp;hsh=4&amp;fclid=25d5373c-34a7-676d-2f67-229d35ee66b4&amp;psq=cloudflare+access+jwt+validation&amp;u=a1aHR0cHM6Ly9kZXZlbG9wZXJzLmNsb3VkZmxhcmUuY29tL2Nsb3VkZmxhcmUtb25lL2lkZW50aXR5L2F1dGhvcml6YXRpb24tY29va2llL3ZhbGlkYXRpbmctanNvbi8&amp;ntb=1"><u>JWT validation</u></a> for these apps as well. Non-browser based applications required adding a new per-application session to Gateway’s firewall. These application sessions are bound to a specific device and track the next time a user has to authenticate before accessing the application.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/20A2Xu4A9i66sKBB5JMFcy/c856a90127a540608d92a9d139b67515/13.png" />
          </figure>
    <div>
      <h4>Access private applications</h4>
      <a href="#access-private-applications">
        
      </a>
    </div>
    <p>Once we solved application awareness and session management in Gateway’s firewall, we could extend Access to support private IP address- and hostname-defined applications. Administrators can now directly define Access applications using private IP addresses and hostnames:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1lbk2iY0Nxp83UYPKjqT9r/6a473d16691d49e9fa6c24b7483c9f29/14.png" />
          </figure><p>You can see that private hostname and private IP address are now configuration options when defining an Access application.</p><p>If it is a non-HTTPS application (whether HTTP or non-browser), the user will receive a client pop-up prompting a re-authentication:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5MODs8OeSp1zarNyfSybRs/c0625e682c94be2076769bf45516f443/15.png" />
          </figure><p>HTTPS applications will behave exactly the same as an Access application with a public hostname. The user will be prompted to log in via single sign-on, and then a JWT will be issued to that specific domain.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2JKV68fl0w38N7G3CbIx3S/12c2fb6911938fae28e8dee8cf3518b5/16.png" />
          </figure><p>Then we see a JWT issued to the application itself.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3pjbbZZatyS5vTg9LBxwyA/8ae31cbbff12494508c686fbd2a60f99/17.png" />
          </figure>
    <div>
      <h3>Introducing Reusable Policies</h3>
      <a href="#introducing-reusable-policies">
        
      </a>
    </div>
    <p>As part of this work, we were able to address another long-standing pain point in Access —– managing policies across multiple applications was a time-consuming and error-prone process. Policies were nested objects under individual applications, requiring administrators to either rely heavily on Access Groups or repeat identical configurations for each application. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5VXOFmgC6ckvmnIaGY8kLL/50ce63a57b6f59625f8a0277f59a3153/18.png" />
          </figure><p>With <b>Reusable Policies</b>, administrators can now create standardized policies — such as high, medium, or low risk — and assign them across multiple applications. A single change to a reusable policy will propagate to all associated applications, significantly simplifying management. With this new capability, we anticipate that many of our customers will be able to move from managing hundreds of access policies to a small handful. We’ve also renamed "Access Groups" to "Rule Groups," aligning with their actual function and reducing confusion with identity provider (IdP) groups.</p>
    <div>
      <h3>A redesigned user interface</h3>
      <a href="#a-redesigned-user-interface">
        
      </a>
    </div>
    <p>Alongside these functional updates, we’ve launched a significant UI refresh based on years of user feedback. The new interface offers more information at a glance and provides consistent, intuitive workflows for defining and managing applications. </p>
    <div>
      <h3>Looking ahead</h3>
      <a href="#looking-ahead">
        
      </a>
    </div>
    <p>While today’s release is a major step forward, there’s more to come. Currently, private hostname support is limited to port 443 with TLS inspection enabled. Later in 2025, we plan to extend support to arbitrary private hostnames on any port and protocol, further broadening Access’s capabilities.</p>
    <div>
      <h3>Get started today</h3>
      <a href="#get-started-today">
        
      </a>
    </div>
    <p>These new Access features are live and ready for you to explore. If you haven’t yet started modernizing remote access at your organization, <a href="https://dash.cloudflare.com/sign-up/teams"><u>sign up for a free account</u></a> to test it out. Whether you’re <a href="https://developers.cloudflare.com/cloudflare-one/applications/non-http/self-hosted-private-app/"><u>securing private resources</u></a> or <a href="https://developers.cloudflare.com/cloudflare-one/policies/access/policy-management/"><u>simplifying policy management</u></a>, we’re excited to see how these updates enhance your Zero Trust journey. As always, we’re here to help — reach out to your account team with any questions or feedback.</p>
    <div>
      <h3>Watch on Cloudflare TV</h3>
      <a href="#watch-on-cloudflare-tv">
        
      </a>
    </div>
    <div>
  
</div><p></p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Cloudflare Access]]></category>
            <category><![CDATA[Cloudflare One]]></category>
            <category><![CDATA[Cloudflare Zero Trust]]></category>
            <guid isPermaLink="false">53DTUki2fBvLXzudP66p2M</guid>
            <dc:creator>Kenny Johnson</dc:creator>
            <dc:creator>Eduardo Gomes</dc:creator>
        </item>
        <item>
            <title><![CDATA[Cloudflare for AI: supporting AI adoption at scale with a security-first approach]]></title>
            <link>https://blog.cloudflare.com/cloudflare-for-ai-supporting-ai-adoption-at-scale-with-a-security-first-approach/</link>
            <pubDate>Wed, 19 Mar 2025 13:10:00 GMT</pubDate>
            <description><![CDATA[ With Cloudflare for AI, developers, security teams and content creators can leverage Cloudflare’s network and portfolio of tools to secure, observe and make AI applications resilient and safe to use. ]]></description>
            <content:encoded><![CDATA[ <p>AI is transforming businesses — from <a href="https://developers.cloudflare.com/agents/"><u>automated agents performing background workflows</u></a>, to improved search, to easier access and summarization of knowledge. </p><p>While we are still early in what is likely going to be a substantial shift in how the world operates, two things are clear: the Internet, and how we interact with it, will change, and the boundaries of security and data privacy have never been more difficult to trace, making security an important topic in this shift.</p><p>At Cloudflare, we have a mission to help build a better Internet. And while we can only speculate on what AI will bring in the future, its success will rely on it being reliable and safe to use.</p><p>Today, we are introducing <a href="https://www.cloudflare.com/press-releases/2025/cloudflare-introduces-cloudflare-for-ai/"><u>Cloudflare for AI</u></a>: a suite of tools aimed at helping businesses, developers, and content creators adopt, deploy, and <a href="https://blog.cloudflare.com/best-practices-sase-for-ai/">secure AI technologies</a> at scale safely.</p><p>Cloudflare for AI is not just a grouping of tools and features, some of which are new, but also a commitment to focus our future development work with AI in mind.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4s1CIOnpHnIdWPdFrzS6e1/a29e0ffa7123d69e855b3eac6d0a154f/1.png" />
          </figure><p>Let’s jump in to see what Cloudflare for AI can deliver for developers, security teams, and content creators…</p>
    <div>
      <h3>For developers</h3>
      <a href="#for-developers">
        
      </a>
    </div>
    <p>If you are building an AI application, whether a fully custom application or a vendor-provided hosted or SaaS application, Cloudflare can help you deploy, store, control/observe, and protect your AI application from threats.</p><p><b>Build &amp; deploy</b>: <a href="https://www.cloudflare.com/en-gb/developer-platform/products/workers-ai/"><u>Workers AI</u></a> and our new <a href="https://developers.cloudflare.com/agents/"><u>AI Agents SDK</u></a> facilitates the scalable development &amp; deployment of AI applications on Cloudflare’s network. Cloudflare’s network enhances user experience and efficiency by running AI closer to users, resulting in low-latency and high-performance AI applications. Customers are also using <a href="https://www.cloudflare.com/developer-platform/products/r2/"><u>Cloudflare’s R2</u></a> to <a href="https://www.cloudflare.com/the-net/cloud-egress-fees-challenge-future-ai/">store their AI training data with zero egress fees</a>, in order to develop the next-gen AI models. </p><p>We are continually investing in not only our serverless AI inference infrastructure across the globe, but also in making Cloudflare the best place to <a href="https://blog.cloudflare.com/build-ai-agents-on-cloudflare/"><u>build AI Agents</u></a>. Cloudflare’s composable AI architecture has all the primitives that enable AI applications to have real time communications, persist state, execute long-running tasks, and repeat them on a schedule. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2M1dOiI89ecQAb1y0SJ57E/dcc98c263ea9503aa0aacdf69326fa9d/2.png" />
          </figure><p><b>Protect and control</b>: Once your application is deployed, be it directly on Cloudflare, using Workers AI, or running on your own infrastructure (cloud or on premise), Cloudflare’s <a href="https://developers.cloudflare.com/ai-gateway/"><u>AI Gateway</u></a> lets you gain visibility into the cost, usage, latency, and overall performance of the application.</p><p>Additionally, <a href="https://blog.cloudflare.com/take-control-of-public-ai-application-security-with-cloudflare-firewall-for-ai/"><u>Firewall for AI</u></a> lets you layer security on top by automatically ensuring every prompt is clean from injection, and that personally identifiable information (PII) is neither submitted to nor (coming soon) extracted from, the application.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4dDiUMSKDoqyrPgzjiHfkx/22a2a9e159f8efcbf2b2a43f9bdf2a9b/3.png" />
          </figure>
    <div>
      <h3>For security teams</h3>
      <a href="#for-security-teams">
        
      </a>
    </div>
    <p>Security teams have a growing new challenge: ensure AI applications are used securely, both in regard to internal usage by employees, as well as by users of externally-facing AI applications the business is responsible for. Ensuring PII data is handled correctly is also a growing major concern for CISOs.</p><p><b>Discover applications: </b>You can’t protect what you don’t know about. Firewall for AI’s discovery capability lets security teams find AI applications that are being used within the organization without the need to perform extensive surveys.</p><p><b>Control PII flow and access: </b>Once discovered, via Firewall for AI or other means, security teams can leverage <a href="https://www.cloudflare.com/learning/access-management/what-is-ztna/"><u>Zero Trust Network Access (ZTNA)</u></a> to ensure only authorized employees are accessing the correct applications. Additionally, using Firewall for AI, they can ensure that, even if authorised, neither employees nor potentially external users, are submitting or extracting personally identifiable information (PII) to/from the application.</p><p><b>Protect against exploits: </b>Malicious users are targeting AI applications with novel attack vectors, as these applications are often connected to internal data stores. With Firewall for AI and the broader Application Security portfolio, you can protect against a wide number of exploits highlighted in the <a href="https://genai.owasp.org/resource/owasp-top-10-for-llm-applications-2025/"><u>OWASP Top 10 for LLM applications</u></a>, including, but not limited to, prompt injection, sensitive information disclosure, and improper output handling.</p><p><b>Safeguarding conversations: </b>With <a href="https://blog.cloudflare.com/guardrails-in-ai-gateway/"><u>Llama Guard</u></a> integrated into both AI Gateway and Firewall for AI, you can ensure both input and output of your AI application is not toxic, and follows topic and sentiment rules based on your internal business policies.</p>
    <div>
      <h3>For content creators</h3>
      <a href="#for-content-creators">
        
      </a>
    </div>
    <p>The advent of AI is arguably putting content creators at risk, with sophisticated LLM models now generating both text, images, and videos of high quality. <a href="https://blog.cloudflare.com/declaring-your-aindependence-block-ai-bots-scrapers-and-crawlers-with-a-single-click/"><u>We’ve blogged in the past about AI Independence, our approach to safeguarding content creators</u></a>, for both individuals and businesses. If you fall in this category, we have the right tools for you too.</p><p><b>Observe who is accessing your content:</b> With our <a href="https://blog.cloudflare.com/cloudflare-ai-audit-control-ai-content-crawlers/"><u>AI Crawl Control </u><i><u>(formerly AI Audit</u></i><u>)</u></a>, you gain visibility (who, what, where and when) into the AI platforms crawling your site to retrieve content to use for AI training data. We are constantly classifying and adding new vendors as they create new crawlers.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6s9WmTy7EQyOF6mCZd6KTc/1ba40dd811bb81de26da04155655e6d8/4.png" />
          </figure><p><b>Block access: </b>If AI crawlers do not follow robots.txt or other relevant standards, or are potentially unwanted, you can <a href="https://www.cloudflare.com/learning/ai/how-to-block-ai-crawlers/">block access outright</a>. We’ve <a href="https://blog.cloudflare.com/declaring-your-aindependence-block-ai-bots-scrapers-and-crawlers-with-a-single-click/"><u>provided a simple “one click” button</u></a> for customers using Cloudflare on our self-serve plans to protect their website. Larger organizations can build fine tune rules using our <a href="https://www.cloudflare.com/en-gb/application-services/products/bot-management/"><u>Bot Management</u></a> solution allowing them to target individual bots and create custom filters with ease.</p>
    <div>
      <h3>Cloudflare for AI: making AI security simple</h3>
      <a href="#cloudflare-for-ai-making-ai-security-simple">
        
      </a>
    </div>
    <p>If you are using Cloudflare already, or the <a href="https://www.cloudflare.com/ai-security/">deployment and security of AI applications</a> is top of mind, <a href="https://www.cloudflare.com/lp/cloudflare-for-ai/"><u>reach out</u></a>, and we can help guide you through our suite of AI tools to find the one that matches your needs.</p><p>Ensuring AI is scalable, <a href="https://www.cloudflare.com/learning/ai/what-is-ai-security/">safe</a> and resilient, is a natural extension of Cloudflare’s mission, given so much of our success relies on a safe Internet.</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Security]]></category>
            <guid isPermaLink="false">7lPwwGmoPaSddtdNRcq4Wv</guid>
            <dc:creator>Michael Tremante</dc:creator>
        </item>
        <item>
            <title><![CDATA[Improved Bot Management flexibility and visibility with new high-precision heuristics]]></title>
            <link>https://blog.cloudflare.com/bots-heuristics/</link>
            <pubDate>Wed, 19 Mar 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ By building and integrating a new heuristics framework into the Cloudflare Ruleset Engine, we now have a more flexible system to write rules and deploy new releases rapidly. ]]></description>
            <content:encoded><![CDATA[ <p>Within the Cloudflare Application Security team, every <a href="https://www.cloudflare.com/learning/ai/what-is-machine-learning/"><u>machine learning</u></a> model we use is underpinned by a rich set of static rules that serve as a ground truth and a baseline comparison for how our models are performing. These are called heuristics. Our Bot Management heuristics engine has served as an important part of eight global <a href="https://developers.cloudflare.com/bots/concepts/bot-score/#machine-learning"><u>machine learning (ML) models</u></a>, but we needed a more expressive engine to increase our accuracy. In this post, we’ll review how we solved this by moving our heuristics to the Cloudflare <a href="https://developers.cloudflare.com/ruleset-engine/"><u>Ruleset Engine</u></a>. Not only did this provide the platform we needed to write more nuanced rules, it made our platform simpler and safer, and provided <a href="https://www.cloudflare.com/application-services/products/bot-management/"><u>Bot Management</u></a> customers more flexibility and visibility into their bot traffic.   </p>
    <div>
      <h3>Bot detection via simple heuristics</h3>
      <a href="#bot-detection-via-simple-heuristics">
        
      </a>
    </div>
    <p>In Cloudflare’s bot detection, we build heuristics from attributes like software library fingerprints, HTTP request characteristics, and internal threat intelligence. Heuristics serve three separate purposes for bot detection: </p><ol><li><p>Bot identification: If traffic matches a heuristic, we can identify the traffic as definitely automated traffic (with a <a href="https://developers.cloudflare.com/bots/concepts/bot-score/"><u>bot score</u></a> of 1) without the need of a machine learning model. </p></li><li><p>Train ML models: When traffic matches our heuristics, we create labelled datasets of bot traffic to train new models. We’ll use many different sources of labelled bot traffic to train a new model, but our heuristics datasets are one of the highest confidence datasets available to us.   </p></li><li><p>Validate models: We benchmark any new model candidate’s performance against our heuristic detections (among many other checks) to make sure it meets a required level of accuracy.</p></li></ol><p>While the existing heuristics engine has worked very well for us, as bots evolved we needed the flexibility to write increasingly complex rules. Unfortunately, such rules were not easily supported in the old engine. Customers have also been asking for more details about which specific heuristic caught a request, and for the flexibility to enforce different policies per heuristic ID.  We found that by building a new heuristics framework integrated into the Cloudflare Ruleset Engine, we could build a more flexible system to write rules and give Bot Management customers the granular explainability and control they were asking for. </p>
    <div>
      <h3>The need for more efficient, precise rules</h3>
      <a href="#the-need-for-more-efficient-precise-rules">
        
      </a>
    </div>
    <p>In our previous heuristics engine, we wrote rules in <a href="https://www.lua.org/"><u>Lua</u></a> as part of our <a href="https://openresty.org/"><u>openresty</u></a>-based reverse proxy. The Lua-based engine was limited to a very small number of characteristics in a rule because of the high engineering cost we observed with adding more complexity.</p><p>With Lua, we would write fairly simple logic to match on specific characteristics of a request (i.e. user agent). Creating new heuristics of an existing class was fairly straight forward. All we’d need to do is define another instance of the existing class in our database. However, if we observed malicious traffic that required more than two characteristics (as a simple example, user-agent and <a href="https://en.wikipedia.org/wiki/Autonomous_system_(Internet)"><u>ASN</u></a>) to identify, we’d need to create bespoke logic for detections. Because our Lua heuristics engine was bundled with the code that ran ML models and other important logic, all changes had to go through the same review and release process. If we identified malicious traffic that needed a new heuristic class, and we were also blocked by pending changes in the codebase, we’d be forced to either wait or rollback the changes. If we’re writing a new rule for an “under attack” scenario, every extra minute it takes to deploy a new rule can mean an unacceptable impact to our customer’s business. </p><p>More critical than time to deploy is the complexity that the heuristics engine supports. The old heuristics engine only supported using specific request attributes when creating a new rule. As bots became more sophisticated, we found we had to reject an increasing number of new heuristic candidates because we weren’t able to write precise enough rules. For example, we found a <a href="https://go.dev/"><u>Golang</u></a> TLS fingerprint frequently used by bots and by a small number of corporate VPNs. We couldn’t block the bots without also stopping the legitimate VPN usage as well, because the old heuristics platform lacked the flexibility to quickly compile sufficiently nuanced rules. Luckily, we already had the perfect solution with Cloudflare Ruleset Engine. </p>
    <div>
      <h3>Our new heuristics engine</h3>
      <a href="#our-new-heuristics-engine">
        
      </a>
    </div>
    <p>The Ruleset Engine is familiar to anyone who has written a WAF rule, Load Balancing rule, or Transform rule, <a href="https://blog.cloudflare.com/announcing-firewall-rules/"><u>just to name a few</u></a>. For Bot Management, the Wireshark-inspired syntax allows us to quickly write heuristics with much greater flexibility to vastly improve accuracy. We can write a rule in <a href="https://yaml.org/"><u>YAML</u></a> that includes arbitrary sub-conditions and inherit the same framework the WAF team uses to both ensure any new rule undergoes a rigorous testing process with the ability to rapidly release new rules to stop attacks in real-time. </p><p>Writing heuristics on the Cloudflare Ruleset Engine allows our engineers and analysts to write new rules in an easy to understand YAML syntax. This is critical to supporting a rapid response in under attack scenarios, especially as we support greater rule complexity. Here’s a simple rule using the new engine, to detect empty user-agents restricted to a specific JA4 fingerprint (right), compared to the empty user-agent detection in the old Lua based system (left): </p><table><tr><td><p><b>Old</b></p></td><td><p><b>New</b></p></td></tr><tr><td><p><code>local _M = {}</code></p><p><code>local EmptyUserAgentHeuristic = {</code></p><p><code>   heuristic = {},</code></p><p><code>}</code></p><p><code>EmptyUserAgentHeuristic.__index = EmptyUserAgentHeuristic</code></p><p><code>--- Creates and returns empty user agent heuristic</code></p><p><code>-- @param params table contains parameters injected into EmptyUserAgentHeuristic</code></p><p><code>-- @return EmptyUserAgentHeuristic table</code></p><p><code>function _M.new(params)</code></p><p><code>   return setmetatable(params, EmptyUserAgentHeuristic)</code></p><p><code>end</code></p><p><code>--- Adds heuristic to be used for inference in `detect` method</code></p><p><code>-- @param heuristic schema.Heuristic table</code></p><p><code>function EmptyUserAgentHeuristic:add(heuristic)</code></p><p><code>   self.heuristic = heuristic</code></p><p><code>end</code></p><p><code>--- Detect runs empty user agent heuristic detection</code></p><p><code>-- @param ctx context of request</code></p><p><code>-- @return schema.Heuristic table on successful detection or nil otherwise</code></p><p><code>function EmptyUserAgentHeuristic:detect(ctx)</code></p><p><code>   local ua = ctx.user_agent</code></p><p><code>   if not ua or ua == '' then</code></p><p><code>      return self.heuristic</code></p><p><code>   end</code></p><p><code>end</code></p><p><code>return _M</code></p></td><td><p><code>ref: empty-user-agent</code></p><p><code>      description: Empty or missing </code></p><p><code>User-Agent header</code></p><p><code>      action: add_bot_detection</code></p><p><code>      action_parameters:</code></p><p><code>        active_mode: false</code></p><p><code>      expression: http.user_agent eq </code></p><p><code>"" and cf.bot_management.ja4 = "t13d1516h2_8daaf6152771_b186095e22b6"</code></p></td></tr></table><p>The Golang heuristic that captured corporate proxy traffic as well (mentioned above) was one of the first to migrate to the new Ruleset engine. Before the migration, traffic matching on this heuristic had a false positive rate of 0.01%. While that sounds like a very small number, this means for every million bots we block, 100 real users saw a Cloudflare challenge page unnecessarily. At Cloudflare scale, even small issues can have real, negative impact.</p><p>When we analyzed the traffic caught by this heuristic rule in depth, we saw the vast majority of attack traffic came from a small number of abusive networks. After narrowing the definition of the heuristic to flag the Golang fingerprint only when it’s sourced by the abusive networks, the rule now has a false positive rate of 0.0001% (One out of 1 million).  Updating the heuristic to include the network context improved our accuracy, while still blocking millions of bots every week and giving us plenty of training data for our bot detection models. Because this heuristic is now more accurate, newer ML models make more accurate decisions on what’s a bot and what isn’t.</p>
    <div>
      <h3>New visibility and flexibility for Bot Management customers </h3>
      <a href="#new-visibility-and-flexibility-for-bot-management-customers">
        
      </a>
    </div>
    <p>While the new heuristics engine provides more accurate detections for all customers and a better experience for our analysts, moving to the Cloudflare Ruleset Engine also allows us to deliver new functionality for Enterprise Bot Management customers, specifically by offering more visibility. This new visibility is via a new field for Bot Management customers called Bot Detection IDs. Every heuristic we use includes a unique Bot Detection ID. These are visible to Bot Management customers in analytics, logs, and firewall events, and they can be used in the firewall to write precise rules for individual bots. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3cYXHw8tFUjdJQGm93gFcE/0a3f6ab89a70410ebb7dd2c6f4f3a677/1.png" />
          </figure>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/9d7L1r7yN9AEhO26H7SgQ/434f0f934dd4f4498a8d13e85a7660ae/2.png" />
          </figure><p>Detections also include a specific tag describing the class of heuristic. Customers see these plotted over time in their analytics. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2UlkGQ070UWsmU76IXYqDd/6bca8f28959a8fe8f3013792a17b348a/image4.png" />
          </figure><p>To illustrate how this data can help give customers visibility into why we blocked a request, here’s an example request flagged by Bot Management (with the IP address, ASN, and country changed):</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/3i6k9ejsBVwlbXUrZFIFJG/4c9cddd11d9f7a8ddf10eb5ff30a027b/4.png" />
          </figure><p>Before, just seeing that our heuristics gave the request a score of 1 was not very helpful in understanding why it was flagged as a bot. Adding our Detection IDs to Firewall Events helps to paint a better picture for customers that we’ve identified this request as a bot because that traffic used an empty user-agent. </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5UQd20VnXCnIav1skHiX6i/18e0cf01106601ae7faf18be50d43365/5.png" />
          </figure><p>In addition to Analytics and Firewall Events, Bot Detection IDs are now available for Bot Management customers to use in Custom Rules, Rate Limiting Rules, Transform Rules, and Workers. </p>
    <div>
      <h4>Account takeover detection IDs</h4>
      <a href="#account-takeover-detection-ids">
        
      </a>
    </div>
    <p>One way we’re focused on improving Bot Management for our customers is by surfacing more attack-specific detections. During Birthday Week, we <a href="https://blog.cloudflare.com/a-safer-internet-with-cloudflare/"><u>launched Leaked Credentials Check</u></a> for all customers so that security teams could help <a href="https://www.cloudflare.com/zero-trust/solutions/account-takeover-prevention/"><u>prevent account takeover (ATO) attacks</u></a> by identifying accounts at risk due to leaked credentials. We’ve now added two more detections that can help Bot Management enterprise customers identify suspicious login activity via specific <a href="https://developers.cloudflare.com/bots/concepts/detection-ids/#account-takeover-detections"><u>detection IDs</u></a> that monitor login attempts and failures on the zone. These detection IDs are not currently affecting the bot score, but will begin to later in 2025. Already, they can help many customers detect more account takeover events now.</p><p>Detection ID <b>201326592 </b>monitors traffic on a customer website and looks for an anomalous rise in login failures (usually associated with brute force attacks), and ID <b>201326593 </b>looks for an anomalous rise in login attempts (usually associated with credential stuffing). </p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4a2LGgB1bXGwFgHQEKFSI9/ff4194a6a470e466274f7b7c51e9dc18/6.png" />
          </figure>
    <div>
      <h3>Protect your applications</h3>
      <a href="#protect-your-applications">
        
      </a>
    </div>
    <p>If you are a Bot Management customer, log in and head over to the Cloudflare dashboard and take a look in Security Analytics for bot detection IDs <code>201326592</code> and <code>201326593</code>.</p><p>These will highlight ATO attempts targeting your site. If you spot anything suspicious, or would like to be protected against future attacks, create a rule that uses these detections to keep your application safe.</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Bots]]></category>
            <category><![CDATA[Bot Management]]></category>
            <category><![CDATA[Application Security]]></category>
            <category><![CDATA[Machine Learning]]></category>
            <category><![CDATA[Heuristics]]></category>
            <category><![CDATA[Edge Rules]]></category>
            <category><![CDATA[Security]]></category>
            <guid isPermaLink="false">4IkgXzyemEEsN7A6Cd18hb</guid>
            <dc:creator>Curtis Lowder</dc:creator>
            <dc:creator>Brian Mitchell</dc:creator>
            <dc:creator>Adam Martinetti</dc:creator>
        </item>
        <item>
            <title><![CDATA[Take control of public AI application security with Cloudflare's Firewall for AI]]></title>
            <link>https://blog.cloudflare.com/take-control-of-public-ai-application-security-with-cloudflare-firewall-for-ai/</link>
            <pubDate>Wed, 19 Mar 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ Firewall for AI discovers and protects your public LLM-powered applications, and is seamlessly integrated with Cloudflare WAF. Join the beta now and take control of your generative AI security. ]]></description>
            <content:encoded><![CDATA[ <p>Imagine building an LLM-powered assistant trained on your developer documentation and some internal guides to quickly help customers, reduce support workload, and improve user experience. Sounds great, right? But what if sensitive data, such as employee details or internal discussions, is included in the data used to train the LLM? Attackers could manipulate the assistant into exposing sensitive data or exploit it for social engineering attacks, where they deceive individuals or systems into revealing confidential details, or use it for targeted phishing attacks. Suddenly, your helpful AI tool turns into a serious security liability. </p>
    <div>
      <h3>Introducing Firewall for AI: the easiest way to discover and protect LLM-powered apps</h3>
      <a href="#introducing-firewall-for-ai-the-easiest-way-to-discover-and-protect-llm-powered-apps">
        
      </a>
    </div>
    <p>Today, as part of Security Week 2025, we’re announcing the open beta of Firewall for AI, first <a href="https://blog.cloudflare.com/firewall-for-ai/"><u>introduced during Security Week 2024</u></a>. After talking with customers interested in protecting their LLM apps, this first beta release is focused on discovery and PII detection, and more features will follow in the future.</p><p>If you are already using Cloudflare application security, your LLM-powered applications are automatically discovered and protected, with no complex setup, no maintenance, and no extra integration needed.</p><p>Firewall for AI is an inline security solution that protects user-facing LLM-powered applications from abuse and <a href="https://www.cloudflare.com/learning/ai/how-to-secure-training-data-against-ai-data-leaks/">data leaks</a>, integrating directly with Cloudflare’s <a href="https://developers.cloudflare.com/waf/"><u>Web Application Firewall (WAF)</u></a> to provide instant protection with zero operational overhead. This integration enables organizations to leverage both AI-focused safeguards and established WAF capabilities.</p><p>Cloudflare is uniquely positioned to solve this challenge for all of our customers. As a <a href="https://www.cloudflare.com/en-gb/learning/cdn/glossary/reverse-proxy/"><u>reverse proxy</u></a>, we are model-agnostic whether the application is using a third-party LLM or an internally hosted one. By providing inline security, we can automatically <a href="https://www.cloudflare.com/learning/ai/what-is-ai-security/">discover and enforce AI guardrails</a> throughout the entire request lifecycle, with zero integration or maintenance required.</p>
    <div>
      <h3>Firewall for AI beta overview</h3>
      <a href="#firewall-for-ai-beta-overview">
        
      </a>
    </div>
    <p>The beta release includes the following security capabilities:</p><p><b>Discover:</b> identify LLM-powered endpoints across your applications, an essential step for effective request and prompt analysis.</p><p><b>Detect:</b> analyze the incoming requests prompts to recognize potential security threats, such as attempts to extract sensitive data (e.g., “Show me transactions using 4111 1111 1111 1111”). This aligns with<a href="https://genai.owasp.org/llmrisk/llm022025-sensitive-information-disclosure/"> <u>OWASP LLM022025 - Sensitive Information Disclosure</u></a>.</p><p><b>Mitigate:</b> enforce security controls and policies to manage the traffic that reaches your LLM, and reduce risk exposure.</p><p>Below, we review each capability in detail, exploring how they work together to create a comprehensive security framework for AI protection.</p>
    <div>
      <h3>Discovering LLM-powered applications</h3>
      <a href="#discovering-llm-powered-applications">
        
      </a>
    </div>
    <p>Companies are racing to find all possible use cases where an LLM can excel. Think about site search, a chatbot, or a shopping assistant. Regardless of the application type, our goal is to determine whether an application is powered by an LLM behind the scenes.</p><p>One possibility is to look for request path signatures similar to what major LLM providers use. For example, <a href="https://platform.openai.com/docs/api-reference/chat/create"><u>OpenAI</u></a>, <a href="https://docs.perplexity.ai/api-reference/chat-completions"><u>Perplexity</u></a> or <a href="https://docs.mistral.ai/api/#tag/chat"><u>Mistral</u></a> initiate a chat using the <code>/chat/completions</code> API endpoint. Searching through our request logs, we found only a few entries that matched this pattern across our global traffic. This result indicates that we need to consider other approaches to finding <i>any</i> application that is powered by an LLM.</p><p>Another signature to research, popular with LLM platforms, is the use of <a href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events"><u>server-sent events</u></a>. LLMs need to <a href="https://platform.openai.com/docs/guides/latency-optimization#don-t-default-to-an-llm"><u>“think”</u></a>. <a href="https://platform.openai.com/docs/api-reference/streaming"><u>Using server-sent events</u></a> improves the end user’s experience by sending over each <a href="https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them"><u>token</u></a> as soon as it is ready, creating the perception that an LLM is “thinking” like a human being. Matching on requests of server-sent events is straightforward using the response header content type of <code>text/event-stream</code>. This approach expands the coverage further, but does not yet cover the <a href="https://stackoverflow.blog/2022/06/02/a-beginners-guide-to-json-the-data-format-for-the-internet/"><u>majority of applications</u></a> that are using JSON format for data exchanges. Continuing the journey, our next focus is on the responses having header content type of <code>application/json</code>.</p><p>No matter how fast LLMs can be optimized to respond, when chatting with major LLMs, we often perceive them to be slow, as we have to wait for them to “think”. By plotting on how much time it takes for the origin server to respond over identified LLM endpoints (blue line) versus the rest (orange line), we can see in the left graph that origins serving LLM endpoints mostly need more than 1 second to respond, while the majority of the rest takes less than 1 second. Would we also see a clear distinction between origin server response body sizes, where the majority of LLM endpoints would respond with smaller sizes because major LLM providers <a href="https://platform.openai.com/docs/guides/safety-best-practices#constrain-user-input-and-limit-output-tokens"><u>limit output tokens</u></a>? Unfortunately not. The right graph shows that LLM response size largely overlaps with non-LLM traffic.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4CkowlKelGlYueNzSrbsGn/f8091d66a6c0eb8b884c7cc6f2a128ab/1.png" />
          </figure><p>By dividing origin response size over origin response duration to calculate an effective bitrate, the distinction is even clearer that 80% of LLM endpoints operate slower than 4 KB/s.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5sJKUnLmWwnTWzUOyWVRKO/c98c8fc32dbafa5d79f21effdfc58f34/2.png" />
          </figure><p>Validating this assumption by using bitrate as a heuristic across Cloudflare’s traffic, we found that roughly 3% of all origin server responses have a bitrate lower than 4 KB/s. Are these responses all powered by LLMs? Our gut feeling tells us that it is unlikely that 3% of origin responses are LLM-powered! </p><p>Among the paths found in the 3% of matching responses, there are few patterns that stand out: 1) GraphQL endpoints, 2) device heartbeat or health check, 3) generators (for QR codes, one time passwords, invoices, etc.). Noticing this gave us the idea to filter out endpoints that have a low variance of response size over time — for instance, invoice generation is mostly based on the same template, while conversations in the LLM context have a higher variance.</p><p>A combination of filtering out known false positive patterns and low variance in response size gives us a satisfying result. These matching endpoints, approximately 30,000 of them, labelled <code>cf-llm</code>, can now be found in API Shield or Web assets, depending on your dashboard’s version, for all customers. Now you can review your endpoints and decide how to best protect them.</p>
    <div>
      <h3>Detecting prompts designed to leak PII</h3>
      <a href="#detecting-prompts-designed-to-leak-pii">
        
      </a>
    </div>
    <p>There are multiple methods to detect PII in LLM prompts. A common method relies on <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions"><u>regular expressions (“regexes”)</u></a>, which is a method we have been using in the WAF for <a href="https://developers.cloudflare.com/waf/managed-rules/reference/sensitive-data-detection/"><u>Sensitive Data Detection</u></a> on the body of the HTTP response from the web server Regexes offer low latency, easy customization, and straightforward implementation. However, regexes alone have limitations when applied to LLM prompts. They require frequent updates to maintain accuracy, and may struggle with more complex or implicit PII, where the information is spread across text rather than a fixed format. </p><p>For example, regexes work well for structured data like credit card numbers and addresses, but struggle with PII is embedded in natural language. For instance, “I just booked a flight using my Chase card, ending in 1111” wouldn’t trigger a regex match as it lacks the expected pattern, even though it reveals a partial credit card number and financial institution.</p><p>To enhance detection, we rely on a <a href="https://www.ibm.com/think/topics/named-entity-recognition"><u>Named Entity Recognition (NER)</u></a> model, which adds a layer of intelligence to complement regex-based detection. NER models analyze text to identify contextual PII data types, such as names, phone numbers, email addresses, and credit card numbers, making detection more flexible and accurate. Cloudflare’s detection utilizes <a href="https://microsoft.github.io/presidio/"><u>Presidio</u></a>, an open-source PII detection framework, to further strengthen this approach.</p>
    <div>
      <h4>Using Workers AI to deploy Presidio</h4>
      <a href="#using-workers-ai-to-deploy-presidio">
        
      </a>
    </div>
    
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/5ruqPkxJBgFCRdsoft1TO1/aa327b069569a0f952c8baea102955b8/3.png" />
          </figure><p>In our design, we leverage Cloudflare <a href="https://developers.cloudflare.com/workers-ai/"><u>Workers AI</u></a> as the fastest way to deploy <a href="https://microsoft.github.io/presidio/"><u>Presidio</u></a>. This integration allows us to process LLM app requests inline, ensuring that sensitive data is flagged before it reaches the model.</p><p>Here’s how it works:</p><p>When Firewall for AI is enabled on an application and an end user sends a request to an LLM-powered application, we pass the request to Cloudflare Workers AI which runs the request through Presidio’s NER-based detection model to identify any potential PII from the available <a href="https://microsoft.github.io/presidio/supported_entities/"><u>entities</u></a>. The output includes metadata like “Was PII found?” and “What type of PII entity?”. This output is then processed in our Firewall for AI module, and handed over to other systems, like <a href="https://developers.cloudflare.com/waf/analytics/security-analytics/"><u>Security Analytics</u></a> for visibility, and the rules like <a href="https://developers.cloudflare.com/waf/custom-rules/"><u>Custom rules</u></a> for enforcement. Custom rules allow customers to take appropriate actions on the requests based on the provided metadata. </p><p>If no terminating action, like blocking, is triggered, the request proceeds to the LLM. Otherwise, it gets blocked or the appropriate action is applied before reaching the origin.</p>
    <div>
      <h3>Integrating AI security into the WAF and Analytics</h3>
      <a href="#integrating-ai-security-into-the-waf-and-analytics">
        
      </a>
    </div>
    <p><a href="https://www.cloudflare.com/ai-security/">Securing AI interactions</a> shouldn't require complex integrations. Firewall for AI is seamlessly built into Cloudflare’s WAF, allowing customers to enforce security policies before prompts reach LLM endpoints. With this integration, there are <a href="https://developers.cloudflare.com/waf/detections/firewall-for-ai/#fields"><u>new fields available</u></a> in Custom and Rate limiting rules. The rules can be used to take immediate action, such as blocking or logging risky prompts in real time.</p><p>For example, security teams can filter LLM traffic to analyze requests containing PII-related prompts. Using Cloudflare’s WAF rules engine, they can create custom security policies tailored to their AI applications.</p><p>Here’s what a rule to block detected PII prompts looks like:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4cvlFU0sia6dZly2LZGG8l/670dbb1ad5068f0fd5d8f4afde9e9e02/4.png" />
          </figure><p>Alternatively, if an organization wants to allow certain PII categories, such as location data, they can create an exception rule:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/wYFkoQyHFoFNwHmKtaaG3/94c7ae78dbabacf5dd8583af9e8eb071/5.png" />
          </figure><p>In addition to the rules, users can gain visibility into LLM interactions, detect potential risks, and enforce security controls using <a href="https://developers.cloudflare.com/waf/analytics/security-analytics/"><u>Security Analytics</u></a> and <a href="https://developers.cloudflare.com/waf/analytics/security-events/"><u>Security Events</u></a>. You can find more details in our <a href="https://developers.cloudflare.com/waf/detections/firewall-for-ai/"><u>documentation</u></a>.</p>
    <div>
      <h3>What's next: token counting, guardrails, and beyond</h3>
      <a href="#whats-next-token-counting-guardrails-and-beyond">
        
      </a>
    </div>
    <p>Beyond PII detection and creating security rules, we’re developing additional capabilities to strengthen AI security for our customers. The next feature we’ll release is token counting, which analyzes prompt structure and length. Customers can use the token count field in Rate Limiting and WAF Custom rules to prevent their users from sending very long prompts, which can impact third party model bills, or allow users to abuse the models. This will be followed by using AI to detect and allow content moderation, which will provide more flexibility in building guardrails in the rules.</p><p>If you're an enterprise customer, join the Firewall for AI beta today! Contact your customer team to start monitoring traffic, building protection rules, and taking control of your LLM traffic.</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Security]]></category>
            <category><![CDATA[LLM]]></category>
            <category><![CDATA[Web Asset Discovery]]></category>
            <guid isPermaLink="false">5XoyHPSrtBH8pPvUJkOXMD</guid>
            <dc:creator>Radwa Radwan</dc:creator>
            <dc:creator>Zhiyuan Zheng</dc:creator>
        </item>
        <item>
            <title><![CDATA[Trapping misbehaving bots in an AI Labyrinth]]></title>
            <link>https://blog.cloudflare.com/ai-labyrinth/</link>
            <pubDate>Wed, 19 Mar 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ How Cloudflare uses generative AI to slow down, confuse, and waste the resources of AI Crawlers and other bots that don’t respect “no crawl” directives. ]]></description>
            <content:encoded><![CDATA[ <p>Today, we’re excited to announce AI Labyrinth, a new mitigation approach that uses AI-generated content to slow down, confuse, and waste the resources of AI Crawlers and other bots that don’t respect “no crawl” directives. When you opt in, Cloudflare will automatically deploy an AI-generated set of linked pages when we detect inappropriate bot activity, without the need for customers to create any custom rules.</p><p>AI Labyrinth is available on an opt-in basis to all customers, including the<a href="https://www.cloudflare.com/plans/free/"> Free plan</a>.</p>
    <div>
      <h3>Using Generative AI as a defensive weapon</h3>
      <a href="#using-generative-ai-as-a-defensive-weapon">
        
      </a>
    </div>
    <p>AI-generated content has exploded, reportedly accounting for <a href="https://www.thetimes.co.uk/article/why-ai-content-everywhere-how-to-detect-l2m2kdx9p"><u>four of the top 20 Facebook posts</u></a> last fall. Additionally, Medium estimates that <a href="https://www.wired.com/story/ai-generated-medium-posts-content-moderation/"><u>47% of all content</u></a> on their platform is AI-generated. Like any newer tool it has both wonderful and <a href="https://www.npr.org/2024/12/24/nx-s1-5235265/how-to-protect-yourself-from-holiday-ai-scams"><u>malicious</u></a> uses.</p><p>At the same time, we’ve also seen an explosion of new crawlers used by AI companies to scrape data for model training. AI Crawlers generate more than 50 billion requests to the Cloudflare network every day, or just under 1% of all web requests we see. While Cloudflare has several tools for <a href="https://www.cloudflare.com/learning/ai/how-to-block-ai-crawlers/"><u>identifying and blocking unauthorized AI crawling</u></a>, we have found that blocking malicious <a href="https://www.cloudflare.com/learning/bots/what-is-a-bot/">bots</a> can alert the attacker that you are on to them, leading to a shift in approach, and a never-ending arms race. So, we wanted to create a new way to thwart these unwanted bots, without letting them know they’ve been thwarted.</p><p>To do this, we decided to use a new offensive tool in the bot creator’s toolset that we haven’t really seen used defensively: AI-generated content. When we detect unauthorized crawling, rather than blocking the request, we will link to a series of AI-generated pages that are convincing enough to entice a crawler to traverse them. But while real looking, this content is not actually the content of the site we are protecting, so the crawler wastes time and resources. </p><p>As an added benefit, AI Labyrinth also acts as a next-generation honeypot. No real human would go four links deep into a maze of AI-generated nonsense. Any visitor that does is very likely to be a bot, so this gives us a brand-new tool to identify and fingerprint bad bots, which we add to our list of known bad actors. Here’s how we do it…</p>
    <div>
      <h3>How we built the labyrinth </h3>
      <a href="#how-we-built-the-labyrinth">
        
      </a>
    </div>
    <p>When AI crawlers follow these links, they waste valuable computational resources processing irrelevant content rather than extracting your legitimate website data. This significantly reduces their ability to gather enough useful information to train their models effectively.</p><p>To generate convincing human-like content, we used <a href="https://developers.cloudflare.com/workers-ai/"><u>Workers AI</u></a> with an open source model to create unique HTML pages on diverse topics. Rather than creating this content on-demand (which could impact performance), we implemented a pre-generation pipeline that sanitizes the content to<a href="https://www.cloudflare.com/learning/security/how-to-prevent-xss-attacks/"> prevent any XSS vulnerabilities</a>, and stores it in <a href="https://www.cloudflare.com/developer-platform/products/r2/">R2</a> for faster retrieval. We found that generating a diverse set of topics first, then creating content for each topic, produced more varied and convincing results. It is important to us that we don’t generate inaccurate content that contributes to the spread of misinformation on the Internet, so the content we generate is real and related to scientific facts, just not relevant or proprietary to the site being crawled.</p><p>This pre-generated content is seamlessly integrated as hidden links on existing pages via our custom HTML transformation process, without disrupting the original structure or content of the page. Each generated page includes appropriate meta directives to protect SEO by preventing search engine indexing. We also ensured that these links remain invisible to human visitors through carefully implemented attributes and styling. To further minimize the impact to regular visitors, we ensured that these links are presented only to suspected AI scrapers, while allowing legitimate users and verified crawlers to browse normally.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2PHSCXVMFipAhGJ5IheXW3/a46aad93f2e60f6d892d4c597a752a58/image4.png" />
          </figure><p><sup><i>A graph of daily requests over time, comparing different categories of AI Crawlers.</i></sup></p><p>What makes this approach particularly effective is its role in our continuously evolving bot detection system. When these links are followed, we know with high confidence that it's automated crawler activity, as human visitors and legitimate browsers would never see or click them. This provides us with a powerful identification mechanism, generating valuable data that feeds into our <a href="https://www.cloudflare.com/learning/ai/what-is-machine-learning/">machine learning models</a>. By analyzing which crawlers are following these hidden pathways, we can identify new bot patterns and signatures that might otherwise go undetected. This proactive approach helps us <a href="https://www.cloudflare.com/learning/ai/how-to-prevent-web-scraping/">stay ahead of AI scrapers</a>, continuously improving our detection capabilities without disrupting the normal browsing experience.</p><p>By building this solution on our developer platform, we've created a system that serves convincing decoy content instantly while maintaining consistent quality - all without impacting your site's performance or user experience.</p>
    <div>
      <h3>How to use AI Labyrinth to stop AI crawlers</h3>
      <a href="#how-to-use-ai-labyrinth-to-stop-ai-crawlers">
        
      </a>
    </div>
    <p>Enabling AI Labyrinth is simple and requires just a single toggle in your Cloudflare dashboard. Navigate to the bot management section within your zone, and toggle the new AI Labyrinth setting to on:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/q1ZQlnnMztSsK8PWD1h0S/ef02f081544dc751f754e9630f17261e/image1.png" />
          </figure>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/61qBVDv0WFh8YzrbVULtxq/13ec46d7651c59454f9fe3754e253b85/image3.png" />
          </figure><p>Once enabled, the AI Labyrinth begins working immediately with no additional configuration needed.</p>
    <div>
      <h3>AI honeypots, created by AI</h3>
      <a href="#ai-honeypots-created-by-ai">
        
      </a>
    </div>
    <p>The core benefit of AI Labyrinth is to confuse and distract bots. However, a secondary benefit is to serve as a next-generation honeypot. In this context, a honeypot is just an invisible link that a website visitor can’t see, but a bot parsing HTML would see and click on, therefore revealing itself to be a bot. Honeypots have been used to catch hackers as early as the late <a href="https://medium.com/@jcart657/the-cuckoos-egg-9b502442ea67"><u>1986 Cuckoo’s Egg incident</u></a>. And in 2004, <a href="https://www.projecthoneypot.org/"><u>Project Honeypot</u></a> was created by Cloudflare founders (prior to founding Cloudflare) to let everyone easily deploy free email honeypots, and receive lists of crawler IPs in exchange for contributing to the database. But as bots have evolved, they now proactively look for honeypot techniques like hidden links, making this approach less effective.</p><p>AI Labyrinth won’t simply add invisible links, but will eventually create whole networks of linked URLs that are much more realistic, and not trivial for automated programs to spot. The content on the pages is obviously content no human would spend time-consuming, but AI bots are programmed to crawl rather deeply to harvest as much data as possible. When bots hit these URLs, we can be confident they aren’t actual humans, and this information is recorded and automatically fed to our machine learning models to help improve our bot identification. This creates a beneficial feedback loop where each scraping attempt helps protect all Cloudflare customers.</p>
    <div>
      <h3>What’s next</h3>
      <a href="#whats-next">
        
      </a>
    </div>
    <p>This is only the first iteration of using generative AI to thwart bots for us. Currently, while the content we generate is convincingly human, it won’t conform to the existing structure of every website. In the future, we’ll continue to work to make these links harder to spot and make them fit seamlessly into the existing structure of the website they’re embedded in. You can help us by opting in now.</p><p>To take the next step in the fight against bots, <a href="https://dash.cloudflare.com/?to=/:account/:zone/security/detections/bot-traffic"><u>opt-in to AI Labyrinth</u></a> today.</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Bots]]></category>
            <category><![CDATA[Bot Management]]></category>
            <category><![CDATA[AI Bots]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Machine Learning]]></category>
            <category><![CDATA[Generative AI]]></category>
            <guid isPermaLink="false">1Zh4fm4BB1S3xuVwfETiTE</guid>
            <dc:creator>Reid Tatoris</dc:creator>
            <dc:creator>Harsh Saxena</dc:creator>
            <dc:creator>Luis Miglietti</dc:creator>
        </item>
        <item>
            <title><![CDATA[An early look at cryptographic watermarks for AI-generated content]]></title>
            <link>https://blog.cloudflare.com/an-early-look-at-cryptographic-watermarks-for-ai-generated-content/</link>
            <pubDate>Wed, 19 Mar 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ It's hard to tell the difference between web content produced by humans and web content produced by AI. We're taking new approach to making AI content distinguishable without impacting performance.  ]]></description>
            <content:encoded><![CDATA[ <p><a href="https://www.cloudflare.com/learning/ai/what-is-generative-ai/">Generative AI</a> is reshaping many aspects of our lives, from how we work and learn, to how we play and interact. Given that it's Security Week, it's a good time to think about some of the unintended consequences of this information revolution and the role that we play in bringing them about.</p><p>Today's web is full of AI-generated content: text, code, <a href="https://www.cloudflare.com/learning/ai/ai-image-generation/">images</a>, audio, and video can all be generated by machines, normally based on a prompt from a human. Some models have become so sophisticated that distinguishing their artifacts — that is, the text, audio, and video they generate — from everything else can be quite difficult, <a href="https://originality.ai/blog/openai-text-classifier-review"><u>even for machines themselves</u></a>. This difficulty creates a number of challenges. On the one hand, those who train and deploy generative AI need to be able to identify AI-created artifacts they scrape from websites in order <a href="https://www.cloudflare.com/learning/ai/how-to-secure-training-data-against-ai-data-leaks/"><u>to avoid polluting their training data</u></a>. On the other hand, the origin of these artifacts may be intentionally misrepresented, creating <a href="https://www.gov.ca.gov/2024/09/19/governor-newsom-signs-bills-to-crack-down-on-sexually-explicit-deepfakes-require-ai-watermarking/"><u>myriad problems</u></a> for society writ large.</p><p>Part of the solution to this problem might be <b>watermarking</b>. The basic idea of watermarking is to modify the training process, the inference process, or both so that an artifact of the model embeds some identifying information of the model from which it originates. This way a model operator, or potentially the consumer of the content themselves, can determine whether some artifact came from the model by checking for the presence of the watermark.</p><p>Watermarking shares many of the same goals as the <a href="https://c2pa.org/"><u>C2PA initiative</u></a>. C2PA seeks to add provenance of media from a variety of sources, not just AI. Think of it as a chain of digital signatures, where each link in the chain corresponds to some modification of the artifact. For example, if you're a Cloudflare customer using <a href="https://www.cloudflare.com/developer-platform/products/cloudflare-images/"><u>Images</u></a> to serve C2PA-tagged content, <a href="https://blog.cloudflare.com/preserve-content-credentials-with-cloudflare-images/"><u>you can opt in to preserve the provenance</u></a> by extending this signature chain, even after the image is compressed on our network.</p><p>The challenge of this approach is that it requires participation by each entity in the chain of custody of the artifact. Watermarking has the potential to make C2PA more robust by preserving the origin of the artifact even after unattributed modification. Whereas the C2PA signature is encoded in an image’s metadata, a watermark is embedded in the pixels of the image itself.</p><p>In this post, we're going to take a look at an emerging paradigm for AI watermarking. Based on cryptography, these new watermarks aim to provide rigorous, mathematical guarantees of quality preservation and robustness to modification of the content. This field is, as of 2025, only a couple of years old, and we don't yet know if it will yield schemes that are practical to deploy. Nevertheless, we believe this is a promising area of research, and we hope this post inspires someone to come up with the next big idea.</p>
    <div>
      <h3>The case for cryptography</h3>
      <a href="#the-case-for-cryptography">
        
      </a>
    </div>
    <p>It's often said that cryptography is necessary but not sufficient for security. In other words, cryptographers make certain assumptions about the state of the system, like that a key is kept secret from the attacker, or that some computational puzzle is hard to solve. When these assumptions hold, a good cryptosystem provides a mathematical proof of security against the class of attacks it is designed to prevent.</p><p>Artifact watermarking usually has three security goals:</p><ol><li><p>Robustness: Users of the model should not be able to easily misrepresent the origin of its artifacts. The watermark should be verifiable even after the artifact is modified to some extent.</p></li><li><p>Undetectability: Watermarking should have negligible impact on the quality of the model output. In particular, watermarked artifacts should be indistinguishable from non-watermarked artifacts of the same model.</p></li><li><p>Unforgeability: It should be impossible for anyone but the model operator to produce watermarked artifacts. No one should be able to convince the model operator that an artifact was generated by the model when it wasn't.</p></li></ol><p>Today's state-of-the-art watermarks, including Google's <a href="https://deepmind.google/technologies/synthid/"><u>SynthID</u></a> and Meta's <a href="https://aidemos.meta.com/videoseal/"><u>Video Seal</u></a>, are often based on <a href="https://www.cloudflare.com/learning/ai/what-is-deep-learning/"><u>deep learning</u></a>. These schemes involve training a <a href="https://www.cloudflare.com/learning/ai/what-is-machine-learning/">machine learning model</a>, typically one with an encoder–decoder architecture where the encoder encodes a signature into an artifact and the decoder decodes the signature:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/wk6vE9ArPOK7EXP2otytf/f847db73272c932ba546d8a6b3176480/1.png" />
          </figure><p><sup><i>Figure 1: Illustration of the process of training an encoder-decoder watermarking model.</i></sup></p><p>The training process involves subjecting the watermarked artifact to a series of known attacks. The more attacks the model thwarts, the higher the model quality. For example, the trainer would alter the artifact in various ways and run the decoder on the outputs: the model scores high if the decoder manages to correctly output the signature most of the time.</p><p>This idea is quite beautiful. It's like a scaled up version of <a href="https://www.cloudflare.com/learning/security/glossary/what-is-penetration-testing/">penetration testing</a>, an essential practice of security engineering whereby the system is subjected to a suite of known attacks until all known vulnerabilities are patched. Of course, there will always be new attack variants or new attack strategies that the model was not trained on and that may evade the model.</p><p>And so ensues the proverbial game of cat-and-mouse that consumes so much time in security engineering. Coping with new attacks on robustness, undetectability, or unforgeability of deep-learning based watermarks requires continual intelligence gathering and re-training of deployed models to keep up with attackers.</p><p>The promise of cryptography is that it helps us break out of these kinds of cat-and-mouse games. Cryptography reduces the attack surface by focusing the attacker's attention on breaking some narrow aspect of the system that is easier to reason about. This might be gaining access to some secret key, or solving some (seemingly unrelated) computational puzzle that is believed to be impossible to solve.</p>
    <div>
      <h3>Pseudorandom codes</h3>
      <a href="#pseudorandom-codes">
        
      </a>
    </div>
    <p>To the best of our knowledge, the first cryptographic AI watermark was proposed by Scott Aaronson <a href="https://scottaaronson.blog/?p=6823"><u>in the summer of 2022 while he was working at OpenAI</u></a>. Tailored specifically for chatbots, Aaronson's simple scheme was both undetectable and unforgeable. However, it was susceptible to some simple attacks on robustness.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4XcSE2infymYTGywob2XlS/b79819f48b58c26a7c1713a89879d412/2.png" />
          </figure><p><sup><i>Figure 2: The "emoji attack": Ask the chatbot to embed a simple pattern in its response, then remove the pattern manually. This is sufficient to remove some cryptographic watermarks from the model output.</i></sup></p><p>In the year or so that followed, other cryptographic watermarks were proposed, all making different trade-offs between detectability and robustness. Two years later, in a paper that appeared at <a href="https://eprint.iacr.org/2024/235"><u>CRYPTO 2024</u></a>, Miranda Christ and Sam Gunn articulated a new framework for watermarks that, if properly instantiated, would provide all three properties simultaneously.</p><p>Along with the prompt provided by the user, generative AI models typically take as input some randomness generated by the model operator. For many such models, it is often possible to run the model "in reverse" such that, given an artifact of the model, one can recover <b>an approximation of</b> the initial randomness used to generate it. We'll see why this is important in a moment.</p><p>The starting point for Christ-Gunn-2024 is a mathematical tool called an <a href="https://en.wikipedia.org/wiki/Error_correction_code"><u>error correcting code</u></a>. These codes are normally used to transmit messages over noisy channels and are found in just about every system we rely on, including fiber optics, satellites, the data bus on your motherboard, and even quantum computers.</p><p>To transmit a message <code>m</code>, one first encodes it into a <b>codeword</b> <code>c=encode(m)</code>. Then the receiver attempts to decode the codeword as <code>decode(c)</code>. Error correcting codes are designed to tolerate some fraction of the codeword bits being flipped: if too many bits are flipped, then decoding will fail.</p><p>Now, ignoring undetectability and unforgeability for a moment, we can use an error correcting code to make a robust watermark as follows:</p><ol><li><p>Generate the initial randomness.</p></li><li><p>Embed a codeword <code>c=encode(m)</code> into the randomness in some manner, by overwriting bits of randomness with bits of <code>c</code>. The message <code>m</code> can be whatever we want, for example a short string identifying the version of our model.</p></li><li><p>Run the model with the modified randomness.</p></li></ol><p>To verify the watermark, we:</p><ol><li><p>Run the model "in reverse" on the artifact, obtaining an approximation of the initial randomness.</p></li><li><p>Extract the codeword <code>c</code><code><sup>*</sup></code> from the randomness.</p></li><li><p>If <code>decode(c</code><code><sup>*</sup></code><code>) </code>succeeds, then the watermark is present.</p></li></ol><p>Why does this work? Since c is a codeword, we can verify the watermark even if our approximation of the initial randomness isn't perfect. Some of the bits will be flipped, but the error correcting property of the code allows us to compensate for this. In fact, this is also what makes the watermark robust, since we can also tolerate bit flips caused by an attacker munging the artifact. Of course, the better our approximation of the initial randomness, the more robust our watermark will be, since we'll be able to correct for more bit flips.</p><p>To see why this watermark is detectable, notice that overwriting bits of the randomness with a fixed codeword (<code>c=encode(m)</code>) biases the randomness and thereby the output of the model. Thus, the distribution of watermarked artifacts will be slightly different from unwatermarked artifacts, perhaps even noticeably so. This watermark is also forgeable, since the encoding algorithm is public and can be run by anyone.</p><p>The challenge then is to design error-correcting codes for which codewords look random, and generating codewords requires knowledge of a secret key held by the model operator. Christ-Gunn-2024 names these <b>pseudorandom error-correcting codes</b>, or simply <b>pseudorandom codes</b>.</p><p>A pseudorandom code consists of three algorithms:</p><ul><li><p><code>k = key_gen()</code>: the key generation algorithm. Let's call <code>k</code> the <b>watermarking key</b>.</p></li><li><p><code>c = encode(k,m)</code>: the encoding algorithm takes in a message <code>m</code> and outputs a codeword <code>c</code>.</p></li><li><p><code>m = decode(k,c)</code>: the decoding algorithm takes in a codeword <code>c</code> and outputs the underlying message <code>m</code>, or an indication that decoding failed.</p></li></ul><p>The term "pseudorandom" refers to the fact that codewords aren't technically random bit strings. Intuitively, an attacker can distinguish a codeword from a random string if it manages to guess the watermarking key. Thus, our goal is to choose parameters for the code such that distinguishing codewords from random — for example, by guessing the watermarking key — is hard for any computationally bounded attacker.</p><p>To use a pseudorandom code for watermarking, the operator first generates a watermarking key <code>k</code>. Then each time it gets a prompt from a user, it generates the initial randomness, embeds <code>c=encode(k,m)</code> into the initial randomness, and runs the model. To verify the watermark, the operator runs the model in reverse to get the inverted randomness, extracts the inverted codeword, <code>c</code><code><sup>*</sup></code>, and computes <code>decode(k,c</code><code><sup>*</sup></code><code>)</code>: if decoding succeeds, then the watermark is present.</p><p>In order for this watermark to be undetectable, we need to pick an embedding of the codeword that doesn't change the distribution of the initial randomness. The details of this embedding depend on the model. Let's take a look at <a href="https://en.wikipedia.org/wiki/Stable_Diffusion"><u>Stable Diffusion</u></a> as an example.</p>
    <div>
      <h3>A watermark for Stable Diffusion</h3>
      <a href="#a-watermark-for-stable-diffusion">
        
      </a>
    </div>
    <p><a href="https://en.wikipedia.org/wiki/Stable_Diffusion"><u>Stable Diffusion</u></a> is a model used for image generation that takes as input a tensor of normally distributed floating point numbers called a <b>latent</b>. The model uses the user's prompt to "denoise" the latent tensor over a number of iterations, then converts the final version of the latent to an image.</p>
    <div>
      <h4>Approximating the initial latent</h4>
      <a href="#approximating-the-initial-latent">
        
      </a>
    </div>
    <p>Diffusion inversion is an iterative process that returns an exact or approximate initial latent by reversing the sampling process that generated an image. Inversion for text to image diffusion models is a relatively new area of research. A common application of diffusion inversion is <a href="https://arxiv.org/abs/2211.09794"><u>editing images by text prompts</u></a>.</p><p><a href="https://arxiv.org/abs/2010.02502"><u>Denoising Diffusion Implicit Models (DDIMs)</u></a> are iterative, implicit probabilistic models that can generate high quality images using a faster sampling process than other approaches, as it only requires a relatively small number of timesteps to generate a sample. This makes <a href="https://arxiv.org/abs/2211.09794"><u>DDIM Inversion</u></a> a popular inversion technique because it is computationally fast, as it requires only a few timesteps to return an approximate initial latent of a generated image. Despite its popularity, it has some known limitations and can be <a href="https://arxiv.org/abs/2312.12540v5"><u>problematic to use for tasks where exact image reproduction is required</u></a>. These limitations have led researchers to explore techniques that produce <a href="https://arxiv.org/abs/2311.18387"><u>exact initial latents</u></a>. However, since watermarks based on pseudorandom codes can tolerate errors, it's worth investigating whether DDIM Inversion suffices for our purposes.</p><p>Before we can generate an approximate initial latent, we need a generated image. To do this we use a pretrained Stable Diffusion model that uses a DDIM scheduler. The scheduler performs the “denoising” process that generates an image from a random noise seed (initial latent). By default, the pipeline computes random latents; when embedding a watermark we will generate this latent ourselves as described in the next section. The Stable Diffusion pipelines in the code snippets below sets the number of inference steps to 50. This parameter controls the number of steps the denoising process takes. 50 steps provides a nice balance between speed and image quality.</p>
            <pre><code>from stable_diffusion.utils import build_stable_diffusion_pipeline
from stable_diffusion.schedulers import ddim_scheduler

# Instantiate Stable Diffusion pipeline
model_cache_path = './model_cache'
model = 'stabilityai/stable-diffusion-2-1-base'
scheduler, _ = ddim_scheduler()
pipe, device = build_stable_diffusion_pipeline(model, model_cache_path, scheduler)

# Generate image
prompt = 'grainy photo of a UFO at night'
image, _ = pipe(prompt, num_inference_steps=50, return_dict=False)</code></pre>
            <p>To compute the approximate initial latent for the image we generated, we run the sampling process backwards. We could include the prompt, but in the case of verifying a watermark, we will usually not know the initial prompt, so we instead just set it to the empty string:</p>
            <pre><code>from PIL import Image
from stable_diffusion.utils import build_stable_diffusion_pipeline,   
                                   convert_pil_to_latents
from stable_diffusion.schedulers import ddim_inverse_scheduler

# Load image
img = Image.open(image_path)

# Instantiate Stable Diffusion pipeline with DDIM Inverse scheduler
model_cache_path = './model_cache'
model = 'stabilityai/stable-diffusion-2-1-base'
scheduler, _= ddim_inverse_scheduler()
pipe, _ = build_stable_diffusion_pipeline(model, model_cache_path, scheduler)

# Convert the input image to latent space
image_latent = convert_pil_to_latents(pipe, img)

# Invert the sampling process that generated the image with an empty prompt
inverted_latent, _ = pipe('', output_type='latent', latents=image_latent,  
                          num_inference_steps=50, return_dict=False)</code></pre>
            
    <div>
      <h4>Embedding the code</h4>
      <a href="#embedding-the-code">
        
      </a>
    </div>
    <p>The initial latent used for stable diffusion consists of a bunch of floating point numbers, each independently and <a href="https://en.wikipedia.org/wiki/Normal_distribution"><u>normally</u></a> distributed with a mean of zero.</p><p>The following observation is from a <a href="https://arxiv.org/pdf/2410.07369"><u>recent evaluation</u></a> of the watermark of Christ and Gunn for stable diffusion. (There they used a more sophisticated but expensive inversion method than DDIM.) Observe that the probability that each number is negative is equal to the probability that the number is positive. Likewise, if the code is indeed pseudorandom, then each bit of the codeword is computationally indistinguishable from a bit that is one with probability ½ and zero with probability ½.</p><p>To embed the codeword in the latent, we just set the sign of each number according to the corresponding bit of the codeword:</p>
            <pre><code>from stable_diffusion.utils import build_stable_diffusion_pipeline
from stable_diffusion.schedulers import ddim_scheduler
import numpy as np
import torch

# Generate a normally distributed latent. For the default image
# size of 512x512 pixels, the latent shape is `[1, 4, 64, 64]`.
initial_latent = np.abs(np.random.randn(*LATENTS_SHAPE))

with np.nditer(initial_latent, op_flags=['readwrite']) as it:
    	codeword = encode(k, m)
    	for (i, x) in enumerate(it):
             # `codeword[i]` is a `bool` representing the `i`-th bit of
             # the codeword.
             x *= 1 if codeword[i] else -1

watermarked_latent = torch.from_numpy(initial_latent).to(dtype=torch.float32)

# Instantiate Stable Diffusion pipeline
model_cache_path = './model_cache'
model = 'stabilityai/stable-diffusion-2-1-base'
scheduler, _ = ddim_scheduler()
pipe, _ = build_stable_diffusion_pipeline(model, model_cache_path, scheduler)

# Generate watermarked image
prompt = 'grainy photo of a UFO at night'
watermarked_image, _ = pipe(prompt, num_inference_steps=50,
                                              latents=watermarked_latent, 
                                              return_dict=False)</code></pre>
            <p>To verify this watermark, we compute the inverted latent, extract the codeword, and attempt to decode:</p>
            <pre><code>from PIL import Image
from stable_diffusion.utils import build_stable_diffusion_pipeline,   
                                   convert_pil_to_latents
from stable_diffusion.schedulers import ddim_inverse_scheduler
import numpy as np

# Load image
img = Image.open(image_path)

# Instantiate Stable Diffusion pipeline with DDIM Inverse scheduler
model_cache_path = './model_cache'
model = 'stabilityai/stable-diffusion-2-1-base'
scheduler, _ = ddim_inverse_scheduler()
pipe, _ = build_stable_diffusion_pipeline(model, model_cache_path, scheduler)

# Convert the input image to latent space
image_latent = convert_pil_to_latents(pipe, img)

# Invert the sampling process that generated the image
inverted_latent, _ = pipe('', output_type='latent', latents=image_latent,     
                         num_inference_steps=50, return_dict=False)

watermark_verified = False
with np.nditer(inverted_latent.cpu().numpy()) as it:
    inverted_codeword = []
    for x in it:
         inverted_codeword.append(x &gt; 0)

    if decode(k, inverted_codeword) == m:
         watermark_verified = True</code></pre>
            <p>This should work in theory given the error-correcting properties of the code. But does it work in practice?</p>
    <div>
      <h4>Evaluation</h4>
      <a href="#evaluation">
        
      </a>
    </div>
    <p>A good approximate initial latent is one that is very similar to the original latent that generated an image.  Given our embedding of a codeword into the latent, we define similarity as latents that have a high percentage of overlapping or matching signs.</p><p>To get a feel for this difference, we can visualize it by comparing a generated image to the same image, but with the inverted latent (these images are unwatermarked):</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/ZFAAipEvnp6u79lcQrk5t/0d06e07468c05d707289a322937e9253/1.png" />
          </figure><p><sup><i>Figure 3: Image generated with prompt 'grainy photo of a UFO at night' (left) and the same image generated using the inverted latent (right).</i></sup></p><p>To evaluate how good the approximate latents are for preserving the robustness of watermarks, we randomly sampled 1,000 prompts from the <a href="https://github.com/google-research/parti?tab=readme-ov-file#partiprompts-benchmark"><u>PartiPrompts benchmark dataset</u></a>. For each of these prompts we generated initial latent and inverted latent pairs. We then computed our similarity metric for each pair. We found that on average, 82% of the signs matched for all initial latent and inverted latent pairs, and at least 75% of signs matched for 90% of the pairs.</p><p>We were pleasantly surprised with how accurate the approximation was on average. If 75% of the signs are preserved, then this gives us a decent margin for correcting for errors introduced by an attacker attempting to remove the watermark. Of course a better approximation would give us a better robustness margin. More study is required to fully understand the strengths and limitations of using DDIM Inversion for watermark decoding.</p>
    <div>
      <h3>Candidate pseudorandom codes</h3>
      <a href="#candidate-pseudorandom-codes">
        
      </a>
    </div>
    <p>Now that we have a feel for how to apply pseudorandom codes, let's take a look at how we actually build them. Although the field is barely a year old, we already have a handful of candidates.</p><p>One obvious idea to try is to compose a plain error-correcting code with some cryptographic primitive to make the code pseudorandom. For instance, we might use some standard authenticated encryption scheme, like <a href="https://datatracker.ietf.org/doc/html/rfc8452"><u>AES-GCM-SIV</u></a>, to encrypt <code>m</code>, then apply an error correcting code to the ciphertext. (The watermarking key would be the encryption key.) This "encrypt-then-encode" composition seems natural because encryption schemes are already designed so that their ciphertexts are pseudorandom. Unfortunately, error correcting codes are generally highly structured, and this structure would be betrayed by the codeword, even when applied to a (pseudo)random input.</p><p>The dual composition, "encode-then-encrypt", also doesn't work. If the ciphertext is non-malleable, as in AES-GCM-SIV, then we wouldn't be able to tolerate any number of bit flips. On the other hand, if the ciphertext were malleable, as in <a href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR)"><u>AES-CTR</u></a>, then the attacker would be able to forge codewords by manipulating a known codeword in a targeted manner.</p><p>The strategy of Christ-Gunn-2024 is to modify an existing error-correcting code to make it pseudorandom.</p>
    <div>
      <h4>Pseudorandom LDPC codes</h4>
      <a href="#pseudorandom-ldpc-codes">
        
      </a>
    </div>
    <p>Their starting point is the widely used <a href="https://en.wikipedia.org/wiki/Low-density_parity-check_code"><u>Low-Density Parity-Check (LDPC) code</u></a>. This code is defined by a <b>parity check</b> matrix <code>P</code> with and a corresponding <b>generator</b> matrix <code>G</code>. The parity check matrix has bit entries and might look something like this:</p>
            <pre><code>import numpy as np
P = np.matrix([[1, 0, 1],
               [0, 0, 1],
               [0, 1, 1],
               [1, 1, 1],
               [1, 0, 0],
               [0, 1, 0]])</code></pre>
            <p>This matrix is used to check if a given bit string is a codeword. By definition, a codeword is any bit string c for which the weight of <code>P*c</code> (the number ones in the output of <code>P*c</code>) is small. (Note that arithmetic is modulo <code>2</code> here.) The generator matrix <code>G</code> is constructed from <code>P </code>so that it can be used as the encoder. In particular, for any bit string <code>m</code>, <code>c=G*m </code>is a codeword. The performance of this code depends in large part on the sparsity of the parity check matrix: roughly speaking, the more zero entries the matrix has, the more the bit flips the code can tolerate.</p><p>The main idea of Christ-Gunn-2024 is to tune the parameters of the LDPC code (the dimensions of the parity check matrix and its density) so that when the parity-check matrix <code>P</code> is chosen at random, the generator matrix <code>G</code> is pseudorandom. This means that, intuitively, when we encode a random input <code>m</code> as <code>c=G*m</code>, the codeword <code>c</code> is also pseudorandom. (There is a bit more that goes into constructing the input <code>m</code>, but this is roughly the idea.)</p><p>It's easy to see that a watermark based on this construction is robust, as it follows immediately from the capacity of LDPC to tolerate bit flips. Ensuring the watermark remains undetectable is more delicate, as it relies on relatively strong and understudied computational assumptions. As a result, it's not clear today for what parameter ranges this scheme is concretely secure. (There has been some progress here: <a href="https://eprint.iacr.org/2024/1425"><u>a recent preprint</u></a> by Surendra Ghentiyala and Venkatesan Guruswami showed that the pseudorandomness of Christ-Gunn-2024 can be proved with slightly weaker assumptions.)</p><p>To get a feel for how things might go wrong, consider what happens if the attacker manages to guess one of the rows of the parity check matrix<code> P</code>. When we take the dot product of this row with a codeword, then the output will be 0 with high probability. (By definition, <code>c</code> is a codeword if the sum of the dot products of <code>c </code>with each row of <code>P</code> is small.) But if we take the dot product of this row with a random bit string, then we should expect to see 0 with probability roughly ½. This gives us a way of distinguishing codewords from random bit strings.</p><p>Guessing a row of <code>P</code> is easy if the matrix is too sparse. In the extreme case, if each row has only one bit set, then there are only <code>n</code> possible values for that row, where <code>n</code> is the number of columns of <code>P</code>. On the other hand, making <code>P</code> too dense will degrade the code's ability to detect bit flips.</p><p>Similarly, it may be easy to guess a row of <code>P</code> if the length of the codeword itself (<code>n</code>) is too small. Thus, in order for this code to be pseudorandom, it is necessary (but not sufficient) for the number of possible parity check matrices to be so large that exhaustively searching for <code>P</code> is not feasible. This can be done by increasing the size of the codeword or tolerating fewer bit flips.</p>
    <div>
      <h4>Pseudorandom codes from PRFs</h4>
      <a href="#pseudorandom-codes-from-prfs">
        
      </a>
    </div>
    <p>Another approach to constructing pseudorandom codes comes from <a href="https://eprint.iacr.org/2024/898"><u>a 2024 preprint</u></a> from Noah Golowich and Ankur Moitra. Their starting point is a common cryptographic primitive called a pseudorandom function (PRF). They require a PRF that takes as input a key <code>k</code>, a bit string <code>x</code> of length <code>m</code> and outputs a bit, denoted <code>F(k,m)</code>.</p><p>Suppose our codewords are <code>x</code><code><sub>1</sub></code>, ⁣<code>w</code><code><sub>1</sub></code><code>=F(k,x</code><code><sub>1</sub></code><code>)</code>, …,<code> x</code><code><sub>n</sub></code>,<code> w</code><code><sub>n</sub></code><code>=F(k,x</code><code><sub>n</sub></code><code>) </code>where <code>x</code><code><sub>1</sub></code>, …, <code>x</code><code><sub>n</sub></code> are random <code>m</code>-bit strings. (Notice that the codeword length is <code>(m+1)*n</code>.) To verify if a string is a codeword, we parse the codeword into <code>x</code><code><sub>1</sub></code>, <code>w</code><code><sub>1</sub></code>, …, <code>x</code><code><sub>n</sub></code>, <code>w</code><code><sub>n</sub></code><code> </code>and check if <code>w</code><code><sub>i</sub></code><code> = F(k,x</code><code><sub>i</sub></code><code>)</code> for all <code>i</code>. If the number of checks that pass is sufficiently high, then the string is likely a codeword.</p><p>It's easy to see that this code is pseudorandom if the output of <code>F</code> is pseudorandom. However, it's not very robust: to make the <code>i</code>-th check fail, we just need to flip a single bit, <code>w</code><code><sub>i</sub></code>. The attacker just needs to flip a sufficient number of these bits to cause verification to fail. To defeat this attack, the encoder permutes the bits of the codeword with a secret, random permutation. That way the attacker has to guess the position of a sufficient number of <code>w</code><code><sub>i</sub></code>s in the permuted bit string. (A bit more is required to make this scheme provably robust, but this is the idea.)</p><p>Note that the number of bit flips we can tolerate with this scheme depends significantly on the number of PRF checks. This in turn determines the length of the codeword, so we may only get a reasonable degree of robustness for longer codewords. Note that we can increase the number of PRF checks by decreasing the length <code>m</code> of the <code>x</code><code><sub>i</sub></code>s, but making these strings too short is detrimental for pseudorandomness. (What happens if we happen to randomly pick <code>x</code><code><sub>i</sub></code><code>==x</code><code><sub>j</sub></code><code> </code>for <code>i!=j</code>?)</p>
    <div>
      <h4>Are these schemes practical?</h4>
      <a href="#are-these-schemes-practical">
        
      </a>
    </div>
    <p>In our own experiments with Stable Diffusion, we were able to tune the LDPC code to tolerate up to 33% of the codeword bits being mangled, which is likely more than sufficient for robustness in practice. However, achieving this required making the parity check matrix so sparse that the code is not strongly pseudorandom. Thus, the resulting watermark cannot be considered cryptographically undetectable. Among the parameter sets for which the code is plausibly pseudorandom, we didn't find any for which the code tolerates more than 5% bit flips.</p><p>Our findings were similar for the PRF-based code: with plausibly pseudorandom parameters, we couldn't tune the code to tolerate more than 1% bit flips. Like the LDPC code, we can crank this higher by sacrificing pseudorandomness, but we weren't able to crack 5% with any parameters we tried.</p><p>There are a few ways to think about this.</p><p>First, for both codes, robustness improves as the codeword gets larger. In particular, if the latent space for Stable Diffusion were larger, then we'd expect to be able to tolerate more bit flips. In general, cryptographic watermarks of all kinds perform better when there is more randomness to work with. For example, short responses produced by chatbots are especially hard for any watermarking strategy, including pseudorandom codes.</p><p>Another takeaway is that we need a better approximation of the initial latent than provided by DDIM. Indeed, <a href="https://arxiv.org/abs/2410.07369"><u>in their own evaluation</u></a> of the LDPC-based code, Sam Gunn, Xuandong Zhao, and Dawn Song chose a much more sophisticated inversion method, which exhibited better results, albeit at a higher computational cost.</p><p>A third view is that, as a practical matter, cryptographic undetectability might not be all that important for some applications. For instance, we might decide the watermark is good enough on the basis of statistical tests to check for biases within, or correlations across, codewords. Of course, such tests can't rule out the possibility of perceptible differences between watermarked and unwatermarked artifacts.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/7BVEy8oI4HZUU6u7zUgW9G/20c48669c252dfe99a689dd0860a54a7/2.png" />
          </figure><p><sup><i>Figure 4: Images with verified LDPC watermarks generated with prompt 'grainy photo of a UFO at night'.</i></sup></p>
    <div>
      <h3>Conclusion</h3>
      <a href="#conclusion">
        
      </a>
    </div>
    <p>The sign of a good abstraction boundary is that it allows folks to collaborate across disciplines. With pseudorandom codes, it seems like we've landed on the right abstraction for AI watermarking: it's up to cryptography experts to figure out how to instantiate them; and it's up to AI/ML experts to figure out how to embed them in their applications. We believe this separation of concerns has the potential to make watermarking easier to deploy, especially for operators like Cloudflare's <a href="https://www.cloudflare.com/developer-platform/products/workers-ai/"><u>Workers AI</u></a>, who don't train and maintain the models themselves.</p><p>After spending a few weeks playing around with this stuff, we're excited by the potential of pseudorandom codes to make strong watermarks for generative AI. However, we feel it will take some time for this field to yield practical schemes.</p><p>Existing candidates will require further study to determine the parameter ranges for which they provide good security. It is also worthwhile to investigate new approaches to building pseudorandom codes, perhaps starting with some other error correcting code besides LDPC. We should also examine what is even theoretically possible in this space: perhaps there is a fundamental tension between detectability and robustness that can't be resolved for some parameter regimes.</p><p>It's also going to be important for watermarks based on pseudorandom codes to be publicly verifiable, as some other cryptographic watermarks are. Concretely, the LDPC code is sort of analogous to public key encryption, where the ciphertext corresponds to a codeword. It might be possible to flip this paradigm around and make a digital signature where the signature is a codeword. Of course, this only works when the weights of the model are also publicly available.</p><p>On the AI/ML side, we need to look closer at methods of approximating the initial randomness for different types of models. This blog looked at what is perhaps the simplest possible method for Stable Diffusion, and while this seems to work pretty well, it's obvious that we can do a lot better. It's just a matter of keeping costs low. A good rule of thumb might be that verifying the watermark should not be more expensive than watermarked inference.</p><p>Pseudorandom codes may also have applications beyond watermarking. When we circulated this blog post internally, an idea that came up a lot was to somehow apply this technology to non-AI content, to embed in the content its provenance. Indeed, this is the idea behind the <a href="https://blog.cloudflare.com/preserve-content-credentials-with-cloudflare-images/"><u>C2PA integration</u></a>. Pseudorandom codes aren't immediately applicable, but may be in the future. Wherever you have a source of randomness in the process of generating some artifact, like digital photography, you can embed in that randomness a codeword.</p><p>Thanks for reading! We hope we've managed to pique your interest in this field. We certainly will be following along. If you'd like to play with the code we used to produce the numbers in this blog, or just make some cool watermarked AI content, you can find our demo on <a href="https://github.com/cloudflareresearch/poc-watermark"><u>GitHub</u></a>.</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Cryptography]]></category>
            <category><![CDATA[Research]]></category>
            <guid isPermaLink="false">VxbhII1JF1Bnb4w9D1kEQ</guid>
            <dc:creator>Teresa Brooks-Mejia</dc:creator>
            <dc:creator>Christopher Patton</dc:creator>
        </item>
        <item>
            <title><![CDATA[How we train AI to uncover malicious JavaScript intent and make web surfing safer]]></title>
            <link>https://blog.cloudflare.com/how-we-train-ai-to-uncover-malicious-javascript-intent-and-make-web-surfing-safer/</link>
            <pubDate>Wed, 19 Mar 2025 13:00:00 GMT</pubDate>
            <description><![CDATA[ Learn more about how Cloudflare developed an AI model to uncover malicious JavaScript intent using a Graph Neural Network, from pre-processing data to inferencing at scale.  ]]></description>
            <content:encoded><![CDATA[ <p>Modern websites <a href="https://blog.cloudflare.com/application-security-report-2024-update/#enterprise-applications-use-47-third-party-scripts-on-average"><u>rely heavily</u></a> on JavaScript. Leveraging third-party scripts accelerates web app development, enabling organizations to deploy new features faster without building everything from scratch. However, supply chain attacks targeting third-party JavaScript are no longer just a theoretical concern — they have become a reality, as <a href="https://blog.cloudflare.com/polyfill-io-now-available-on-cdnjs-reduce-your-supply-chain-risk/"><u>recent incidents</u></a> have shown. Given the vast number of scripts and the rapid pace of updates, manually reviewing each one is not a scalable security strategy.</p><p>Cloudflare provides automated client-side protection through <a href="https://developers.cloudflare.com/page-shield/"><u>Page Shield</u></a>. Until now, Page Shield could scan JavaScript dependencies on a web page, flagging obfuscated script content which also exfiltrates data. However, these are only indirect indicators of compromise or malicious intent. Our original approach didn’t provide clear insights into a script’s specific malicious objectives or the type of attack it was designed to execute.</p><p>Taking things a step further, we have developed a new AI model that allows us to detect the exact malicious intent behind each script. This intelligence is now integrated into Page Shield, available to all Page Shield <a href="https://developers.cloudflare.com/page-shield/#availability"><u>add-on</u></a> customers. We are starting with three key threat categories: <a href="https://en.wikipedia.org/wiki/Web_skimming"><u>Magecart</u></a>, crypto mining, and malware.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/6EefJpCcho3DIjbVbQIjuz/68852b905955065e48ec2aa4648621cd/1.png" />
          </figure><p><sup><i>Screenshot of Page Shield dashboard showing results of three types of analysis.</i></sup></p><p>With these improvements, Page Shield provides deeper visibility into client-side threats, empowering organizations to better protect their users from evolving security risks. This new capability is available to all Page Shield customers with the <a href="https://developers.cloudflare.com/page-shield/#availability"><u>add-on</u></a>. Head over <a href="https://dash.cloudflare.com/?to=/:account/:zone/security/page-shield"><u>to the dashboard</u></a>, and you can find the new malicious code analysis for each of the scripts monitored.</p><p>In the following sections, we take a deep dive into how we developed this model.</p>
    <div>
      <h3>Training the model to detect hidden malicious intent</h3>
      <a href="#training-the-model-to-detect-hidden-malicious-intent">
        
      </a>
    </div>
    <p>We built this new Page Shield AI model to detect the intent of JavaScript threats at scale. Training such a model for JavaScript comes with unique challenges, including dealing with web code written in many different styles, often obfuscated yet benign. For instance, the following three snippets serve the same function.</p>
            <pre><code>//Readable, plain code
function sayHi(name) {
  console.log(
    `Hello ${
      name ?? 
      "World" //default
    }!`
  );
}
sayHi("Internet");

//Minified
function sayHi(l){console.log(`Hello ${l??"World"}!`)}sayHi("Internet");

//Obfuscated
var h=Q;(function(V,A){var J=Q,p=V();while(!![]){try{var b=-parseInt(J('0x79'))/0x1*(-parseInt(J('0x6e'))/0x2)+-parseInt(J('0x80'))/0x3+parseInt(J('0x76'))/0x4*(-parseInt(J('0x72'))/0x5)+parseInt(J('0x6a'))/0x6+parseInt(J('0x84'))/0x7+-parseInt(J('0x6d'))/0x8*(-parseInt(J('0x7d'))/0x9)+parseInt(J('0x73'))/0xa*(-parseInt(J('0x7c'))/0xb);if(b===A)break;else p['push'](p['shift']());}catch(U){p['push'](p['shift']());}}}(S,0x22097));function sayHi(p){var Y=Q,b=(function(){var W=!![];return function(e,x){var B=W?function(){var m=Q;if(x){var G=x[m('0x71')](e,arguments);return x=null,G;}}:function(){};return W=![],B;};}()),U=b(this,function(){var s=Q,W=typeof window!==s('0x6b')?window:typeof process===s('0x6c')&amp;&amp;typeof require===s('0x7b')&amp;&amp;typeof global==='object'?global:this,e=W['console']=W['console']||{},x=[s('0x78'),s('0x70'),'info',s('0x69'),s('0x77'),'table',s('0x7f')];for(var B=0x0;B&lt;x[s('0x83')];B++){var G=b[s('0x75')][s('0x6f')][s('0x74')](b),t=x[B],X=e[t]||G;G['__proto__']=b[s('0x74')](b),G['toString']=X[s('0x7e')]['bind'](X),e[t]=G;}});U(),console['log'](Y('0x81')+(p??Y('0x7a'))+'!');}sayHi(h('0x82'));function Q(V,A){var p=S();return Q=function(b,U){b=b-0x69;var W=p[b];return W;},Q(V,A);}function S(){var v=['Internet','length','77966Hcxgji','error','1078032RtaGFM','undefined','object','8zrzBEk','244xEPFaR','prototype','warn','apply','10LQgYRU','400TNVOzq','bind','constructor','146612cfnkCX','exception','log','1513TBJIGL','World','function','57541MkoqrR','2362383dtBFrf','toString','trace','647766YvOJOm','Hello\x20'];S=function(){return v;};return S();}</code></pre>
            <p>With such a variance of styles (and many more), our machine learning solution needs to balance precision (low false positive rate), recall (don’t miss an attack vector), and speed. Here’s how we do it:</p>
    <div>
      <h4>Using syntax trees to classify malicious code</h4>
      <a href="#using-syntax-trees-to-classify-malicious-code">
        
      </a>
    </div>
    <p>JavaScript files are parsed into <a href="https://en.wikipedia.org/wiki/Tree_(graph_theory)"><u>syntax trees (connected acyclic graphs)</u></a>. These serve as the input to a <a href="https://en.wikipedia.org/wiki/Graph_neural_network"><u>Graph Neural Network (GNN)</u></a>. GNNs are used because they effectively capture the interdependencies (relationships between nodes) in executing code, such as a function calling another function. This contrasts with treating the code as merely a sequence of words — something a code compiler, incidentally, does not do. Another motivation to use GNNs is the <a href="https://dl.acm.org/doi/10.1007/978-3-030-92270-2_57"><u>insight</u></a> that the syntax trees of malicious versus benign JavaScript tend to be different. For example, it’s not rare to find attacks that consist of malicious snippets inserted into, but otherwise isolated from, the rest of a benign base code.</p><p>To parse the files, the <a href="https://tree-sitter.github.io/"><u>tree-sitter library</u></a> was chosen for its speed. One peculiarity of this parser, specialized for text editors, is that it parses out <a href="https://en.wikipedia.org/wiki/Parse_tree"><u>concrete syntax trees (CST)</u></a>. CSTs retain everything from the original text input, including spacing information, comments, and even nodes attempting to repair syntax errors. This differs from <a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree"><u>abstract syntax trees (AST)</u></a>, the data structures used in compilers, which have just the essential information to execute the underlying code while ignoring the rest. One key reason for wanting to convert the CST to an AST-like structure, is that it reduces the tree size, which in turn reduces computation and memory usage. To do that, we abstract and filter out unnecessary nodes such as code comments. Consider for instance, how the following snippet</p>
            <pre><code>x = `result: ${(10+5) *   3}`;;; //this is a comment</code></pre>
            <p>… gets converted to an AST-like representation:</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/4KweWZ4yIzOTiIcYqHC682/56c059b38ad46949e7285d84438be4c9/2.png" />
          </figure><p><sup><i>Abstract Syntax Tree (AST) representation of the sample code above. Unnecessary elements get removed (e.g. comments, spacing) whereas others get encoded in the tree structure (order of operations due to parentheses).</i></sup></p><p>One benefit of working with parsed syntax trees is that <a href="https://huggingface.co/learn/nlp-course/en/chapter2/4"><u>tokenization</u></a> comes for free! We collect and treat the node leaves’ text as our tokens, which will be used as features (inputs) for the machine learning model. Note that multiple characters in the original input, for instance backticks to form a template string, are not treated as tokens per se, but remain encoded in the graph structure given to the GNN. (Notice in the sample tree representations the different node types, such as “assignment_expression”). Moreover, some details in the exact text input become irrelevant in the executing AST, such as whether a string was originally written using double quotes vs. single quotes.</p><p>We encode the node tokens and node types into a matrix of counts. Currently, we lowercase the nodes' text to reduce vocabulary size, improving efficiency and reducing sparsity. Note that JavaScript is a case-sensitive language, so this is a trade-off we continue to explore. This matrix and, importantly, the information about the node edges within the tree, is the input to the GNN.</p><p>How do we deal with obfuscated code? We don’t treat it specially. Rather, we always parse the JavaScript text as is, which incidentally unescapes <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Character_escape"><u>escape characters</u></a> too. For instance, the resulting AST shown below for the following input exemplifies that:</p>
            <pre><code>atob('\x55\x32\x56\x75\x5a\x45\x52\x68\x64\x47\x45\x3d') == "SendData"</code></pre>
            
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/sV2qPtj8G30EFnW6rwCav/ef0a970e338e5610da08fa3ccbdeafcc/3.png" />
          </figure><p><sup><i>Abstract Syntax Tree (AST) representation of the sample code above. JavaScript escape characters are unescaped.</i></sup></p><p>Moreover, our vocabulary contains several tokens that are commonly used in obfuscated code, such as double escaped hexadecimal-encoded characters. That, together with the graph structure information, is giving us satisfying results — the model successfully classifies malicious code whether it's obfuscated or not. Analogously, our model’s scores remain stable when applied to plain benign scripts compared to obfuscating them in different ways. In other words, the model’s score on a script is similar to the score on an obfuscated version of the same script. Having said that, some of our model's false positives (FPs) originate from benign but obfuscated code, so we continue to investigate how we can improve our model's intelligence.</p>
    <div>
      <h4>Architecting the Graph Neural Network</h4>
      <a href="#architecting-the-graph-neural-network">
        
      </a>
    </div>
    <p>We train a <a href="https://mbernste.github.io/posts/gcn/"><u>message-passing graph convolutional network (MPGCN)</u></a> that processes the input trees. The message-passing layers iteratively update each node’s internal representation, encoded in a matrix, by aggregating information from its neighbors (parent and child nodes in the tree). A pooling layer then condenses this matrix into a feature vector, discarding the explicit graph structure (edge connections between nodes). At this point, standard neural network layers, such as fully connected layers, can be applied to progressively refine the representation. Finally, a <a href="https://en.wikipedia.org/wiki/Softmax_function"><u>softmax activation</u></a> layer produces a probability distribution over the four possible classes: benign, magecart, cryptomining, and malware.</p><p>We use the <a href="https://github.com/tensorflow/gnn"><u>TF-GNN library</u></a> to implement graph neural networks, with <a href="https://keras.io/"><u>Keras</u></a> serving as the high-level frontend for model building and training. This works well for us with one exception: <a href="https://github.com/tensorflow/gnn/issues/803#issue-2279602052"><u>TF-GNN does not support sparse matrices / tensors</u></a>. (That lack of support increases memory consumption, which also adds some latency.) Because of this, we are considering switching to <a href="https://pytorch-geometric.readthedocs.io/"><u>PyTorch Geometric</u></a> instead.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/79SbvJgWq3mwMks6Vtxpgs/5ab55f19b6cf90dc070b5f0d70abdde9/4.png" />
          </figure><p><sup><i>Graph neural network architecture, transforming the input tree with features down to the 4 classification probabilities.</i></sup></p><p>The model’s output probabilities are finally inverted and scaled into <a href="https://developers.cloudflare.com/page-shield/how-it-works/malicious-script-detection/#malicious-script-detection"><u>scores</u></a> (ranging from 1 to 99). The “js_integrity” score aggregates the malicious classes (magecart, malware, cryptomining). A low score means likely malicious, and a high score means likely benign. We use this output format for consistency with other Cloudflare detection systems, such as <a href="https://developers.cloudflare.com/page-shield/how-it-works/malicious-script-detection/#malicious-script-detection"><u>Bot Management</u></a> and the <a href="https://developers.cloudflare.com/waf/detections/attack-score/"><u>WAF Attack Score</u></a>. The following diagram illustrates the preprocessing and feature analysis pipeline of the model down to the inference results.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/zLPW9kydBIJySfjaN2TTI/d7b9a7f51c1bb501aac2b7a724d62a1d/5.png" />
          </figure><p><sup><i>Model inference pipeline to sniff out and alert on malicious JavaScript.</i></sup></p>
    <div>
      <h4>Tackling unbalanced data: malicious scripts are the minority</h4>
      <a href="#tackling-unbalanced-data-malicious-scripts-are-the-minority">
        
      </a>
    </div>
    <p>Finding malicious scripts is like finding a needle in a haystack; they are anomalies among plenty of otherwise benign JavaScript. This naturally results in a highly imbalanced dataset. For example, our Magecart-labeled scripts only account for ~6% of the total dataset.</p><p>Not only that, but the “benign” category contains an immense variance (and amount) of JavaScript to classify. The lengths of the scripts are highly diverse (ranging from just a few bytes to several megabytes), their coding styles vary widely, some are obfuscated whereas others are not, etc. To make matters worse, malicious payloads are often just small, carefully inserted fragments within an otherwise perfectly valid and functional benign script. This all creates a cacophony of token distributions for an ML model to make sense of.</p><p>Still, our biggest problem remains finding enough malevolent JavaScript to add to our training dataset. Thus, simplifying it, our strategy for data collection and annotation is two-fold:</p><ol><li><p>Malicious scripts are about quantity → the more, the merrier (for our model, that is 😉). Of course, we still care about quality and diversity. But because we have so few of them (in comparison to the number of benign scripts), we take what we can.</p></li><li><p>Benign scripts are about quality → the more <i>variance</i>, the merrier. Here we have the opposite situation. Because we can collect so many of them easily, the value is in adding differentiated scripts.</p></li></ol>
    <div>
      <h5>Learning key scripts only: reduce false positives with minimal annotation time</h5>
      <a href="#learning-key-scripts-only-reduce-false-positives-with-minimal-annotation-time">
        
      </a>
    </div>
    <p>To filter out semantically-similar scripts (mostly benign), we employed the latest advancements in LLM for generating code <a href="https://www.cloudflare.com/learning/ai/what-are-embeddings/"><u>embeddings</u></a>. We added those scripts that are distant enough from each other to our dataset, as measured by <a href="https://developers.cloudflare.com/vectorize/best-practices/create-indexes/#distance-metrics"><u>vector cosine similarity</u></a>. Our methodology is simple — for a batch of potentially new scripts:</p><ul><li><p>Initialize an empty <a href="https://www.cloudflare.com/learning/ai/what-is-vector-database/"><u>vector database</u></a>. For local experimentation, we are fans of <a href="https://docs.trychroma.com/docs/overview/introduction"><u>Chroma DB</u></a>.</p></li><li><p>For each script:</p><ul><li><p>Call an LLM to generate its embedding. We’ve had good results with <a href="https://github.com/bigcode-project/starcoder2"><u>starcoder2</u></a>, and most recently <a href="https://huggingface.co/Qwen/Qwen2.5-Coder-32B"><u>qwen2.5-coder</u></a>.</p></li><li><p>Search in the database for the top-1 closest other script’s vectors.</p></li><li><p>If the distance &gt; threshold (0.10), select it and add it to the database.</p></li><li><p>Else, discard the script (though we consider it for further validations and tests).</p></li></ul></li></ul><p>Although this methodology has an inherent bias in gradually favoring the first seen scripts, in practice we’ve used it for batches of newly and randomly sampled JavaScript only. To review the whole existing dataset, we could employ other but similar strategies, like applying <a href="https://scikit-learn.org/stable/modules/generated/sklearn.cluster.HDBSCAN.html"><u>HDBSCAN</u></a> to identify an unknown number of clusters and then selecting the medoids, boundary, and anomaly data points.</p><p>We’ve successfully employed this strategy for pinpointing a few highly varied scripts that were relevant for the model to learn from. Our security researchers save a tremendous amount of time on manual annotation, while false positives are drastically reduced. For instance, in a large and unlabeled bucket of scripts, one of our early evaluation models identified ~3,000 of them as malicious. That’s too many to manually review! By removing near duplicates, we narrowed the need for annotation down to only 196 samples, less than 7% of the original amount (see the <a href="https://en.wikipedia.org/wiki/T-distributed_stochastic_neighbor_embedding"><u>t-SNE</u></a> visualization below of selected points and clusters). Three of those scripts were actually malicious, one we could not fully determine, and the rest were benign. By just re-training with these new labeled scripts, a tiny fraction of our whole dataset, we reduced false positives by 50% (as gauged in the same bucket and in a controlled test set). We have consistently repeated this procedure to iteratively enhance successive model versions.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/hHw00ojXE4CdorMQI5b56/897e0e045230522478e0735c3e28ff12/6.png" />
          </figure><p><sup><i>2D visualization of scripts projected onto an embedding space, highlighting those sufficiently dissimilar from one another.</i></sup></p>
    <div>
      <h4>From the lab, to the real world</h4>
      <a href="#from-the-lab-to-the-real-world">
        
      </a>
    </div>
    <p>Our latest model in evaluation has both a macro accuracy and an overall malicious precision nearing 99%(!) on our test dataset. So we are done, right? Wrong! The real world is not the same as the lab, where many more variances of benign JavaScript can be seen. To further assure minimum prediction changes between model releases, we follow these three anti-fool measures:</p>
    <div>
      <h5>Evaluate metrics uncertainty</h5>
      <a href="#evaluate-metrics-uncertainty">
        
      </a>
    </div>
    <p>First, we thoroughly estimate the <i>uncertainty</i> of our offline evaluation metrics. How accurate are our accuracy metrics themselves? To gauge that, we calculate the <a href="https://en.wikipedia.org/wiki/Standard_error"><u>standard error</u></a> and confidence intervals for our offline metrics (precision, recall, <a href="https://en.wikipedia.org/wiki/F-score"><u>F1 measure</u></a>). To do that, we calculate the model’s predicted scores on the test set once (the original sample), and then generate bootstrapped resamples from it. We use simple random (re-)sampling as it offers us a more conservative estimate of error than stratified or balanced sampling.</p><p>We would generate 1,000 resamples, each a fraction of 15% resampled from the original test sample, then calculate the metrics for each individual resample. This results in a distribution of sampled data points. We measure its mean, the standard deviation (with <a href="https://en.wikipedia.org/wiki/Standard_deviation#Corrected_sample_standard_deviation"><u>Bessel’s correction</u></a>), and finally the standard error and a <a href="https://en.wikipedia.org/wiki/Confidence_interval"><u>confidence interval</u></a> (CI) (using the percentile method, such as the 2.5 and 97.5 percentiles for a 95% CI). See below for an example of a bootstrapped distribution for precision (P), illustrating that a model’s performance is a continuum rather than a fixed value, and that might exhibit subtly (left-)skewed tails. For some of our internally evaluated models, it can easily happen that some of the sub-sampled metrics decrease by up to 20 percentage points within a 95% confidence range. High standard errors and/or confidence ranges signal needs for model improvement and for improving and increasing our test set.</p>
          <figure>
          <img src="https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2x3X2oVv2EfIkLYFrcjLWK/985a685e565f759b7781821595ac4ff7/7.png" />
          </figure><p><sup><i>An evaluation metric, here precision (P), might change significantly depending on what’s exactly tested. We thoroughly estimate the metric’s standard error and confidence intervals.</i></sup></p>
    <div>
      <h5>Benchmark against massive offline unlabeled dataset</h5>
      <a href="#benchmark-against-massive-offline-unlabeled-dataset">
        
      </a>
    </div>
    <p>We run our model on the entire corpus of scripts seen by Cloudflare's network and temporarily cached in the last 90 days. By the way, that’s nearly 1 TiB and 26 million different JavaScript files! With that, we can observe the model’s behavior against real traffic, yet completely offline (to ensure no impact to production). We check the malicious prediction rate, latency, throughput, etc. and sample some of the predictions for verification and annotation.</p>
    <div>
      <h5>Review in staging and shadow mode</h5>
      <a href="#review-in-staging-and-shadow-mode">
        
      </a>
    </div>
    <p>Only after all the previous checks were cleared, we then run this new tentative version in our staging environment. For major model upgrades, we also deploy them in <a href="https://cloud.google.com/architecture/guidelines-for-developing-high-quality-ml-solutions"><u>shadow mode</u></a> (log-only mode) — running on production, alongside our existing model. We study the model’s behavior for a while before finally marking it as production ready, otherwise we go back to the drawing board.</p>
    <div>
      <h3>AI inference at scale</h3>
      <a href="#ai-inference-at-scale">
        
      </a>
    </div>
    <p>At the time of writing, Page Shield sees an average of <i>40,000 scripts per second</i>. Many of those scripts are repeated, though. Everything on the Internet follows a <a href="https://blog.cloudflare.com/making-waf-ai-models-go-brr/#caching-inference-result"><u>Zipf's law distribution</u></a>, and JavaScript seen on the Cloudflare network is no exception. For instance, it is estimated that different versions of the <a href="https://blog.cloudflare.com/page-shield-positive-blocking-policies/#client-side-libraries"><u>Bootstrap library run on more than 20% of websites</u></a>. It would be a waste of computing resources if we repeatedly re-ran the AI model for the very same inputs — inference result caching is needed. Not to mention, GPU utilization is expensive!</p><p>The question is, what is the best way to cache the scripts? We could take an <a href="https://csrc.nist.gov/glossary/term/sha_256"><u>SHA-256</u></a> hash of the plain content as is. However, any single change in the transmitted content (comments, spacing, or a different character set) changes the SHA-256 output hash.</p><p>A better caching approach? Since we need to parse the code into syntax trees for our GNN model anyway, this tree structure and content is what we use to hash the JavaScript. As described above, we filter out nodes in the syntax tree like comments or empty statements. In addition, some irrelevant details get abstracted out in the AST (escape sequences are unescaped, the way of writing strings is normalized, unnecessary parentheses are removed for the operations order is encoded in the tree, etc.).</p><p>Using such a tree-based approach to caching, we can conclude that at any moment over 99.9% of reported scripts have already been seen in our network! Unless we deploy a new model with significant improvements, we don’t re-score previously seen JavaScript but just return the cached score. As a result, the model only needs to be called <i>fewer than 10 times per minute</i>, even during peak times!</p>
    <div>
      <h3>Let AI help ease PCI DSS v4 compliance</h3>
      <a href="#let-ai-help-ease-pci-dss-v4-compliance">
        
      </a>
    </div>
    <p>One of the most popular use cases for deploying Page Shield is to help meet the two new client-side security requirements in PCI DSS v4 — <a href="https://assets.ctfassets.net/slt3lc6tev37/4HJex2kG7FCb1IJRC9rIhL/081fdd8b1a471def14cfd415f99e4b58/Evaluation_Page_Shield_091124_FINAL.pdf"><u>6.4.3 and 11.6.1</u></a>. These requirements make companies responsible for approving scripts used in payment pages, where payment card data could be compromised by malicious JavaScript. Both of these requirements <a href="https://blog.pcisecuritystandards.org/countdown-to-pci-dss-v4.0"><u>become effective</u></a> on March 31, 2025.</p><p>Page Shield with AI malicious JavaScript detection can be deployed with just a few clicks, especially if your website is already proxied through Cloudflare. <a href="https://www.cloudflare.com/page-shield/"><u>Sign up here</u></a> to fast track your onboarding!</p> ]]></content:encoded>
            <category><![CDATA[Security Week]]></category>
            <category><![CDATA[Page Shield]]></category>
            <category><![CDATA[AI]]></category>
            <category><![CDATA[Machine Learning]]></category>
            <category><![CDATA[Malicious JavaScript]]></category>
            <category><![CDATA[JavaScript]]></category>
            <guid isPermaLink="false">3VQUOQBWzT8cc7oFFv003i</guid>
            <dc:creator>Juan Miguel Cejuela</dc:creator>
            <dc:creator>Zhiyuan Zheng</dc:creator>
        </item>
    </channel>
</rss>