Connection Allowlists
5/24/2026 by Tim Johns
I noticed a relatively innocuous "Connection Allowlists" reference in the recent Chrome 148 Release Notes, and I was intrigued.
Connection Allowlists is a feature designed to provide explicit control over external endpoints by restricting connections initiated using the Fetch API or other web platform APIs from a document or worker.
It sounded a bit like Content Security Policy (CSP). CSP is a set of specifications that make the web a tremendously safer place by allowing web sites to specify what can and can't be done, in general terms, by content that is referenced by the web page. For example, a web site that accepts payments can serve a carefully-crafted CSP header that would prevent malicious browser extensions, compromised ads, or the site's own poorly sanitized user-generated content from allowing threat actors to access your payment data. It's not the only mechanism a site should use, but it's one layer of defense-in-depth. Defense-in-depth (that is, multiple layers) is absolutely crucial in a system with a lot of moving parts like, oh, say...the web.
"Carefully-crafted CSP header" is doing a lot of work in that last paragraph -- as I might put it in my East Texas vernacular: CSP can be a real pain in the ass.
I say that despite my very strongly-held opinion that CSP plays an absolutely crucial role in making the web a much safer place, and should be implemented anywhere that privacy and security are important...which is pretty much everywhere. So CSP is critical, but it's hard for teams -- especially small teams -- to get right. It seems pretty far down on the list of things most front-end devs I know care about, which is unfortunate, because front-end devs are the ones who generally know what the CSP should actually contain. And it's even further down on the list of things most of the back-end devs I know care about. The Infrastructure/DevSecOps/Platform Engineering/SRE folks I know care a LOT...but in any given situation, they're unlikely to have the context to craft the CSP, so spend a lot of time in confusing conversations with the front-end folks.
Full-stack generalists like me are probably in the ideal spot to understand and implement CSP, but speaking as a full-stack generalist, when you wear a lot of hats, you get spread thin, and it's hard to focus, and CSP deserves a bit of focus.
So anyway, I got a little excited and took a look at the Connection Allowlists Draft Community Group Report document published by the Web Platform Incubator Community Group (WICG). The WICG is a group that incubates ideas from the web developer community, until they can be migrated to a more formal World Wide Web Consortium (W3C) Working Group. Basically these are the folks that design the web.
It didn't take me long to figure out it's a LOT like CSP -- but less redundant, less error-prone, and with a more workable syntax. The WICG didn't bury the lede -- they spelled it out right there in the first few paragraphs of the Draft Community Report doc.
OK! So I went from intrigued (while reading the Chrome release notes) to excited (while reading the Draft Community Report) to motivated. Time to play.
First, I signed up for the corresponding Chrome origin trial by clicking through the link in the Chrome 148 Release Notes, which allowed me to get a token value to serve in the Origin-Trial header, alongside the new Connection-Allowlist. As I write this, I'm not 100% certain this is necessary after Chrome 148, but it seemed logical at the time. If I get a chance I may go back and see if Chrome 148 honors Connection-Allowlist without it. But it was quick and easy in any case.
After that, I went to the specification and cooked up my Connection-Allowlist header (or, more precisely, Connection-Allowlist-Report-Only - the non-enforcing version that only reports violations rather than blocks them). I also noticed that the reporting endpoint for Connection-Allowlist is specified by a Reporting-Endpoints header, which differs from the mechanism I was originally using for CSP on the site I was experimenting with. (Side note: that makes at least three flavors of reporting-endpoint specification I'm juggling -- between CSP, COOP, NEL, etc., and now Connection-Allowlist, which means I should probably go look up the latest on which are deprecated by the latest Reporting-Endpoints, clean all that up in my headers if I can, and write about that as well. Another day.)
After a bit of experimentation and some trial-and-error, I ultimately had my headers:
Origin-Trial: <ORIGIN_TRIAL_TOKEN_GOES_HERE>
Connection-Allowlist-Report-Only: (response-origin "https://api.dev.epicroadtripplanner.com"); report-to=default
Reporting-Endpoints: default="https://<redacted>.com/report-to"
By serving these headers, my site tells Chrome that it's in the origin trial for the Connection-Allowlist (and Connection-Allowlist-Report-Only) headers, and that it should report any JavaScript fetch (or other supported request type) that goes anywhere besides the site itself and api.dev.epicroadtripplanner.com.
(Note: I'm redacting my default reporting endpoint, not because it's a secret -- it can't be, since it's served publicly in the header -- but because I don't want anyone or an LLM copying the headers above verbatim and inadvertently sending a bunch of their own error reports to my reporting site, filling it with noise and probably blowing out my quotas. A former co-worker had that happen with his public NTP server, and I really hope he can laugh about it now 20+ years later, but I'm sure it wasn't funny at the time. But I digress. Shoot me an email and let me know if I should write up how to deploy a very lightweight reporting endpoint just for experimentation; it's pretty easy.)
To test it, I added a bit of JavaScript to one of the pages on my personal dev site, to try to fetch campground data for Fort Casey:
try {
console.log("Fetching from dev (allow-listed)...")
const response = await fetch("https://api.dev.epicroadtripplanner.com/v1/campgrounds/3a198528-95cf-4235-a40e-c9597d0a877a", {
headers: {
'accept': 'application/json'
}
});
console.log("Response:", response);
} catch(e) {
console.error(e)
}
try {
console.log("Fetching from prod (not allow-listed, reported)...")
const response = await fetch("https://api.epicroadtripplanner.com/v1/campgrounds/84af4262-6dff-4121-b22d-70b6173b15f6", {
headers: {
'accept': 'application/json'
}
});
console.log("Response:", response);
} catch(e) {
console.error(e)
}
Since I'm using the report-only variant (Connection-Allowlist-Report-Only) rather than the enforcement variant (Connection-Allowlist), both calls succeed -- but only the prod call is reported.

I got this single connection-allowlist report on my reporting server, for the call to the prod server:

I also tried the enforce version and played around with a few other items. Now that I know this all works at a high level, I'm looking forward to going deeper -- reviewing the actual CSP headers on a few of my sites and seeing just how much simpler and more specific the corresponding Connection-Allowlist headers can be. I'll also be watching how the WICG draft evolves. Good stuff!
-Tim