Skip to content

fix(launch): route systemd + demo bind through the SEC-F22 guard (SEC-F23/F24)#433

Merged
pcalnon merged 1 commit into
mainfrom
fix/launch-path-bind-loopback-default
Jul 7, 2026
Merged

fix(launch): route systemd + demo bind through the SEC-F22 guard (SEC-F23/F24)#433
pcalnon merged 1 commit into
mainfrom
fix/launch-path-bind-loopback-default

Conversation

@pcalnon

@pcalnon pcalnon commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Summary

Launch-path bind audit findings SEC-F23 (systemd unit) and SEC-F24 (demo launcher). Both started canopy with uvicorn main:app --host 0.0.0.0 --port 8050. uvicorn binds the socket from the CLI --host without ever consulting settings.server.host, so the SEC-F22 bind guard — which reads the setting (default 127.0.0.1) in the app lifespan — saw loopback, concluded "safe", and passed while the socket was bound to all interfaces. canopy has no uvicorn-CLI parity shim (unlike cascor), so this bypass was undefended.

Fix

Drive both launchers through the settings-based entrypoint — python main.py from the src WorkingDirectory (the demo already cd src; the unit's WorkingDirectory is .../juniper-canopy/src) — so the guard evaluates the real bind host. Both now bind loopback by default (matching the deploy container and plant_all), and each documents how to expose off-loopback via JUNIPER_CANOPY_SERVER__HOST + one honest attestation flag. The guard hard-fails on an unattested non-loopback bind, so exposure is a conscious, attested act.

Host/port defaults are unchanged (127.0.0.1:8050; settings.server.port default is 8050).

Behavior change (intended)

The systemd unit and demo previously bound 0.0.0.0; they now bind loopback by default. Same-machine use is unaffected (browse http://localhost:8050/dashboard/). Off-loopback reachability now requires setting JUNIPER_CANOPY_SERVER__HOST=0.0.0.0 + the matching attestation — the SEC-F22 posture, and consistent with the request to limit environment-config divergence. A bare on-host 0.0.0.0 bind cannot set an honest attestation (no loopback publish, no fronting proxy), so loopback-default is the correct shipped posture.

Not in scope (follow-up)

canopy still lacks cascor's generic _settings_with_uvicorn_cli_bind parity shim; porting it would defend any future uvicorn --host launcher, not just these two. Tracked as the reclassified SEC-F27 (see PR #630 discussion).

Testing

  • shellcheck -S warning util/juniper_canopy-demo.bash — clean; pre-commit Lint shell scripts passed.
  • systemd unit change is ExecStart only; WorkingDirectory=.../src already present.

See juniper-ml notes/JUNIPER_2026-07-06_JUNIPER-ECOSYSTEM_LAUNCH-PATH-BIND-AUDIT.md (SEC-F23, SEC-F24), companion to juniper-ml PR #630.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LX5ToumBaABH3QutQC86sM

…-F23/F24)

The systemd unit and the demo launcher started canopy with
`uvicorn main:app --host 0.0.0.0`. uvicorn binds the socket from the CLI flag
without ever consulting settings.server.host, so the SEC-F22 bind guard (which
reads the setting, default 127.0.0.1) saw loopback and passed while the socket
was public -- an undefended guard bypass (canopy has no uvicorn-CLI parity shim).

Drive both launchers through the settings-based entrypoint (python main.py, from
the src WorkingDirectory), so the guard evaluates the real bind. Both now bind
loopback by default (matching the container + plant_all paths); each documents
how to expose off-loopback via JUNIPER_CANOPY_SERVER__HOST + an honest
attestation flag (the guard hard-fails on an unattested non-loopback bind).
Host/port defaults are unchanged (127.0.0.1:8050).

See juniper-ml notes/JUNIPER_2026-07-06_JUNIPER-ECOSYSTEM_LAUNCH-PATH-BIND-AUDIT.md (SEC-F23, SEC-F24).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LX5ToumBaABH3QutQC86sM

@pcalnon pcalnon left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

approved

@pcalnon pcalnon merged commit 52f54e7 into main Jul 7, 2026
43 of 44 checks passed
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