Skip to content

fix(cloud): trust the in-box Portless CA so in-box https://<box>.localhost works#120

Closed
madarco wants to merge 1 commit into
mainfrom
agentbox/fix-portless-incox-cert
Closed

fix(cloud): trust the in-box Portless CA so in-box https://<box>.localhost works#120
madarco wants to merge 1 commit into
mainfrom
agentbox/fix-portless-incox-cert

Conversation

@madarco

@madarco madarco commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Problem

After the symmetric `.localhost` URL feature, opening `https://.localhost` inside a box (confirmed on Hetzner) fails with a certificate error — both from the VNC Chromium window and from Playwright driven by Codex. The host browser is fine.

Root cause: when the host Portless proxy runs in TLS mode, the symmetric URL is served inside the box by a self-signed CA the box doesn't trust:

  • hetzner: the in-VPS mirror's own CA at `/root/.portless/ca.pem`
  • docker: the host CA bind-mounted at `/home/vscode/.portless/ca.pem`

`portless proxy start` only trusts the CA in the Linux system store, not the box user's NSS db — which Chromium / Playwright read on Linux — so in-box Chromium rejects the cert. `libnss3-tools` (`certutil`) wasn't even baked, and the cloud path never set `NODE_EXTRA_CA_CERTS`.

Fix

Trust the CA across every in-box client (user chose the robust option over agent-browser-only suppression):

  • New baked helper `agentbox-portless-trust` — installs a CA into the system store (`update-ca-certificates`) and the box user's NSS db (`certutil`), idempotent + best-effort, prints the system CA path for `NODE_EXTRA_CA_CERTS`. Resolves the box user's home dynamically.
  • Bake `libnss3-tools` into the hetzner snapshot (`install-box.sh`) + canonical `Dockerfile.box`; register the helper in `stage-runtime.mjs` + hetzner `runtime-assets.ts`.
  • hetzner `startInBoxPortless` (when `tls`): run the helper on `/root/.portless/ca.pem` + export `NODE_EXTRA_CA_CERTS` via `/etc/profile.d`.
  • docker `create` (when the resolved portless URL is `https`): run the helper on the bind-mounted host CA + same profile.d export.

No-TLS host proxies (the `--no-tls -p 1355` default) serve plain http and skip this entirely. Requires a snapshot re-bake / docker image rebuild to pick up `libnss3-tools` + the helper.

Verification

  • Unit: `pnpm --filter @agentbox/sandbox-hetzner test` (runtime-asset list) + `pnpm lint` green.
  • Helper logic proven in a throwaway container (system-store `curl` trusts the CA with no `-k`; NSS nick lands `C,,` vscode-owned; idempotent; graceful on missing CA).
  • Live hetzner e2e (re-baked snapshot `401902887`, real box from `examples/express-ready`, TLS host proxy):
    • `curl https://cert-smoke.localhost/\`HTTP 200 (system store, no `-k`)
    • node `fetch` → HTTP 200 (`NODE_EXTRA_CA_CERTS`)
    • `certutil` NSS nick `agentbox-portless-ca` present
    • Playwright Chromium → HTTP 200 with no `ignoreHTTPSErrors` (the exact reported failure — VNC Chromium + Codex Playwright share this NSS db)

https://claude.ai/code/session_0152GmbNW3e7QpXNkQFd3MB2


Note

Medium Risk
Touches box image bake, create-time root exec, and TLS trust stores; failures are best-effort and skipped for non-TLS Portless, but users must rebuild images/snapshots for the fix to apply.

Overview
Fixes in-box certificate errors on https://<box>.localhost when the host Portless proxy runs in TLS mode. Chromium and Playwright use the box user's NSS store, which portless proxy start does not populate, so VNC browser and Codex Playwright failed while the host browser worked.

Adds a baked agentbox-portless-trust helper that installs the Portless CA into the system trust store and the vscode NSS database via certutil, and wires NODE_EXTRA_CA_CERTS through /etc/profile.d/. libnss3-tools is added to Docker and Hetzner base images. Hetzner startInBoxPortless runs the helper on /root/.portless/ca.pem when tls is set; Docker create runs it on the bind-mounted host CA when the resolved Portless URL is https://. Staging, runtime assets, and docs are updated. Plain http Portless (default --no-tls) is unchanged.

Requires Hetzner snapshot re-bake (agentbox prepare --provider hetzner) and/or Docker image rebuild to pick up the helper and libnss3-tools.

Reviewed by Cursor Bugbot for commit 18046b0. Configure here.

…lhost works

When the host Portless proxy runs in TLS mode, the symmetric <box>.localhost
URL is served inside the box by a self-signed CA the box doesn't trust:
- hetzner: the in-VPS mirror's own CA at /root/.portless/ca.pem
- docker: the host CA bind-mounted at /home/vscode/.portless/ca.pem

portless proxy start only trusts the CA in the Linux system store, not the box
user's NSS db, so the in-box VNC Chromium window and Playwright (via Codex)
rejected the cert with an HTTPS error. Fix by trusting the CA across every
in-box client:

- New baked helper agentbox-portless-trust: installs a CA into the system store
  (update-ca-certificates) + the box user's NSS db (certutil), idempotent and
  best-effort, prints the system CA path for NODE_EXTRA_CA_CERTS.
- Bake libnss3-tools (certutil) into the hetzner snapshot + docker base image.
- hetzner startInBoxPortless: when tls, run the helper on /root/.portless/ca.pem
  and export NODE_EXTRA_CA_CERTS via /etc/profile.d.
- docker create: when the resolved portless URL is https, run the helper on the
  bind-mounted host CA + drop the same profile.d export.

No-TLS host proxies (the --no-tls -p 1355 default) serve plain http and skip
this entirely. Requires a snapshot re-bake / docker image rebuild to pick up
libnss3-tools + the helper.

Claude-Session: https://claude.ai/code/session_0152GmbNW3e7QpXNkQFd3MB2
@vercel

vercel Bot commented Jun 26, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agentbox-web Ready Ready Preview, Comment Jun 26, 2026 5:30pm

Request Review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 18046b0. Configure here.

const script =
'agentbox-portless-trust /home/vscode/.portless/ca.pem >/dev/null 2>&1 || true; ' +
"echo 'export NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/agentbox-portless-ca.crt' " +
'> /etc/profile.d/agentbox-portless-ca.sh 2>/dev/null || true';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Profile export without CA install

Medium Severity

After TLS Portless setup, both docker and Hetzner always write /etc/profile.d/agentbox-portless-ca.sh exporting NODE_EXTRA_CA_CERTS, even when agentbox-portless-trust did not install the CA (missing/unreadable ca.pem, failed install, or skipped mount). Login shells can then point Node at a non-existent or stale cert path instead of omitting the variable.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 18046b0. Configure here.

@madarco

madarco commented Jun 26, 2026

Copy link
Copy Markdown
Owner Author

Reviewed (Bugbot NEUTRAL, CI green) and integrated to nightly via cherry-pick c74f86342 (fast-forward). Per the nightly integration flow, not squash-merging to main — closing this PR. Live hetzner e2e verified: curl/node/certutil/Playwright all trust https://<box>.localhost (HTTP 200, no error suppression).

@madarco madarco closed this Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant