Two options: (A) CloudFront Response Headers Policy (easiest) or (B) a CloudFront Function for full control.
Create a policy once and attach it to your distribution’s Behaviors. Suggested values:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Content-Security-Policy: default-src 'self'; img-src 'self' data:; script-src 'self'; style-src 'self' 'unsafe-inline';
Referrer-Policy: strict-origin-when-cross-origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Permissions-Policy: geolocation=(), microphone=(), camera=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin
Note: page uses inline CSS, so CSP includes 'unsafe-inline'
for style-src
. If you move styles to a static CSS file later, you can tighten CSP.
Attach as a Viewer Response function on the behavior serving HTML.
function handler(event) {
var resp = event.response;
var h = resp.headers;
h['strict-transport-security'] = {value: 'max-age=63072000; includeSubDomains; preload'};
h['content-security-policy'] = {value: "default-src 'self'; img-src 'self' data:; script-src 'self'; style-src 'self' 'unsafe-inline'"};
h['referrer-policy'] = {value: 'strict-origin-when-cross-origin'};
h['x-content-type-options'] = {value: 'nosniff'};
h['x-frame-options'] = {value: 'DENY'};
h['permissions-policy'] = {value: 'geolocation=(), microphone=(), camera=()'};
h['cross-origin-opener-policy']= {value: 'same-origin'};
h['cross-origin-resource-policy']= {value: 'same-origin'};
return resp;
}
For non-HTML (PNG/CSS/JS), you can optionally attach the same function or let the Response Headers Policy apply globally.
/index.html
and /docs/*
.