Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/example-audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Start buildcage builder
- name: Start Buildcage builder
id: buildcage
uses: dash14/buildcage/setup@v1
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/example-restrict.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Start buildcage builder
- name: Start Buildcage builder
id: buildcage
uses: dash14/buildcage/setup@v1
with:
Expand Down
79 changes: 35 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# buildcage
# Buildcage

![buildcage](./assets/banner.png)
![Buildcage](./assets/banner.png)

[![GitHub](https://img.shields.io/badge/GitHub-dash14%2Fbuildcage-blue?logo=github)](https://github.com/dash14/buildcage)
![version](https://img.shields.io/github/v/release/dash14/buildcage
Expand All @@ -13,18 +13,18 @@

**Secure your Docker builds against supply chain attacks — restrict outbound network access to only the domains you allow.**

When you run `RUN npm install` or `RUN apt-get install` in a Dockerfile, those commands can reach any server on the internet — and you have no visibility or control over where they connect. A compromised dependency could silently exfiltrate your build secrets or phone home to an attacker's server.
When you run `RUN npm install` or `RUN pip install` in a Dockerfile, those commands can execute arbitrary code and make outbound connections to any server on the internet — without visibility or control. A compromised dependency could silently exfiltrate your build secrets or phone home to an attacker's server.

buildcage prevents this. You define a list of allowed domains, and only those connections are permitted during builds. Everything else is blocked.
Buildcage prevents this. You define a list of allowed domains, and only those connections are permitted during builds. Everything else is blocked.

No Dockerfile changes required. No certificates to install. Works with any language or package manager.
No Dockerfile changes required. No proxy configuration needed. No certificates to install. Works with any language or package manager.


## How It Works

buildcage runs as a [remote driver](https://docs.docker.com/build/builders/drivers/remote/) for Docker Buildx. All `RUN` step containers are placed on an isolated network, and outbound traffic is routed through a proxy that enforces your allowlist.
Buildcage runs as a [remote driver](https://docs.docker.com/build/builders/drivers/remote/) for Docker Buildx. All `RUN` step containers are placed on an isolated network, and outbound traffic is routed through a proxy that enforces your allowlist.

<img src="assets/diagram-overview.png" alt="How buildcage works" width="544" height="328">
<img src="assets/diagram-overview.png" alt="How Buildcage works" width="544" height="328">

- HTTPS: SNI (Server Name Indication) for domain matching — TLS is not terminated
- HTTP: Host header for domain matching
Expand All @@ -40,9 +40,9 @@ buildcage runs as a [remote driver](https://docs.docker.com/build/builders/drive

### Recommended for:

- **CI/CD pipelines pulling from public registries** — if your builds download packages from npm, PyPI, RubyGems, or other public sources, buildcage limits the blast radius of compromised packages
- **Builds that handle secrets** — if your Dockerfiles use build secrets, tokens, or credentials, buildcage prevents them from being exfiltrated to unauthorized servers
- **Teams that need network visibility** — if you need to know exactly which external services your builds contact, buildcage logs every outbound connection and can enforce an allowlist
- **CI/CD pipelines pulling from public registries** — if your builds download packages from npm, PyPI, RubyGems, or other public sources, Buildcage limits the blast radius of compromised packages
- **Builds that handle secrets** — if your Dockerfiles use build secrets, tokens, or credentials, Buildcage prevents them from being exfiltrated to unauthorized servers
- **Teams that need network visibility** — if you need to know exactly which external services your builds contact, Buildcage logs every outbound connection and can enforce an allowlist

### May not be necessary for:

Expand Down Expand Up @@ -70,10 +70,10 @@ buildcage runs as a [remote driver](https://docs.docker.com/build/builders/drive

### First-Time Setup (Recommended Workflow)

Using buildcage in GitHub Actions involves three workflow steps:
Using Buildcage in GitHub Actions involves three workflow steps:

1. Start the buildcage container (runs BuildKit inside a network-controlled environment)
2. Configure Docker Buildx to use the buildcage container as a remote builder
1. Start the Buildcage container (runs BuildKit inside a network-controlled environment)
2. Configure Docker Buildx to use the Buildcage container as a remote builder
3. Run your build as usual — your Dockerfile and build commands stay the same

#### Step 1: Discover what domains your build needs (Audit Mode)
Expand All @@ -89,7 +89,7 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Start buildcage in audit mode
- name: Start Buildcage in audit mode
id: buildcage
uses: dash14/buildcage/setup@v1
with:
Expand All @@ -107,7 +107,7 @@ jobs:
context: .
push: false # Set to true to push the built image

- name: Show buildcage report
- name: Show Buildcage report
if: always()
uses: dash14/buildcage/report@v1
with:
Expand Down Expand Up @@ -137,7 +137,7 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Start buildcage in restrict mode
- name: Start Buildcage in restrict mode
id: buildcage
uses: dash14/buildcage/setup@v1
with:
Expand All @@ -158,7 +158,7 @@ jobs:
context: .
push: false # Set to true to push the built image

- name: Show buildcage report
- name: Show Buildcage report
if: always()
uses: dash14/buildcage/report@v1
# Build fails if any unexpected connections were blocked
Expand All @@ -172,10 +172,10 @@ Your builds are now protected. Any unexpected connections will be blocked and re

### Setup Action (`dash14/buildcage/setup`)

Starts the buildcage builder container.
Starts the Buildcage builder container.

```yaml
- name: Start buildcage builder
- name: Start Buildcage builder
id: buildcage
uses: dash14/buildcage/setup@v1
with:
Expand Down Expand Up @@ -216,7 +216,7 @@ For detailed syntax, see [Rule Syntax](./docs/rules.md).
|------|-------------|
| `port` | BuildKit endpoint port |

Pass this port to [`docker/setup-buildx-action`](https://github.com/docker/setup-buildx-action) to use buildcage as a remote builder:
Pass this port to [`docker/setup-buildx-action`](https://github.com/docker/setup-buildx-action) to use Buildcage as a remote builder:

```yaml
- name: Set up Docker Buildx
Expand Down Expand Up @@ -294,7 +294,7 @@ In restrict mode, the report step fails if blocked connections are detected, cau

### For Technical Users

buildcage creates a controlled network environment for your Docker builds:
Buildcage creates a controlled network environment for your Docker builds:

1. **BuildKit RUN steps run in isolated containers** connected to a private network (CNI)
2. **All DNS queries return the proxy IP** (172.20.0.1), forcing traffic through the proxy
Expand All @@ -314,15 +314,15 @@ buildcage creates a controlled network environment for your Docker builds:

### Architecture Diagram

<img src="assets/diagram-architecture.png" alt="buildcage architecture" width="611" height="544">
<img src="assets/diagram-architecture.png" alt="Buildcage architecture" width="611" height="544">

All containers spawned by BuildKit `RUN` steps are placed on an isolated network (CNI). DNS queries are redirected to the proxy IP, and the proxy checks each request's SNI (HTTPS) or Host header (HTTP) against the allowlist before forwarding or blocking.

---

## Trust & Self-Hosting

buildcage is a security tool — so it's fair to ask: *how do you trust buildcage itself?*
Buildcage is a security tool — so it's fair to ask: *how do you trust Buildcage itself?*

A pre-built image from a third party could be modified or rebuilt at any time without your knowledge. For a tool that sits in your build pipeline, that's a risk worth addressing.

Expand All @@ -344,21 +344,21 @@ If you don't need that level of control, you can use the image published from th

## Security Considerations

> **Important:** buildcage controls *where* your builds can connect, not *what code* they run. If a malicious package is delivered through a legitimate repository (e.g., a compromised npm package hosted on `registry.npmjs.org`), buildcage cannot detect or prevent it — the connection goes to an allowed domain.
> **Important:** Buildcage controls *where* your builds can connect, not *what code* they run. If a malicious package is delivered through a legitimate repository (e.g., a compromised npm package hosted on `registry.npmjs.org`), Buildcage cannot detect or prevent it — the connection goes to an allowed domain.
>
> Do not rely on buildcage as your sole supply chain security measure. Use it as one layer in a defense-in-depth strategy — a last line of defense that limits the blast radius of compromised dependencies by restricting their ability to communicate with external servers.
> Do not rely on Buildcage as your sole supply chain security measure. Use it as one layer in a defense-in-depth strategy — a last line of defense. If something slips through your other measures, at least it can't call home.

### What buildcage protects against
### What Buildcage protects against

buildcage blocks outbound connections to domains not on your allowlist during Docker builds. This helps mitigate scenarios such as:
Buildcage blocks outbound connections to domains not on your allowlist during Docker builds. This helps mitigate scenarios such as:

- **Data exfiltration** — prevents build secrets (e.g., environment variables, tokens) from being sent to external servers
- **Command-and-control (C2) communication** — blocks compromised dependencies from phoning home to attacker-controlled servers
- **Unexpected telemetry** — stops analytics, tracking, or other undisclosed network calls that packages may make during installation

### Security mechanisms and attack resistance

buildcage enforces network isolation through DNS-level control, HTTP/HTTPS proxy filtering, iptables rules, and CNI network isolation. These mechanisms defend against SNI spoofing, ECH bypass, DNS tunneling, non-TCP protocol tunneling, IPv6 bypass, and alternative DNS transports (DoH/DoT).
Buildcage enforces network isolation through DNS-level control, HTTP/HTTPS proxy filtering, iptables rules, and CNI network isolation. These mechanisms defend against SNI spoofing, ECH bypass, DNS tunneling, non-TCP protocol tunneling, IPv6 bypass, and alternative DNS transports (DoH/DoT).

For full technical details, see the [Security Details](./docs/security.md) document.

Expand All @@ -368,7 +368,7 @@ The only known bypass is **domain fronting** — a technique where an attacker s

## FAQ

- **Can I host buildcage in my own private repository?**
- **Can I host Buildcage in my own private repository?**

Yes. See [Trust & Self-Hosting](#trust--self-hosting) for details.

Expand All @@ -378,7 +378,7 @@ The only known bypass is **domain fronting** — a technique where an attacker s

- **Can I use this with multi-stage builds?**

Yes. buildcage works seamlessly with multi-stage Dockerfiles.
Yes. Buildcage works seamlessly with multi-stage Dockerfiles.

- **Does this work with private package registries?**

Expand All @@ -388,7 +388,7 @@ The only known bypass is **domain fronting** — a technique where an attacker s

In restrict mode, the build will fail with a clear error message. Run in audit mode first to discover all required domains.

- **Do I need to clean up the buildcage container?**
- **Do I need to clean up the Buildcage container?**

No. The container is automatically removed when the GitHub Actions job completes.

Expand All @@ -398,7 +398,7 @@ The only known bypass is **domain fronting** — a technique where an attacker s

- **Does this protect against malicious code execution?**

No. buildcage only controls network access. It doesn't prevent malicious code from running—it prevents that code from communicating with external servers.
No. Buildcage only controls network access. It doesn't prevent malicious code from running—it prevents that code from communicating with external servers.

## Troubleshooting

Expand Down Expand Up @@ -433,22 +433,13 @@ Contributions are welcome! Please feel free to submit issues or pull requests at
## Show Your Support

Knowing that this project is useful to others gives me the motivation to keep working on it.
If you find buildcage helpful, please consider giving it a star ⭐ on GitHub!
If you find Buildcage helpful, please consider giving it a star ⭐ on GitHub!

## Disclaimer

This software is provided "as is", without warranty of any kind, express or implied. The authors and contributors are not liable for any damages, losses, or security incidents arising from the use of this software. Use at your own risk.

## License
The buildcage source code is licensed under the MIT License. See [LICENSE](./LICENSE) file for details.
The Buildcage source code is licensed under the MIT License. See [LICENSE](./LICENSE) file for details.

The Docker image includes third-party components under their own licenses (GPL, Apache 2.0, ISC, etc.). See [THIRD_PARTY_LICENSES](./THIRD_PARTY_LICENSES) for the full list.

## Acknowledgments

buildcage is built on top of:
- [BuildKit](https://github.com/moby/buildkit) - Modern build toolkit
- [CNI](https://github.com/containernetworking/cni) - Container network interface
- [HAProxy](https://www.haproxy.org/) - TCP/HTTP proxy
- [dnsmasq](https://thekelleys.org.uk/dnsmasq/doc.html) - DNS server
- [s6-overlay](https://github.com/just-containers/s6-overlay) - Process supervisor
The Docker image includes third-party components under their own licenses (GPL, Apache 2.0, ISC, etc.). See [THIRD_PARTY_LICENSES](./THIRD_PARTY_LICENSES) for the full list.
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

I welcome reports about:

- **Proxy bypass** — ways to make network connections from `RUN` steps that evade the buildcage proxy (other than the [known domain fronting limitation](./README.md#known-limitations))
- **Proxy bypass** — ways to make network connections from `RUN` steps that evade the Buildcage proxy (other than the [known domain fronting limitation](./README.md#known-limitations))
- **Network isolation escape** — bypassing CNI isolation or iptables rules to reach the internet directly
- **GitHub Actions setup** — vulnerabilities in the `setup` or `report` actions (e.g., injection, credential leak)
- **DNS filtering bypass** — bypassing the DNS redirect mechanism
Expand Down
6 changes: 3 additions & 3 deletions THIRD_PARTY_LICENSES
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Third-Party Licenses
====================

The buildcage Docker image includes the following third-party software.
Each component retains its original license. The buildcage source code
The Buildcage Docker image includes the following third-party software.
Each component retains its original license. The Buildcage source code
itself is licensed under the MIT License (see LICENSE file).

------------------------------------------------------------------------------
Expand Down Expand Up @@ -59,7 +59,7 @@ repository. Their source code is available through:
2. Alpine Linux source packages:
https://pkgs.alpinelinux.org/packages

The buildcage source code (MIT License) is not derived from, linked to,
The Buildcage source code (MIT License) is not derived from, linked to,
or combined with the GPL-licensed components. They are independent programs
distributed together in a Docker image as an aggregate work, consistent
with GPL v2 Section 2.
Binary file modified assets/diagram-architecture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/report-restrict-mode.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions docker/files/THIRD_PARTY_LICENSES
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Third-Party Licenses
====================

The buildcage Docker image includes the following third-party software.
Each component retains its original license. The buildcage source code
The Buildcage Docker image includes the following third-party software.
Each component retains its original license. The Buildcage source code
itself is licensed under the MIT License (see LICENSE file).

------------------------------------------------------------------------------
Expand Down Expand Up @@ -59,7 +59,7 @@ repository. Their source code is available through:
2. Alpine Linux source packages:
https://pkgs.alpinelinux.org/packages

The buildcage source code (MIT License) is not derived from, linked to,
The Buildcage source code (MIT License) is not derived from, linked to,
or combined with the GPL-licensed components. They are independent programs
distributed together in a Docker image as an aggregate work, consistent
with GPL v2 Section 2.
6 changes: 3 additions & 3 deletions docs/development.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Development Guide

This document covers local development, testing, and the project structure of buildcage.
This document covers local development, testing, and the project structure of Buildcage.

## Local Usage

You can run buildcage locally without GitHub Actions using Docker Compose and Make.
You can run Buildcage locally without GitHub Actions using Docker Compose and Make.

> GitHub Actions inputs use lowercase names (e.g., `proxy_mode`), while environment variables for local usage use uppercase (e.g., `PROXY_MODE`).

Expand All @@ -31,7 +31,7 @@ ALLOWED_HTTPS_RULES="github.com:443 npmjs.org:443 example.com:443" make run_rest
### End-to-End Workflow

```bash
# 1. Start buildcage
# 1. Start Buildcage
make run_audit_mode

# 2. Build
Expand Down
4 changes: 2 additions & 2 deletions docs/rules.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Rule Syntax

buildcage uses `allowed_https_rules`, `allowed_http_rules`, and `allowed_ip_rules` to control which destinations are accessible during Docker builds.
Buildcage uses `allowed_https_rules`, `allowed_http_rules`, and `allowed_ip_rules` to control which destinations are accessible during Docker builds.

## Delimiters

Expand Down Expand Up @@ -66,7 +66,7 @@ Since the regex is tested against the `domain:port` string, include a port patte
## Examples

```yaml
- name: Start buildcage
- name: Start Buildcage
uses: dash14/buildcage/setup@v1
with:
proxy_mode: restrict
Expand Down
8 changes: 4 additions & 4 deletions docs/security.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Security Details

This document provides in-depth technical details on how buildcage enforces network isolation during Docker builds.
This document provides in-depth technical details on how Buildcage enforces network isolation during Docker builds.

For a high-level overview, see the [Security Considerations](../README.md#security-considerations) section in the README.

Expand Down Expand Up @@ -31,7 +31,7 @@ For a high-level overview, see the [Security Considerations](../README.md#securi

## Attack Resistance

buildcage's architecture defends against the following attack vectors.
Buildcage's architecture defends against the following attack vectors.

### SNI Spoofing

Expand Down Expand Up @@ -73,13 +73,13 @@ An attacker may attempt to use DNS over HTTPS (DoH) or DNS over TLS (DoT) to byp

### Domain Fronting

buildcage inspects the **SNI (Server Name Indication)** field in HTTPS connections but cannot decrypt the actual request content inside the TLS tunnel. This creates a potential bypass technique called "domain fronting."
Buildcage inspects the **SNI (Server Name Indication)** field in HTTPS connections but cannot decrypt the actual request content inside the TLS tunnel. This creates a potential bypass technique called "domain fronting."

**How it works:**

```
Attack flow:
1. ClientHello SNI: allowed.example.com ← buildcage only sees this → ✅ allowed
1. ClientHello SNI: allowed.example.com ← Buildcage only sees this → ✅ allowed
2. HTTP Host header: malicious.example.com ← encrypted, cannot be inspected
3. CDN routes based on Host header → reaches attacker's server
```
Expand Down
Loading
Loading