These headers are configured server-side in .htaccess via Apache's mod_headers module and apply to every page on the site. They instruct browsers on how to handle content, which resources to trust, and which features to permit or deny - before a single line of JavaScript runs. External verification: SecurityHeaders.com report →

Fingerprint Suppression

Server Suppressed

Value: removed entirely

Apache normally sends a Server header identifying the web server software and version number. That's a free gift to anyone running a vulnerability scanner - they can target known CVEs without even needing to probe. This header is stripped entirely before the response leaves the server. A browser doesn't need to know what's serving it to display a page.

X-Powered-By Suppressed

Value: removed entirely

PHP sets this by default to something like PHP/8.2.18. Same problem as Server - it hands out version fingerprinting data for free. Gone.

Transport Security

Strict-Transport-Security Set

max-age=31536000; includeSubDomains; preload

HSTS tells browsers to always use HTTPS for this domain - never HTTP - for the next 365 days (max-age=31536000). Once a browser sees this header, it will refuse to make an unencrypted connection to chrisbmn.com for the entire duration, even if the user types http:// manually.

includeSubDomains extends this requirement to every subdomain. preload opts the domain into browser-maintained preload lists - meaning a brand-new browser that has never visited the site will already refuse HTTP before the first connection is ever made. This header is only sent over HTTPS; an HTTP response doesn't count and won't be trusted.

Core Security Headers

X-Content-Type-Options Set

nosniff

Prevents browsers from MIME-sniffing a response away from the declared Content-Type. Without this, a browser might decide on its own that a file is JavaScript and execute it, even if the server said it was plain text. nosniff says: trust what the server declares the file is, period.

X-Frame-Options Set

SAMEORIGIN

Controls whether this page can be embedded inside a <frame>, <iframe>, or <object> on another domain. SAMEORIGIN allows embedding only from the same origin. This is the primary defense against clickjacking - an attack where a malicious site overlays a transparent version of your page on top of theirs and tricks users into clicking things they didn't intend to. The CSP frame-ancestors directive enforces this at the policy layer as well.

Referrer-Policy Set

strict-origin-when-cross-origin

Controls how much referrer information is included when following a link. With this policy: navigating within the same origin sends the full URL; navigating to a different origin sends only the origin (https://chrisbmn.com), never the full path; downgrading from HTTPS to HTTP sends nothing at all. This prevents URL paths - which might contain usernames, tokens, or search terms in query strings - from leaking to third-party sites or analytics platforms.

X-Permitted-Cross-Domain-Policies Set

none

Prevents Adobe Flash and PDF clients from loading cross-domain policy files hosted on this domain. With none, no policy files are permitted. Flash is long dead, but this header still shuts the door on legacy runtimes that might look for a crossdomain.xml they shouldn't be reading.

Permissions Policy

Permissions-Policy Set

Grants or denies browser feature access on a per-feature, per-origin basis. Every feature this site doesn't actually use is explicitly disabled. If JavaScript on the page - whether from this site or injected by a third-party script - ever tries to access the camera, microphone, geolocation, or payment APIs, the browser will refuse before the request reaches the hardware or OS.

accelerometer
autoplay
camera
display-capture
encrypted-media
geolocation
gyroscope
magnetometer
microphone
midi
payment
screen-wake-lock
usb
xr-spatial-tracking
fullscreen (self)
picture-in-picture (self)

Content Security Policy

Reporting-Endpoints Set

csp-endpoint="https://csp.chrisbmn.com/report.php"

Defines a named reporting endpoint where browsers automatically POST JSON reports when a CSP violation occurs - meaning a resource was blocked that shouldn't have been, or something that shouldn't have loaded tried to. This gives real-time visibility into policy violations without the user needing to do anything. It's also how misconfigurations surface before they affect users.

Content-Security-Policy Set

CSP is the primary browser-side defense against XSS and data injection. It defines an explicit allowlist of origins from which resources may be loaded. Anything not on the list is blocked - even if an attacker manages to inject a script tag. The policy is enforced by the browser and cannot be bypassed by page-level JavaScript.

default-src 'self'

Catch-all fallback: only load from the same origin unless a more specific directive applies.

base-uri 'self'

Restricts <base> elements to same-origin. Prevents base-tag injection from hijacking all relative URLs on the page.

object-src 'none'

Blocks plugins entirely - Flash, Java applets, and similar. There is no legitimate use for them on this site.

form-action 'self'

Form submissions can only go to the same origin. Prevents an attacker from redirecting POST data to an external server.

frame-ancestors 'self'

Only this origin may embed this page in a frame. Reinforces X-Frame-Options at the CSP level - two locks on the same door.

upgrade-insecure-requests

Automatically upgrades any HTTP resource loads to HTTPS before the request is made. Catches hardcoded http:// URLs without requiring code changes.

script-src 'self' 'unsafe-inline' + CDN allowlist

Scripts from this origin and a short allowlist of trusted CDNs: Font Awesome kit, Google Tag Manager, Microsoft Clarity, reCAPTCHA, Ko-fi, and BunnyCDN. 'unsafe-inline' is a known trade-off required by GTM and FA kit - tracked for future nonce-based tightening.

style-src 'self' 'unsafe-inline' + CDN allowlist

Same pattern as script-src for stylesheets. Inline styles are used extensively in the site's PHP templates.

img-src 'self' data: + CDN / analytics origins

Images from self, inline data URIs, BunnyCDN, Gravatar (blog comment avatars), YouTube thumbnails, and analytics pixel origins.

font-src 'self' + BunnyCDN + Font Awesome

Web fonts only from this origin, BunnyCDN, and Font Awesome's delivery CDN.

frame-src YouTube, Google, Ko-fi

iframe embeds are allowed for YouTube videos in blog posts, Google reCAPTCHA, and the Ko-fi support widget.

connect-src Analytics + Font Awesome + Ko-fi

fetch() and XHR are allowed to self and the analytics/font services the site actively uses.

report-uri / report-to csp.chrisbmn.com

Violation reports are sent to the self-hosted CSP collector endpoint for review.

CORS

Access-Control-Allow-Origin Conditional

Reflects Origin only when it matches a trusted CDN domain

CORS headers are required because the site loads assets from BunnyCDN (assets-cbmn.b-cdn.net, cdn.chrisbmn.com). Rather than using a blanket * - which would allow any site to make credentialed cross-origin requests - the header is only set when the incoming Origin matches a hardcoded allowlist of known CDN origins. Everyone else gets no CORS header at all.

assets-cbmn.b-cdn.net cdn.chrisbmn.com assets.chrisbmn.com
Vary Set

Origin

Required alongside the conditional CORS header. Tells caches - CDNs, proxies, and browsers - that the response may differ depending on the Origin request header. Without this, a CDN might cache a CORS-allowed response and incorrectly serve it to a request from a non-allowed origin, leaking the allowed response to an unauthorized caller.

← Security Disclosure Policy TLS / SSL Configuration →