Hi,
I gave a try to cap.js for self hosted alternative to turnstile. (This is a great idea to integrate into BW by the way, thanks!)
It seems like Bunkerweb implementation of it can be improved. Currently I needed to set
CONTENT_SECURITY_POLICY: "object-src 'none'; form-action 'self'; frame-ancestors 'self'; script-src 'unsafe-eval';"
If not, cap.js stops at 99% with error
Content-Security-Policy: The page's settings blocked the execution of an inline script because it violates the following directive: script-src 'nonce-xxx' ``https://cap.example.com`` 'wasm-unsafe-eval' ('unsafe-eval' is missing)
As I am not familiar with what should be fixed exactly, here is the answer from Claude:
The Cap widget dynamically injects scripts at runtime (for the pako decompression fallback and the instrumentation challenge iframe). Because these scripts are injected dynamically by the widget, they need either 'unsafe-eval' or a valid nonce in the script-src CSP directive to be allowed by the browser.
Currently, BunkerWeb’s generated challenge page sets a script-src CSP that includes a nonce (e.g. 'nonce-xxxx'), https://cap.example.com, and 'wasm-unsafe-eval' — but does not include 'unsafe-eval'. This causes the Cap widget to fail at 99% with the following browser error:
Content-Security-Policy: The page's settings blocked the execution of an inline script
because it violates the following directive: script-src 'nonce-xxx' https://cap.example.com
'wasm-unsafe-eval' ('unsafe-eval' is missing)
The clean fix Cap.js provides
The Cap widget natively supports window.CAP_SCRIPT_NONCE — when set, it stamps that nonce onto all scripts the widget injects dynamically, making them trusted under the existing nonce-based CSP without needing 'unsafe-eval' at all. See: https://trycap.dev/guide/widget
What BunkerWeb needs to add
In the Cap.js challenge page template, before the widget is initialized, add:
html
<script nonce="$SCRIPT_NONCE">
window.CAP_SCRIPT_NONCE = '$SCRIPT_NONCE';
</script>
Where $SCRIPT_NONCE is the same nonce BunkerWeb already generates and uses for its own scripts on the challenge page. This would make the Cap.js integration work correctly with strict CSP, without requiring the security-weakening 'unsafe-eval' directive.
Hope this is helpful enough.
Wishing you a good day!