diff --git a/README.md b/README.md index 0330112..ea861a4 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ workflow `run:` step rather than a Docker build, use - [Proxy engines](#proxy-engines) - [Report action](#report-action) - [Scope](#scope) +- [Hardening](#hardening) - [Documentation](#documentation) ## Usage @@ -253,6 +254,16 @@ delivered through an allowed domain still runs. Use it as one layer in a defense a last line of defense so that if something slips through your other measures, at least it can't call home. See [Security Details](./docs/security.md) for the full threat model. +## Hardening + +An allowlist works on domain names, so it is weak against anything that leaves through a service you +had to allow anyway. Those services are public, though, and traffic to them tends to leave a trace. +What it is good at is the opposite case: a command-and-control server or any other host the attacker +picked is simply unreachable, and that is exactly where a leak would otherwise go unnoticed. + +The allowlist an audit run generates already gets you that, without touching your Dockerfile. If you +want to narrow it further, [Hardening](./docs/security.md#hardening) covers what to look at. + ## Documentation | Doc | What's in it | diff --git a/docs/security.md b/docs/security.md index 0456a4c..8e176b3 100644 --- a/docs/security.md +++ b/docs/security.md @@ -136,6 +136,58 @@ Given these implementation costs versus the strict preconditions for the attack - **Major CDN countermeasures** — Major CDN providers like CloudFront and Cloudflare have already introduced measures to restrict domain fronting. Consult your CDN provider's documentation for current details. - **Regular audits** — Periodically run in [audit mode](../README.md#operation-modes) to detect anomalies in connection patterns. +## Hardening + +An allowlist decides which destinations a build can reach. It works on domain names, so it cannot +tell a legitimate use of an allowed destination from an abusive one. Anything that leaves through a +service you had to allow anyway will still leave. + +What it is good at is the other half. A command-and-control server, or any other host an attacker +chose, is not on the list and is simply unreachable. That matters because the two cases are not +equivalent. The services you end up allowing are public ones, where traffic tends to leave a trace +somebody can find later. A host the attacker controls leaves none. + +So the allowlist does not remove exfiltration. It closes the routes that would have gone unnoticed +and leaves the ones that do not. + +You get that from the allowlist an audit run generates, with no changes to your Dockerfile. The rest +of this section is about narrowing it further, and is worth reading only if you want more than the +default. + +### Review what the audit produced + +A generated allowlist is tuned for one thing: the build completing. Every entry in it is a +destination you are now permitting, so it is worth a second pass. + +- Can a wildcard become an exact host? `*.githubusercontent.com` covers considerably more than the + one host a build usually needs. +- Is a general-purpose place to put things on the list, such as a gist host, object storage, or an + API that can create repositories? Those double as somewhere to send data to. Check whether the + build genuinely needs it or merely touched it in passing. +- If an entry cannot be dropped, the build itself may be able to change. Pinning a download to a + fixed URL is often enough to replace a broad rule with a narrow one. + +### Reduce what the build has to reach + +Dependency fetching is usually what forces a package registry onto the list. Moving it out of the +main build, into an earlier stage or a step that runs before it, can leave the build proper needing +very little. + +If you already run a registry mirror or proxy, pointing the build at it removes the public registry +from the allowlist. Standing one up purely for this is a large undertaking and not something to do +on Buildcage's account. + +### Read the report when dependencies change + +A destination that was not there before is the thing worth looking into, and a dependency update is +when it tends to appear. The report is where an exfiltration attempt that used an allowed service +becomes visible, which only helps if somebody looks. + +### Keep the rest of your supply chain practice + +Pinning versions, lockfiles, and review still do work an allowlist cannot. Buildcage is one layer +among them rather than a replacement for any of them. + ## Explicit Proxy Engine > [!WARNING]