# Egress CI quickstart

> Put a GitHub Actions job's outbound traffic behind an allowlist with the OpenWAF Egress CI action, in audit first and then in enforce.

OpenWAF Egress CI is a GitHub Action, [`openwaf-dev/egress-action`](https://github.com/openwaf-dev/egress-action), that puts the outbound traffic of a CI job behind an allowlist. Every connection and DNS query of the job and of its containers is named and logged. Anything outside `.github/egress.yml` is reported (`audit`) or refused (`enforce`), what leaves is checked for secrets with the same detectors as the [OpenWAF Egress](https://developers.openwaf.dev/egress/) gateway, and the job summary lists every destination the job talked to.

It is the CI counterpart of the gateway: a compromised dependency, build script or action that tries to send your secrets or your code somewhere else finds the way closed, and you see the attempt in the summary.

The action runs as a sidecar inside the job, on the runner itself. It needs no OpenWAF account and sends nothing anywhere unless you turn on [sending events to OpenWAF](https://developers.openwaf.dev/egress/ci/send-events/). It is an early-access beta under the Apache License 2.0, listed on the [GitHub Marketplace](https://github.com/marketplace/actions/openwaf-egress-ci).

## Before you start

- **A Linux runner**, x64 or arm64. GitHub-hosted Ubuntu runners work as they are. On a [self-hosted runner](https://developers.openwaf.dev/egress/ci/self-hosted-runners/) the job's user needs passwordless `sudo` or access to the Docker daemon, and the host needs `nft` (nftables) and `ip` (iproute2).
- **Write access to the workflow** and to `.github/` in the repository.

## 1. Add the action

Add it as the first step after `actions/checkout`. The steps before it are not covered.

```yaml
name: test
on: [push, pull_request]
permissions:
  contents: read
jobs:
  test:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v5
      - uses: openwaf-dev/egress-action@v0.3.2
      - run: make test
```

In production, pin the release's full commit SHA instead of the tag, with the version as a comment so Dependabot
can update it: `uses: openwaf-dev/egress-action@5a956e8bdeff9c34c13f2277f9096fddc6e6e51a # v0.3.2`.

## 2. Write the policy

```yaml
version: 1
mode: audit                 # report only, refuse nothing
presets: [github-actions]   # the names GitHub publishes for Actions runners
allow:
  - proxy.golang.org        # ports 80 and 443
  - "*.npmjs.org"           # any name below npmjs.org
```

`github-actions` covers what any job needs: the runner's own service, checkout, the API, the cache, artifacts and logs storage, and `raw.githubusercontent.com`. Every key is described in the [egress.yml reference](https://developers.openwaf.dev/egress/ci/reference/).

## 3. Read the job summary

Push and open the run. The job summary starts with **OpenWAF Egress CI: audit** and a table of destinations:

```text
12 destinations, 2 outside the policy (enforce would block them), 0 detections.

| Destination      | Ports | Via   | Conn. | Up      | Down    | Policy      | Detections |
| proxy.golang.org | 443   | proxy | 3     | 4.1 KiB | 2.3 MiB | allowed     |            |
| sum.golang.org   | 443   | proxy | 1     | 812 B   | 6.2 KiB | not allowed |            |
```

**Via** says how the connection left: `proxy` through `HTTPS_PROXY`, `direct` caught by the lock (a tool that ignores the proxy variables), `container` from one of the job's containers, `udp` for non-TCP flows. Under **Names outside the policy** the summary gives a ready-made `allow` block with every name that enforce would refuse.

## 4. Switch to enforce

Copy those names into `allow`, run again until the summary shows nothing outside the policy, and set `mode: enforce`. From then on a name outside the policy gets `403` from the proxy, `NXDOMAIN` from DNS, or a reset, and the summary says which and why. [From audit to enforce](https://developers.openwaf.dev/egress/ci/audit-to-enforce/) walks through it.

## Next steps

- [egress.yml reference](https://developers.openwaf.dev/egress/ci/reference/): every key of the policy, every input of the action and what it sets for the job.
- [Docker and builds](https://developers.openwaf.dev/egress/ci/docker/): containers, `docker build` and image pulls under the same policy.
- [Inspection and DLP](https://developers.openwaf.dev/egress/ci/inspect-and-dlp/): which requests are scanned for secrets, and the TLS trade-off.
- [Limits](https://developers.openwaf.dev/egress/ci/limits/): what the action covers and what it does not.


Written from [github.com/openwaf-dev/egress-action@v0.3.2](https://github.com/openwaf-dev/egress-action/tree/v0.3.2).
