Content Security Policy
Content Security Policy (CSP) is a browser security mechanism that lets a server
declare which content sources a page may load and execute, mitigating cross-site-scripting (XSS) and data-injection
attacks. Juneau auto-generates HTML with inline <style>/<script> blocks (the HtmlDoc serializer, the Swagger UI,
the OpenAPI UI, and menu-item widgets), so a CSP is the standard way to lock those pages down.
Juneau models a policy as a first-class, immutable HTTP header bean,
ContentSecurityPolicy,
assembled with a fluent
ContentSecurityPolicy.Builder.
Both live in juneau-rest-common alongside the other modern HTTP header beans.
CSP is off by default. Turning a policy on silently would break existing apps, so you must opt in.
Building a policy
The builder exposes typed setters for the common directives plus a generic directive(name, sources...) escape hatch
so new directives never require an API change. Source-expression keywords are exposed as constants (SELF, NONE,
UNSAFE_INLINE, UNSAFE_EVAL, STRICT_DYNAMIC) and helpers (nonce(token), scheme(scheme), hash(alg, b64)).
import static org.apache.juneau.http.header.ContentSecurityPolicy.Builder.*;
String value = ContentSecurityPolicy.create()
.defaultSrc(SELF)
.scriptSrc(SELF, scheme("https"))
.imgSrc(SELF, "data:")
.objectSrc(NONE)
.baseUri(SELF)
.frameAncestors(SELF)
.build();
// => "default-src 'self'; script-src 'self' https:; img-src 'self' data:;
// object-src 'none'; base-uri 'self'; frame-ancestors 'self'"
Setting the same directive twice replaces its source list (while preserving its original position), and a directive
with no sources renders as a bare keyword (e.g. directive("upgrade-insecure-requests")).
Emitting the header
Because ContentSecurityPolicy is an ordinary string header, it flows through the existing response-header path. The simplest opt-in is the static string form on the REST annotation:
@Rest(
defaultResponseHeaders={
"Content-Security-Policy: default-src 'self'; object-src 'none'"
}
)
public class MyResource extends BasicRestServlet { ... }
For programmatic assembly, contribute the bean through a defaultResponseHeaders
HttpHeaderList factory method:
@Rest(...)
public class MyResource extends BasicRestServlet {
@Bean(name="defaultResponseHeaders")
public HttpHeaderList responseHeaders() {
return HttpHeaderList.of(
ContentSecurityPolicy.create()
.defaultSrc(SELF)
.objectSrc(NONE)
.toHeader()
);
}
}
toHeader() returns a ContentSecurityPolicy whose name is Content-Security-Policy (or
Content-Security-Policy-Report-Only when report-only mode is enabled).
Report-only mode
Operators can deploy a policy in observe-only mode first, watch violations, tune, then enforce. reportOnly() flips
the header name to Content-Security-Policy-Report-Only; the reportUri(...) / reportTo(...) directives point a
browser at a violation collector (the collector endpoint itself is out of scope — point at your own).
ContentSecurityPolicy csp = ContentSecurityPolicy.create()
.defaultSrc(SELF)
.reportTo("csp-endpoint")
.reportOnly()
.toHeader();
// Header name => "Content-Security-Policy-Report-Only"
The strict-starter preset
strictStarter() returns a builder pre-populated with a ready, nonce-based baseline:
ContentSecurityPolicy.strictStarter().build();
// => "default-src 'self'; script-src 'self' 'nonce-{nonce}'; style-src 'self' 'nonce-{nonce}';
// img-src 'self' data:; connect-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'"
Because Juneau's built-in pages emit inline <script>/<style>, a strict 'self'-only policy needs a per-request
nonce to allow those inline blocks. The preset embeds a
NONCE_PLACEHOLDER
token ({nonce}); the REST layer mints one cryptographically-random nonce per response, rewrites the placeholder via
resolveNonce(value, nonce), and stamps the same nonce onto every inline tag the serializer emits so the header
and the markup agree.
Do not combine a nonce with 'unsafe-inline' in script-src — browsers ignore 'unsafe-inline' whenever a nonce (or
hash) is present. The strict starter deliberately omits 'unsafe-inline'.
See also
- ContentSecurityPolicy
- ContentSecurityPolicy.Builder
- Content Security Policy Level 3 (W3C)
- REST Security — other REST-layer security considerations.