csp

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 18, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package csp provides middleware that builds and sets a Content-Security-Policy response header from a directive map. It is the Go analogue of Helmet's contentSecurityPolicy middleware from the Node ecosystem, packaged as a drop-in express.Handler. Where Helmet accepts a directives object and renders it into the header string, this port accepts a Go map of directive names to source lists and does the same rendering, then attaches the value to every response that flows through it.

Use this middleware to instruct browsers about which origins are legitimate sources of scripts, styles, images, fonts, frames, and other resources, which is the single most effective defense against cross-site scripting and resource-injection attacks. A policy of "default-src 'self'" alone already blocks inline scripts and third-party code; tighten it further by adding directives such as "script-src", "style-src", or "img-src". Mount it globally with app.Use so the header is present on every response, or attach it to a specific router or path prefix when only part of the application needs a policy.

Operationally the middleware belongs near the front of the chain, before any handler that writes the response body, because a Content-Security-Policy header is only honored if it is sent with the response. On each request it writes a single header — Content-Security-Policy by default, or Content-Security-Policy-Report-Only when Options.ReportOnly is set — and then always calls next() so the request proceeds untouched. The header value is computed once when New builds the handler, not per request, so the cost at request time is a single res.Set. No request headers or request state are read; the middleware is purely additive to the response.

The policy string is produced by Build, which sorts directive names alphabetically for a deterministic, stable header value, joins each directive's sources with spaces, and separates directives with "; ". A directive whose source list is empty or nil is emitted as a bare keyword (for example "upgrade-insecure-requests") with no trailing value. When Options.Directives is empty the middleware falls back to the safe default {"default-src": {"'self'"}}, so the zero-value Options is usable and yields "default-src 'self'". Report-only mode sends the policy for monitoring without enforcing it, letting you collect violation reports before switching to enforcement.

Compared with Helmet's contentSecurityPolicy, this port keeps the same header-building semantics — directive map in, policy string out, enforce or report-only — but is deliberately minimal. It does not ship Helmet's baked-in default directive set beyond the single "default-src 'self'" fallback, does not generate per-request nonces (see the sibling cspnonce package for that), and does not offer per-directive functions for dynamic values; every source is a static string supplied at construction time. Callers who need nonces or hashes should compose this package with their own logic or use cspnonce.

Example

Example builds a Content-Security-Policy middleware from a directive map and mounts it on an express application. The middleware sets the header on every response before the route handler runs, so the policy is present regardless of what the handler writes. Directive names are emitted in sorted order, giving a deterministic header value that is safe to assert against. Here we allow scripts from the same origin plus a CDN while keeping the default source restricted to 'self'. The example drives the app with httptest and prints the resulting header so the exact policy string is visible.

package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/malcolmston/express"
	"github.com/malcolmston/express/middleware/csp"
)

func main() {
	app := express.New()
	app.Use(csp.New(csp.Options{Directives: map[string][]string{
		"default-src": {"'self'"},
		"script-src":  {"'self'", "https://cdn.example.com"},
	}}))
	app.Get("/", func(req *express.Request, res *express.Response, next express.Next) {
		res.Send("ok")
	})

	rec := httptest.NewRecorder()
	app.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/", nil))

	fmt.Println(rec.Header().Get("Content-Security-Policy"))
}
Output:
default-src 'self'; script-src 'self' https://cdn.example.com

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Build

func Build(directives map[string][]string) string

Build renders a directive map into a Content-Security-Policy header value. Directives are sorted by name and each directive's sources are joined with spaces; directives are separated by "; ".

func New

func New(opts ...Options) express.Handler

New returns middleware that sets a Content-Security-Policy header.

Types

type Options

type Options struct {
	// Directives maps a CSP directive name (e.g. "default-src", "script-src")
	// to its list of source expressions. When empty, a default of
	// {"default-src": {"'self'"}} is used. Directive names are emitted in
	// sorted order for a deterministic header value.
	Directives map[string][]string

	// ReportOnly, when true, sets Content-Security-Policy-Report-Only instead
	// of Content-Security-Policy.
	ReportOnly bool
}

Options configures the csp middleware. The zero value is usable and yields the default policy "default-src 'self'".

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL