SPA security vulnerabilities: the regulatory exposure your forensics report will not capture

Key takeaways
DOM-based XSS executes entirely in the browser and generates no server-side log entry — when a breach is scoped for regulatory notification, the mechanism that enabled it is invisible to the monitoring programs most compliance teams have built.
GDPR Article 33 requires notification to include the number of affected individuals and categories of personal data accessed — organizations that cannot reconstruct which accounts a stolen session token reached cannot satisfy this requirement, and regulators treat that inability as evidence of inadequate monitoring.
localStorage token storage is the single configuration decision most likely to produce both a breach and an unscoped breach — there is no server-side record of which localStorage tokens existed or when they were accessed.
Third-party JavaScript libraries in SPAs execute with first-party permissions and are subject to first-party liability under GDPR and equivalent frameworks — the library vendor does not absorb regulatory responsibility for a breach caused by a vulnerable dependency you deployed.
CSP implemented without violation reporting configured satisfies no security objective and creates a misleading audit trail — regulators can ask for violation logs that do not exist.
In Vulnox assessments of SPA environments, the gap between client-side attack surface and server-side monitoring coverage is consistently wider than the development team estimates, typically by at least two exploit classes.
TL;DR
SPA security vulnerabilities are a regulatory evidence problem as much as a technical one. DOM-based XSS leaves no server-side trace. Token theft from localStorage has no audit trail. Third-party dependencies carry liability that does not transfer to the vendor. When a breach reaches a regulator, the evidence your monitoring program produces determines the scope of your exposure — and most compliance programs built around server-side controls produce the wrong evidence for client-side attacks.
What a SPA breach looks like from the regulator's evidence request
A 60-person SaaS company received a GDPR investigation notice eight months after a customer reported that their session appeared to have been accessed by an unauthorized party. The company had a SOC 2 Type II report, an active vulnerability management program, and server-side access logs covering the relevant period. The regulator's evidence request asked for: all CSP violation reports from the 90-day window preceding the report, browser-side telemetry covering the affected user's sessions, the dependency inventory for the SPA as of the breach date, records of any security testing that covered client-side JavaScript in the prior 12 months, and session token issuance and invalidation records for affected accounts.
The company could satisfy none of these requests completely. CSP was implemented but violation reporting was not configured — no violation logs existed. Browser-side telemetry was not in scope for their monitoring program, which covered server infrastructure. The SPA dependency inventory did not exist as a formal document; dependencies were tracked implicitly through the package-lock.json file, which had been updated multiple times since the breach date. Security testing records covered server-side API endpoints and infrastructure; client-side JavaScript testing had not been conducted as a documented engagement. Session tokens were stored in localStorage — there was no server-side record of which tokens existed or when they were last active. The regulator noted all five gaps as evidence of inadequate technical measures under Article 32, independent of the underlying breach.
Why the client-side attack surface produces the wrong evidence for regulatory compliance
Compliance monitoring programs are built around server-side infrastructure because that is where audit trails exist by default. Web server access logs, database query logs, authentication event logs, API gateway records — all of these are server-side artifacts that capture activity in a format auditors and regulators know how to request and evaluate. The SPA architecture moves application logic to the browser. DOM manipulation, JavaScript execution, local storage reads and writes, and client-side routing decisions happen in an environment where the server sees only the outbound API calls that result from those decisions, not the decisions themselves. A DOM-based XSS attack injects JavaScript into the victim's browser. That JavaScript can read localStorage tokens, capture keystrokes, exfiltrate data to attacker-controlled endpoints, and manipulate the DOM to display fraudulent content. The server logs a normal page load request and then normal API calls authenticated with the victim's token. Nothing in the server logs distinguishes a legitimate session from a compromised one until behavioral analysis on the API side detects the anomaly — if behavioral analysis is running at all.
Example
The evidence gap becomes concrete in a breach scoping exercise. GDPR Article 33 requires notification to include the 'approximate number of data subjects affected' and the 'categories and approximate number of personal data records concerned.' If DOM-based XSS executed in a user's browser and the attacker used a stolen localStorage token to make API calls, the server log shows API calls from the victim's authenticated session. It does not show whether the attacker accessed 10 records or 10,000 records, because the attacker's requests are indistinguishable from the victim's legitimate activity in the log. The organization cannot scope the breach from server-side evidence alone. Regulators have specifically cited this scoping failure as a basis for Article 32 violations — the failure to have monitoring capable of breach scoping is itself a control deficiency, separate from the breach.
The GDPR Article 32 obligation is to implement 'appropriate technical and organisational measures' to ensure a level of security appropriate to the risk. Data protection authorities including the CNIL, the ICO, and the Dutch AP have interpreted this to include monitoring capable of detecting and scoping client-side incidents, not just server-side ones. The argument that client-side attacks are harder to monitor does not constitute a defense — the DPA position is that the difficulty is known in advance and should be addressed in the security architecture.
What the assessments show about the evidence gap
Assessment base: Vulnox SPA and web application security assessments, 2023-2024
CSP implemented in report-only mode indefinitely, producing reports no one reviews
In SPA security assessments at Vulnox, a consistent pattern appears: CSP is deployed in report-only mode because the development team needed time to resolve legitimate violations before moving to enforcement mode. Report-only mode was intended to be temporary. It became permanent because moving to enforcement mode broke functionality that the team did not have time to fix. The CSP generates violation reports to a report-uri endpoint. The reports are not reviewed systematically. No alerting is configured on violation patterns. The policy has been in report-only mode for, in several assessed environments, more than 18 months.
From a security standpoint, a report-only CSP blocks nothing. From a regulatory standpoint, it creates a misleading paper trail — an auditor reviewing the security configuration sees a CSP and marks the control as present. A regulator investigating a breach asks for violation logs and finds months of reports that were never reviewed, which establishes that the control was not being actively managed. The presence of the control becomes evidence of inadequate management rather than evidence of due diligence.
localStorage token storage with no server-side session inventory
The decision to store authentication tokens in localStorage is common in SPA environments because it simplifies token access from JavaScript and survives page refreshes without server interaction. In assessments where Vulnox examines both the authentication architecture and the monitoring program, localStorage token storage consistently creates a scoping gap: there is no server-side record of which tokens are active, when they were last used, or whether they were accessed by JavaScript running in a compromised context. When asked to produce session records for a specific time window, the organization can produce authentication event logs showing when tokens were issued but not what happened to those tokens afterward.
Under frameworks that require breach notification with affected individual counts, this architecture makes accurate scoping structurally impossible for a subset of breach scenarios. The regulatory consequence is not just the breach — it is the inability to demonstrate that you know the scope of the breach, which regulators in GDPR jurisdictions have treated as a separate Article 32 deficiency. The technical fix and the compliance fix are the same: move to HttpOnly cookie-based token storage, which generates server-side issuance and validation records.
Third-party analytics and marketing scripts executing with full DOM access
SPAs commonly load third-party JavaScript from analytics platforms, customer support chat widgets, A/B testing tools, and marketing automation systems. These scripts execute in the same browser context as first-party code and have access to the same DOM, the same localStorage, and the same ability to make network requests. In assessed environments, the third-party script inventory is rarely complete — scripts are added by marketing and product teams without security review, and the CSP often includes broad wildcard allowances for third-party script origins that were added to resolve loading errors rather than through deliberate risk acceptance. One assessed environment was loading 14 distinct third-party JavaScript files, of which the security team could account for 9. The remaining 5 had been added through a tag management system by the marketing team.
Each third-party script is a potential supply chain risk. A compromised analytics vendor who pushes a malicious script update can execute arbitrary JavaScript in every user session on the platform. The organization remains the data controller for any personal data that script accesses or exfiltrates. Regulatory liability does not transfer to the vendor. In the Thailand PDPA and Singapore PDPA contexts, which apply to many of the clients Vulnox works with in Southeast Asia, the data controller obligation to implement appropriate security measures extends explicitly to third-party data processors — and a third-party script running in a browser without a data processing agreement in place is a processing relationship that may not be documented at all.
The security testing that produces a clean report and increases regulatory exposure
Common belief
Organizations that conduct annual penetration tests on their SPA environments treat the clean report as evidence of due diligence. Regulators reviewing breach documentation would presumably see the test record and conclude that appropriate measures were in place.
What we found
In Vulnox gap analysis engagements following SPA incidents, the gap between what the prior penetration test covered and what the breach exploited is consistently large. In none of the post-incident reviews examined did the prior test scope include DOM-based XSS testing, CSP bypass analysis, or third-party script inventory. In most cases, the test report contained a standard disclaimer noting that client-side testing was out of scope. That disclaimer, presented to a regulator, is read as a documented decision to exclude the attack surface that was subsequently breached.
A penetration test scoped to authenticated API endpoints and server-side infrastructure generates a report that is silent on client-side attack surface. Silence in a test report means the tester did not look, not that nothing is there. When a regulator asks for security testing records following a DOM-based XSS breach, a penetration test report that covers API endpoints is worse than no report — it demonstrates that a testing program existed, that someone made decisions about what to include in scope, and that client-side JavaScript testing was not included. The regulator's interpretation is that the organization knew security testing was necessary, conducted it, and chose not to test the attack surface that was ultimately exploited. That sequence is harder to defend than an organization that had no testing program at all, because it implies a deliberate scope decision.
The evidence gaps compliance programs do not close
Session behavior analytics capable of distinguishing legitimate from compromised sessions
Server-side access logs show authenticated API calls. They do not show whether the session behind those calls is legitimate or has been taken over. Behavioral analytics — baseline user activity patterns, geographic anomalies, request rate deviations, unusual field access patterns — can narrow the gap between 'authenticated request' and 'compromised session.' Most SPA compliance monitoring programs do not include behavioral analytics because they are implemented by the infrastructure team against server metrics, not by the security team against application-layer behavioral patterns. After a breach, the inability to identify which sessions were compromised is the most common cause of breach scope inflation — organizations notify more individuals than were actually affected because they cannot exclude anyone.
Subresource Integrity enforcement for third-party scripts
Subresource Integrity allows a browser to verify that a third-party script has not been modified since the hash was recorded. If the script changes — because the vendor was compromised or pushed a malicious update — the browser refuses to execute it. SRI is technically straightforward and is the correct control for managing third-party script supply chain risk. It requires recording the hash of each third-party script at a point in time and updating the hash when the script legitimately changes. In practice, it is absent from most SPA environments because tag management systems, which are how most marketing scripts are loaded, do not support SRI. The tag management system becomes the single point of supply chain failure for every script it manages.
Dependency provenance records at each deployment
When a regulator or forensic examiner asks what version of a library was running in the SPA at the time of a breach, the answer needs to come from deployment records that were captured at deployment time — not reconstructed from the current package-lock.json. Package-lock.json changes with every npm install. If the deployment artifact is not preserved with its dependency manifest, the dependency state at the time of a historical breach cannot be established with certainty. This matters in regulatory investigations where the question is not just what vulnerability existed but whether the organization had the information to know about it before the breach — for example, whether the CVE for the vulnerable library version was published before or after the deployment that introduced it.
Where regulatory enforcement on SPA security is heading
Within 24 months, a GDPR enforcement action will explicitly cite failure to implement browser-side monitoring as an Article 32 inadequacy in a SPA breach case, establishing a precedent that client-side telemetry is a required technical measure for organizations processing personal data through SPA architectures.
Data protection authorities are developing technical expertise faster than organizations are updating their monitoring programs. The ICO, CNIL, and Dutch AP have all published technical guidance indicating that monitoring must be commensurate with the architecture. SPA architectures have been mainstream for over a decade. The argument that client-side monitoring is technically novel is no longer available. The enforcement action will follow a breach where the DPA examines the monitoring program and finds it was designed entirely for server-side infrastructure despite a predominantly client-side application architecture.
Confidence: mediumA published GDPR enforcement decision by end of 2027 that cites client-side monitoring absence as a specific Article 32 inadequacy, distinct from the underlying breach violation.Third-party JavaScript supply chain liability will be tested in a regulatory context before the end of 2027, with a DPA asserting that an organization's failure to inventory and monitor third-party scripts executing in their SPA constitutes a failure to implement appropriate measures under data protection law, independent of whether the scripts caused a breach.
The regulatory logic already exists: data controllers are responsible for appropriate measures covering all processing in their environment, including processing by third-party code they deploy. The technical mechanism — third-party JavaScript with DOM access — is increasingly well understood by DPA technical staff. The gap between regulatory theory and enforcement action is narrowing as DPAs build technical capacity. An organization with 20 unreviewed third-party scripts in their SPA and no data processing agreements covering the associated vendors is already non-compliant under existing frameworks; the enforcement action formalizes what is already a violation.
Confidence: lowA published DPA enforcement action or formal guidance document by end of 2027 explicitly addressing third-party JavaScript inventory as a data controller obligation.
Penetration testing scoped to exclude client-side JavaScript should require documented risk acceptance
Every penetration test engagement letter that excludes DOM-based XSS testing, CSP bypass analysis, and third-party script review should require the client to sign a risk acceptance document acknowledging what is not being tested and why. Currently, scope exclusions appear in the report as a methodology note and are not presented to the client as decisions they are actively making. The result is that organizations believe they have tested their security posture when they have tested a subset of it. The consultant is protected by the scope clause. The organization is not protected at all, because a regulator examining the test record does not distinguish between 'not tested' and 'tested and found secure.' Requiring documented risk acceptance for scope exclusions would force the conversation about what client-side testing costs versus what regulatory exposure the exclusion creates.
Counterargument
The counterargument is that scope decisions are a function of budget and time, and requiring formal risk acceptance for every exclusion adds process overhead that slows down engagements and may discourage organizations from conducting any testing at all. A scoped test is better than no test. This is correct in the narrow sense that partial coverage is better than zero coverage. It is less correct when the excluded scope is the attack surface that regulators will examine after a breach. The conversation about what to exclude should happen explicitly, with the client understanding the regulatory implications, not implicitly through boilerplate methodology language.
The compliance gap you can close this week without an engagement
Pull your SPA's CSP header and check two things: whether report-uri or report-to is configured, and whether the policy is in enforcement mode or report-only mode. If violation reporting is not configured, you have no evidence that the policy is being actively managed — which is what a regulator will ask for first. If the policy is in report-only mode, document why and set a date for enforcement transition with the specific violations that need resolving before the switch. Then pull your deployment records and verify that you have the dependency manifest — package-lock.json or equivalent — captured as of each production deployment, not just the current state. Those two checks do not require a penetration test or a new tool. They close two of the most common regulatory evidence gaps before the next assessment is scoped.
Further Reading
Vulerability Assessment
vulnerability assessmentGap Analysis
gap analysisNIST Vulnerability Assessment Definition
NIST's vulnerability assessment definitionOWASP Web Security Testing Guide
OWASP web security testingNational Vulnerability Database NIST
NIST National Vulnerability Database
Frequently Asked Questions
What SPA security vulnerabilities create regulatory notification obligations?
Any SPA vulnerability that results in unauthorized access to personal data triggers notification obligations under GDPR, Thailand PDPA, and equivalent frameworks. DOM-based XSS is the highest-risk class because it executes in the victim's browser without generating server-side log entries, making the scope of data access difficult to establish. If you cannot determine which user accounts were affected or what data was accessed, regulators treat that uncertainty as evidence of inadequate monitoring — which itself can constitute a separate violation from the underlying breach.
Why does DOM-based XSS not appear in server-side audit logs?
DOM-based XSS executes entirely in the browser. The malicious payload is processed by the victim's JavaScript engine, not the server. The server never sees the payload — it sees a normal page request followed by normal API calls made using the stolen session token. Server-side WAFs and access logs record the API calls, not the mechanism that enabled them. Forensic attribution of a DOM-based XSS breach requires browser-side telemetry, CSP violation reports, or behavioral anomaly detection on the API side — none of which most compliance monitoring programs include.
What evidence does a regulator request after a SPA breach that organizations typically cannot produce?
Regulators investigating SPA breaches commonly request: timestamped evidence of when the vulnerability was introduced into the codebase, records of any security testing that should have detected it, CSP violation logs covering the breach window, session token issuance and invalidation records, and evidence that affected user data was identified and scoped accurately. Organizations that lack browser-side telemetry cannot scope the breach. Organizations without dependency scanning records cannot demonstrate due diligence on third-party library vulnerabilities. Both gaps translate directly into regulatory exposure beyond the underlying breach.
How should SPA token storage be configured to satisfy both security and regulatory evidence requirements?
HttpOnly cookies with SameSite=Strict prevent JavaScript access to tokens and eliminate the localStorage theft vector. They also produce server-side issuance and validation records that exist in audit logs, which localStorage tokens do not. From a regulatory evidence standpoint, cookie-based token management creates a paper trail — when a token was issued, to which user, and when it was invalidated — that localStorage storage cannot provide. The security argument and the regulatory evidence argument point to the same implementation.
What is the regulatory risk of an incomplete breach scope after a SPA incident?
Under GDPR Article 33, notification must include the approximate number of individuals affected and categories of personal data involved. If DOM-based XSS executed in an unknown number of browsers before detection, and server logs cannot reconstruct which accounts were accessed using stolen tokens, the organization cannot satisfy the scoping requirement. Regulators do not accept 'we cannot determine scope' as an answer — they treat it as evidence of inadequate monitoring that pre-existed the breach. GDPR enforcement actions have cited failure to scope breaches accurately as a separate ground for fines beyond the breach itself.
How do third-party JavaScript dependencies in SPAs create compliance exposure?
A vulnerable third-party JavaScript library loaded by a SPA executes with the same browser permissions as first-party code. If the library introduces an XSS vector or exfiltrates data through its own endpoints, the organization that deployed it remains the data controller under GDPR and equivalent frameworks — responsibility does not transfer to the library vendor. Regulators have treated failure to maintain a software inventory of third-party dependencies and failure to monitor for known vulnerabilities as evidence of inadequate technical measures, which is a separate Article 32 violation from any breach that results.
What CSP configuration mistakes create regulatory evidence gaps?
The most consequential CSP mistake is implementing a policy without configuring report-uri or report-to directives. A CSP without violation reporting produces no evidence that the policy was actively monitored. If a breach occurs and an attacker bypassed the CSP, regulators can ask: what violation reports did you receive, and what did you do with them? An organization with no violation reporting configured has no answer. A second common mistake is deploying CSP in report-only mode for so long that it never transitions to enforcement — the policy generates reports but blocks nothing, which satisfies no security objective while creating a misleading paper trail.
Related Articles

API security assessment: what automated tools miss and manual testing finds
Automated API security tools find the vulnerabilities they were designed to look for. The findings that matter in real assessments, broken object-level authorization, JWT algorithm confusion, and unauthenticated internal endpoints, require a tester who understands what the API is supposed to do before probing what it actually does.

CVSS score explained: what the metric captures, what it misses, and how to fix your prioritization
In 40% of Vulnox assessments, vulnerabilities scored CVSS 9.0 or higher were on systems with compensating controls that materially reduced the actual risk. The score was accurate. The priority order it implied was not. This guide covers how to use CVSS correctly and what to layer on top of it.

Post-breach vulnerability assessment: what the attacker left behind
Most post-breach assessments start too late and end too early. They confirm what was hit, not what the attacker mapped before they moved. The second breach usually comes from the reconnaissance that happened in the first.
Ready to Secure Your Digital Assets?
Get a comprehensive vulnerability assessment for your website today.