Skip to main content

Content security policy

Nonces

In templ script templates are rendered as inline <script> tags.

Strict Content Security Policies (CSP) can prevent these inline scripts from executing.

By setting a nonce attribute on the <script> tag, and setting the same nonce in the CSP header, the browser will allow the script to execute.

info

It's your responsibility to generate a secure nonce. Nonces should be generated using a cryptographically secure random number generator.

See https://content-security-policy.com/nonce/ for more information.

Setting a nonce

The templ.WithNonce function can be used to set a nonce for templ to use when rendering scripts.

It returns an updated context.Context with the nonce set.

In this example, the alert function is rendered as a script element by templ.

templates.templ
package main

import "context"
import "os"

script onLoad() {
alert("Hello, world!")
}

templ template() {
@onLoad()
}
main.go
package main

import (
"fmt"
"log"
"net/http"
"time"
)

func withNonce(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
nonce := securelyGenerateRandomString()
w.Header().Add("Content-Security-Policy", fmt.Sprintf("script-src 'nonce-%s'", nonce))
// Use the context to pass the nonce to the handler.
ctx := templ.WithNonce(r.Context(), nonce)
next.ServeHTTP(w, r.WithContext(ctx))
})
}

func main() {
mux := http.NewServeMux()

// Handle template.
mux.HandleFunc("/", templ.Handler(template()))

// Apply middleware.
withNonceMux := withNonce(mux)

// Start the server.
fmt.Println("listening on :8080")
if err := http.ListenAndServe(":8080", withNonceMux); err != nil {
log.Printf("error listening: %v", err)
}
}
Output
<script type="text/javascript" nonce="randomly generated nonce">
function __templ_onLoad_5a85() {
alert("Hello, world!")
}
</script>
<script type="text/javascript" nonce="randomly generated nonce">
__templ_onLoad_5a85()
</script>