XSS and Script Tampering on Dubai Websites in 2026: CSP Level 3, Trusted Types and Integrity Policy
Only 21.9% of pages send a CSP and 92% of those allow unsafe-inline. The nonce CSP, Trusted Types and Integrity-Policy stack that actually stops injected script, with AED costs.
- PUBLISHED
- 07 NOV 2026
- READ TIME
- 13 MIN
- AUTHOR
- AQUARIUS · DUBAI
- UNIT
- REV 2026.09
Short answer: Cross-site scripting and third-party script tampering are no longer stopped by a scanner or a WAF — they are stopped by three response headers: a nonce-based Content-Security-Policy with strict-dynamic, require-trusted-types-for 'script', and Chrome’s new Integrity-Policy. Most Dubai websites ship none of them, and most of the ones that do ship a CSP cancel it out with unsafe-inline. A policy that allows inline script is not a security control; it is a header that makes a pentest report look shorter.
The gap is measurable. In the 2025 Web Almanac crawl, only 21.9% of pages send any Content-Security-Policy header (up from 18.5% the year before) — and of those, 92% still contain unsafe-inline and 77% still contain unsafe-eval. Nonces appear in roughly 20% of policies and strict-dynamic in about 10%. Meanwhile the attack surface keeps growing: around 90% of pages load at least one third party, the median page makes 83 third-party requests on desktop and 79 on mobile (129 for the top 1,000 sites), and 24.8% of all third-party requests are scripts — executable code you did not write, running with full access to your checkout form.
And it is actively exploited right now. Report URI’s November 2026 scan found 15,579 websites currently serving malicious JavaScript, conservatively 135 million visits a month landing on them, with roughly 16,000 more sites in the notification queue and, in Scott Helme’s words, “almost no response rate” from the owners. Sansec adds around 30 new Magecart skimmer signatures every day and counts 70,000+ stores skimmed historically, including a 2026 Magento CMS-block loader campaign across 953 stores. For a UAE market where e-commerce is worth roughly AED 45.1 billion in 2026 across 45,000+ active stores and 11.04 million online shoppers, and where the UAE Cyber Security Council reports more than 800,000 cyberattacks a day, the base rate is not comforting.
Why the CSP on your Dubai site probably does nothing
A CSP stops injected script by telling the browser which script is yours. There are two ways to say that: an allowlist of hostnames, or a nonce — a random token minted per response and stamped on your own tags. Allowlists lose. Any allowlisted CDN that hosts user-uploadable files, an old JSONP endpoint, or a framework with a known bypass turns the whole policy into decoration. That is why Google moved its own properties to nonces.
Then there is the self-inflicted wound. If your policy contains unsafe-inline, the browser cannot distinguish your inline analytics snippet from an attacker’s injected <script>, so it allows both. The Almanac data says that is 92% of deployed policies. Add unsafe-eval (77%) and script injected through eval() and friends runs too. The most common directives on the web are upgrade-insecure-requests and frame-ancestors (roughly 50–55% of policies) — useful, but neither of them stops XSS.
One number in that dataset is worth reading carefully: require-trusted-types-for 'script' is now the third most common CSP directive, on 12.10% of mobile pages. That is not organic adoption — it is a handful of large platforms enabling it by default for everyone on them. If you are on a custom build, you are almost certainly not in that 12%.
The three layers that actually stop script injection
Treat these as a stack, not alternatives. Each one closes a different door, and only the first two are safe to assume everywhere in 2026.
| Control | What it blocks | Browser support (Nov 2026) | Breakage risk | Dubai build cost |
|---|---|---|---|---|
Nonce CSP + strict-dynamic | Injected and reflected <script>, allowlist bypasses | All modern browsers (CSP Level 3) | Medium — inline handlers and tag managers must be refactored | AED 8,000 – 22,000 |
| Trusted Types | DOM XSS at the sink: innerHTML, outerHTML, insertAdjacentHTML, document.write | Baseline since early 2026 — Chrome/Edge 83, Safari 26, Firefox 148 | Medium–high on legacy jQuery-era code | AED 10,000 – 35,000 |
| Subresource Integrity (SRI) | A third-party script file being swapped for a tampered one | Universal | Low — but versioned or rotating CDN files break | AED 3,000 – 8,000 |
Integrity-Policy | Any script loaded without an integrity hash — closes the SRI coverage gap | Chrome/Edge 138+ only; Firefox 145 partial; Safari no | High if any vendor ships unhashed script | AED 4,000 – 10,000 |
Layer 1 — a nonce CSP you can actually enforce
Generate a fresh random nonce per response, put it on every first-party <script>, and let strict-dynamic propagate trust to scripts those scripts load. That last part is what makes the migration survivable: you nonce the loader, not all forty tags it injects. A working starting policy looks like script-src 'nonce-{random}' 'strict-dynamic' https: 'unsafe-inline'; object-src 'none'; base-uri 'none' — the trailing https: and unsafe-inline are ignored by modern browsers that understand nonces and exist only as fallbacks for old ones.
Layer 2 — Trusted Types, now Baseline
CSP tells the browser which script files to trust. Trusted Types attacks the other half of the problem: strings reaching DOM sinks. With require-trusted-types-for 'script' set, passing a raw string to innerHTML throws a TypeError — the code has to pass through a named policy that sanitises it. Dangerous assignment becomes a type error you catch in review instead of a bug bounty report six months later.
This stopped being an experiment in 2026. Chrome and Edge shipped it in version 83 (May 2020), Safari in 26 (September 2025) and Firefox in 148 (February 2026), which made it Baseline. The results on the biggest deployment are hard to argue with: Google has migrated 130+ services and reported zero DOM XSS in them since 2019 — in a codebase where DOM XSS previously accounted for more than half of all XSS reported through its vulnerability reward programme. XSS is still 14.1% of all coordinated-disclosure reports on HackerOne in 2026, at an average bounty of USD 650, so the class is not dead. It is just solved structurally now instead of one sanitiser call at a time.
Layer 3 — SRI, and the hole Integrity-Policy plugs
SRI is on 25.9% of desktop pages, which sounds healthy until you look at coverage: the median page with SRI protects only 2.82% of its scripts. One hashed jQuery from 2019 and nothing else. Worse, SRI is opt-in per tag, so a marketer pasting a new vendor snippet silently bypasses it.
That is what Chrome’s Integrity-Policy header fixes, shipped in Chrome 138 (June 2025): it refuses to load any script that lacks an integrity hash. Syntax is two headers — Integrity-Policy: blocked-destinations=(script), endpoints=(integrity-endpoint) plus Reporting-Endpoints: integrity-endpoint="https://yoursite.ae/integrity". Run Integrity-Policy-Report-Only first. State the support gap honestly: Firefox 145 implements it partially (console logging only, reporting endpoints ignored) and Safari 26.x does not support it at all, so this is defence in depth for your Chrome and Edge majority, not a universal control.
A 30-day rollout that does not break the site
- Days 1–3: inventory. List every script your pages load, first and third party, including the ones injected by your tag manager. Most Dubai teams find two to three times more than they expected.
- Days 4–10: report-only. Ship
Content-Security-Policy-Report-Onlywith the nonce policy and a reporting endpoint. Nothing breaks; violations just arrive. Hosted collectors start around USD 54.99 a month (about AED 202) for one domain and 100,000 events, rising to USD 274.99 (about AED 1,010) for five domains — or self-host the endpoint. - Days 11–20: refactor. Move inline handlers into files, nonce the loaders, delete the dead vendor tags you found in step 1. This is where the real work sits.
- Days 21–25: enforce CSP, then add
require-trusted-types-forin report-only mode and fix the sink violations it surfaces. - Days 26–30: enforce Trusted Types, add SRI hashes to pinned libraries, and run
Integrity-Policy-Report-Only. Keep the reporting endpoint live permanently — it is your early warning when a vendor changes a script.
What it costs in Dubai, and what it saves
Budget by codebase age, not by page count. A Next.js or Nuxt build with clean components is a one to two week job. A ten-year-old WordPress theme with inline onclick attributes everywhere and six marketing plugins is a month.
| Scope | What you get | Timeline | AED |
|---|---|---|---|
| Audit + report-only CSP | Script inventory, reporting endpoint, violation triage report | 1 week | 6,000 – 12,000 |
| Enforced nonce CSP | Server-side nonce injection, refactored inline code, enforced policy | 2–3 weeks | 15,000 – 30,000 |
| Full stack: CSP + Trusted Types + SRI and Integrity-Policy | All four controls enforced, sanitiser policies, monitoring dashboard | 4–6 weeks | 35,000 – 75,000 |
| Ongoing monitoring | Violation alerting, vendor-change watch, quarterly review | Monthly | 1,200 – 3,500/mo |
Compare that to the downside. IBM’s 2026 Cost of a Data Breach report puts the Middle East average at USD 8 million, about AED 29.4 million — the second-highest region in the world. Fraud pressure is rising with it: a 2026 BioCatch survey of 100 UAE banking executives found 66% reporting more fraud attempts and 62% putting annual fraud losses above USD 5 million. If you are a CBUAE-licensed entity or a vendor to one, Regulation C 1/2026 (effective 14 September 2026) gives you 4 hours to assess materiality, 24 hours for a brief report and 72 hours for a high-severity incident report — clocks you cannot meet with no client-side telemetry at all. And if you take card details on your own pages, PCI DSS v4.0.1 requirements 6.4.3 and 11.6.1 have been mandatory since 31 March 2025; we break that scope down in our PCI DSS compliance cost guide for Dubai.
How Aquarius ships this
We do it report-only first, always. You get the script inventory before anyone touches code, so the marketing team sees exactly which tags will be refactored and which are getting deleted. Nonces are generated in middleware, not pasted by hand. Trusted Types goes in with a named sanitiser policy, so a future developer cannot quietly reintroduce a raw innerHTML assignment. We leave the reporting endpoint and a dashboard behind, because the control that matters most six months later is the alert that fires when a vendor changes a script.
If you want the attacker’s view first, pair it with a VAPT engagement — headers plus testing beats either alone. See what else is in scope on our services page, check indicative ranges on pricing, or send us your URL from the contact page and we will tell you within a day what your current headers do and do not stop.
FAQ
Does a strict CSP slow the site down?
No measurable cost. Nonce generation is one random value per response, and the policy is a header, not a script. The performance win usually comes from the side effect: the script inventory forces you to delete dead vendor tags, and that does show up in Core Web Vitals.
Will this break Google Tag Manager or Meta Pixel?
Not if you use strict-dynamic. You nonce the tag-manager loader and trust propagates to the tags it injects. What does break is custom HTML tags inside GTM that write markup directly — those need rewriting once Trusted Types is enforced. Plan for it; do not discover it in production.
Is SRI enough on its own for third-party scripts?
No. SRI only protects the files someone remembered to hash, and the median page using SRI covers 2.82% of its scripts. It also cannot protect a script that legitimately changes on every request. Use SRI for pinned libraries and Integrity-Policy-Report-Only to find the gaps.
Do I still need this if payments go through a hosted page or redirect?
Yes — less urgently for card data, just as urgently for everything else. A hosted payment page narrows PCI scope, but injected script on your own pages still harvests logins, phone numbers, Emirates ID uploads and OTP prompts, and UAE PDPL obligations attach to that personal data regardless of where the card number is typed.
What about Safari users if Integrity-Policy is Chrome-only?
Layer accordingly. The nonce CSP and Trusted Types work in every modern browser, including Safari 26 and up, and those two stop the XSS classes that matter most. Treat Integrity-Policy as a bonus layer for Chrome and Edge traffic, which is the clear majority of UAE desktop sessions.
