Skip to content
This repository was archived by the owner on Oct 13, 2026. It is now read-only.

Detect corporate TLS interception from inside a container - #1

Merged
sdonche merged 2 commits into
mainfrom
claude/repo-overview-870170
Sep 18, 2026
Merged

sdonche merged 2 commits into
mainfrom
claude/repo-overview-870170

Conversation

@sdonche

@sdonche sdonche commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Why

Students on corporate laptops hit unable to get local issuer certificate — but only in Lab 06 / the capstone, when the GitHub Actions runner container tries to register. Every existing preflight check passes on those machines: git, gh and docker pull all use the host's trust store, where IT has installed the intercepting proxy's root CA. A container only trusts the CA bundle baked into its image, so nothing in the preflight caught it and it surfaced mid-course.

What

New required check — "GitHub from inside a container" (scripts/preflight.sh, placed before the slow image pull):

  • Confirms the host can reach api.github.com first (otherwise the problem is upstream of Docker).
  • From a pinned curlimages/curl:8.14.1 container, GETs api.github.com, github.com and pipelines.actions.githubusercontent.com — the hosts the runner needs. Any HTTP response counts; only transport/TLS failures matter. One retry per host, except curl exit 60 which is deterministic.
  • Exit 60 → "TLS interception detected", with the issuer of the certificate the container saw (Zscaler Root CA etc.) so the TA can read it straight off the report.
  • Other failures → "Containers cannot reach GitHub although this machine can" → Docker proxy settings.
  • If ~/corp-root.crt exists and makes the probe verify, the check passes with a reminder about the compose override — so a student who has done the fix sees green rather than a red check they've already dealt with. A cert that exists but doesn't help gets its own message.

troubleshooting.md — full walkthrough: exporting the root CA per OS (with the issuer: hint and certlm.msc for the Windows machine store), re-running the preflight, a tested docker-compose.corp-ca.yaml override for the runner (update-ca-certificates wrapper + NODE_EXTRA_CA_CERTS for JS actions, enabled via COMPOSE_FILE in .env), and options when IT won't release the certificate. Plus a short section for the non-certificate "containers can't get out" case.

README.md — table row.

Verified

  • bash -n + shellcheck (same as CI) clean.
  • Full run on macOS/OrbStack: new check passes for all three hosts.
  • Failure paths: ran a copy of the script against a curl image with a broken CA bundle → correct FAIL for no cert, correct "exists but does not make … verify" for a wrong cert, PASS + reminder for a correct cert.
  • The compose override was brought up against the real myoung34/github-runner:latest: CA installed and verified against the rebuilt bundle, CMD forwarded intact, real entrypoint reached the "Configuring" banner.

Follow-up (not in this PR)

Ship docker-compose.corp-ca.yaml inside Lab 06 and capstone/ with a commented-out COMPOSE_FILE= line in their .env.example, so the fix is "uncomment one line" instead of creating the file by hand.

🤖 Generated with Claude Code

sdonche and others added 2 commits September 18, 2026 15:32
Students on corporate laptops hit "unable to get local issuer certificate"
only when the Lab 06 / capstone GitHub Actions runner container tries to
register — every existing preflight check (git, gh, docker pull) passes
because those use the host's trust store, where IT has installed the
proxy's root CA. The runner image only trusts its own CA bundle.

New required check "GitHub from inside a container": probes
api.github.com, github.com and pipelines.actions.githubusercontent.com
from a pinned curlimages/curl container. curl exit 60 is reported as TLS
interception with the issuer of the certificate the container saw; other
failures point at Docker's proxy settings. If ~/corp-root.crt exists and
makes the probe verify, the check passes with a reminder about the
compose override, so a student who has done the fix sees green.

troubleshooting.md gains a full walkthrough: exporting the root CA per
OS, re-running the preflight, a tested docker-compose.corp-ca.yaml
override for the runner (update-ca-certificates wrapper + NODE_EXTRA_CA_CERTS
for JS actions) enabled via COMPOSE_FILE in .env, and what to do when IT
won't release the certificate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Redact user:password@ from proxy URLs before they land in the report
  (students paste it into Discord).
- Reject a corp-root.crt that holds no self-signed certificate: curl
  accepts a partial chain so an exported intermediate turned the check
  green, while update-ca-certificates in the runner needs the root.
- Name the "~/corp-root.crt is a directory" case, which Docker produces
  when the compose override runs before the file exists.
- Report host-side curl exit 60 as a missing CA in this OS/WSL distro
  instead of a generic connectivity failure, with a doc section for it.
- After the corporate CA rescues the first failing host, re-probe every
  GitHub host with it rather than declaring victory on one.
- Compose override: long bind syntax with create_host_path: false so a
  missing cert is an error, and an openssl verify guard that prints why
  the runner refused to start instead of exiting silently.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant