Inspection and DLP

Which outbound requests of a CI job Egress CI scans for secrets, what inspect changes, and the trade-off of terminating TLS in a job.

On this page

Egress CI scans what a job sends for secrets with the data-leak detectors of the OpenWAF Egress gateway. In enforce a request that carries one is refused; in audit it passes and the summary lists the detection.

What is detected

Detection idWhat
dlp.private_keyA PEM private key (-----BEGIN … PRIVATE KEY-----)
dlp.aws_access_keyAn AWS access key id
dlp.openai_keyAn OpenAI-style sk- key
dlp.github_tokenA GitHub token, except when it goes to GitHub (github.com, githubusercontent.com, ghcr.io, githubapp.com and their subdomains), where the job's own token is expected
dlp.credit_cardA payment card number that passes the Luhn check
dns.high_entropy_labelA DNS label of 40 characters or more with high entropy: data encoded into a name
dns.long_nameA name of 150 characters or more
tls.sni_mismatchA CONNECT whose TLS SNI names a host outside the policy

The dns. detections are flagged, not refused by themselves: the name is still answered or refused by the policy. A secret inside a DNS name or a CONNECT host (dlp.… on the name) is detected on every destination, because the name is visible without decrypting anything.

What is scanned

RequestScanned
Plain HTTP through HTTPS_PROXY/HTTP_PROXYURL, headers and body
Plain HTTP caught by the lock (a tool that ignores the proxy)The first bytes of the connection: request line, headers and the start of the body
HTTPS to a host under inspect, through HTTPS_PROXYURL, headers and body of every request
Any other HTTPSOnly the name (CONNECT host, SNI, DNS name), not the content

Bodies are scanned whole up to 4 MiB. Larger bodies, and binary ones (application/octet-stream, image/*, video/*, zip, gzip, tar), pass unscanned, and the event says so.

inspect

.github/egress.yml
allow:
  - api.staging.example.com
inspect:
  - api.staging.example.com

For a host under inspect, the proxy terminates the job's TLS with a certificate issued by a CA created for the run, scans each request, and sends it on over a new TLS connection to the real host, verifying that host's certificate as usual. Inspection works on HTTP/1.1 (the proxy offers only http/1.1 in ALPN) and on connections made through HTTPS_PROXY; a tool that ignores the proxy variables reaches the host through the transparent proxy, which checks the name but does not decrypt.

So that the job trusts the run's CA, the action writes its certificate to $RUNNER_TEMP/egress-ci/ca.pem and a bundle with the system CAs, and sets:

VariableRead by
NODE_EXTRA_CA_CERTSNode.js
SSL_CERT_FILEOpenSSL-based tools, Go, Ruby, Python's ssl
REQUESTS_CA_BUNDLEPython Requests
CURL_CA_BUNDLEcurl
GIT_SSL_CAINFOGit

The TLS trade-off

Inspecting means the job accepts a CA that can sign a certificate for any name, for as long as the run lasts. The action limits what that costs:

  • The CA is created at the start of each run, valid for 12 hours, and only for that run. Its private key never leaves the sidecar's memory; only the certificate is written.
  • It signs certificates only for the hosts under inspect; every other HTTPS connection stays an opaque tunnel.
  • The real host's certificate is still verified by the sidecar, so inspecting does not hide a bad certificate from you: the request fails.

And what it does not solve:

  • Tools with their own trust store (a JVM's cacerts, some language package managers) or with certificate pinning fail on inspected hosts. Leave those hosts out of inspect.
  • Containers do not get the variables; inspection is for the job's own steps.
  • Without inspect, the content of HTTPS requests is never seen. A secret sent over HTTPS to an allowed host is not detected: the allowlist is the main control, DLP is a second line for plain HTTP and for the hosts you choose to inspect.

Inspect the hosts where a secret in a body would matter and that your tools reach through the proxy: a staging API your tests post to, a webhook, an artifact or telemetry endpoint. Do not inspect registries or GitHub.

Last updated:

↑↓ to navigate↵ to openesc to close