Security and Nonce
The term “nonce” in refers to something “temporarily created, randomly generated, and used only once.” When paired with the “Content Security Policy” (CSP), it determines whether the request for a given element will be executed.
A typical use case is as follows:
On the frontend, the content security policy for a page can be specified using the <meta>
element, for example:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'" />
It allows only static resources from the same domain to be loaded, while also preventing the execution of any inline JavaScript on the page. This helps prevent XSS attacks.
For example, here is some page code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
<title>CSP unsafe-inline</title>
</head>
<body>
<p>no alert</p>
<script>
alert('hello world');
</script>
</body>
</html>
If a CSP policy is specified within the <header>
element, inline <script>
elements will not execute the JavaScript code, and the page will not show any alert messages.
Not only that, but the page will also report some errors:
Refused to execute inline script because it violates the following Content Security Policy directive: “default-src ‘self’”. Either the ‘unsafe-inline’ keyword, a hash (‘sha256-Ucj61+zsMpSab6QdWBaKF0dD7g1XPR4K+DJ4ZkaowqY=’), or a nonce (‘nonce-…’) is required to enable inline execution. Note also that ‘script-src’ was not explicitly set, so ‘default-src’ is used as a fallback.
But this restriction is too strict. The developer’s intention was to limit the loading and execution of external resources, which results in inline JS not being executed.
However, there is a solution. The unsafe-inline policy can be used, for example:
<meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline'" />
At this point, the alert will be triggered and the code will execute as expected.
However, if you search for information about CSP, it is universally recommended not to use ‘unsafe-inline’, as it renders most security restrictions ineffective. For example, if the implementation is flawed, XSS attacks like the one shown in the image below can occur.
/app?name=<script>alert('xss');<script>
This creates a dilemma: some inline code is written by trusted developers, yet it is not allowed to execute. Should we throw out the baby with the bathwater?
At this point, the nonce strategy can be used to allow certain inline JS to execute, thus avoiding the global impact of the unsafe-inline policy on the entire page.
How to implement it?
Generally, it involves the following steps:
- Generate a random Base64 string as a key, containing at least 128 bits of data. This value must be unique and regenerate with every page load. The following code demonstrates how to generate this in a Node.js environment:
const crypto = require("crypto");
crypto.randomBytes(16).toString("base64");
// '8IBTHwOdqNKAWeKl7plt8g=='
On the client-side, you can try the following method:
btoa(crypto.randomUUID())
// NDhkODkxMzYtNGUxZS00N2NjLTk1YTItNWMyOTM4YzdhZGJj
- Use this random string as the value of the nonce attribute, for example:
<script nonce="NDhkODkxMzYtNGUxZS00N2NjLTk1YTItNWMyOTM4YzdhZGJj">
// …
</script>
- Specify this nonce value in the Content-Security-Policy (CSP) policy, prefixed with
nonce-
.
<meta http-equiv="Content-Security-Policy" content="script-src 'nonce-NDhkODkxMzYtNGUxZS00N2NjLTk1YTItNWMyOTM4YzdhZGJj'">
At this point, only the <script>
code with a matching nonce value will execute.
Native Popups vs. Popover UI Elements
The popover attribute is a relatively new feature.
It allows any element to trigger a browser-level popover effect when clicked.
In fact, it’s quite simple to implement, and can be achieved with just a few HTML attributes. The functionality is clear from the code:
Here’s a simple example:
<button popovertarget="imgPopover">click me</button>
<div popover id="imgPopover">
<img src="https://raw.githubusercontent.com/trevortylerlee/n1/main/n1.jpeg" width="400" height="400" />
</div>
The popovertarget attribute is set on the button. When clicked, it automatically finds the element with a matching id and the popover attribute.
The element with the popover attribute is hidden by default, has a border, a transparent background overlay, and is displayed at the top layer with the highest z-index.
It supports shortcut keys like ESC, making it highly convenient to use. It’s one of the best options for implementing floating popups.
Compatibility
Regarding compatibility, it is clear that all major modern browsers will support it. Currently, Chrome and Safari already support it, while Firefox has experimental support. Within a year or two, it should be ready for production use.