The Synapse backend and memory service bound 0.0.0.0 with wildcard CORS and no auth, exposing the full unauthenticated admin/data API to the LAN. This PR:
Defaults the uvicorn bind to 127.0.0.1 (NEXUS_BIND_HOST override) in management/ncp.py.
Scopes CORS to known local origins instead of * on both the backend and the memory service.
Adds TrustedHostMiddleware to reject foreign Host headers, which defeats DNS-rebinding — something same-origin CORS cannot stop.
NEXUS_ALLOWED_HOSTS / NEXUS_ALLOWED_ORIGINS allow opt-in LAN exposure, intended to be paired with real authentication.
Testing
Verified services listen only on 127.0.0.1 after the change.
Probed endpoints with foreign Origin and Host headers: foreign hosts get 400, CORS preflight only allows the local-origin allowlist.
pytest smoke tests pass.
Stack note
This is PR 1 of 3 in a hardening series. Merge order: this PR → "SSRF guard + approval tokens" → "resource limits + model allowlist". The later PRs are stacked on this branch, so their diffs will show earlier commits until this one merges (use regular merge, not squash, so the follow-up diffs collapse cleanly).
## Summary
The Synapse backend and memory service bound `0.0.0.0` with wildcard CORS and no auth, exposing the full unauthenticated admin/data API to the LAN. This PR:
- Defaults the uvicorn bind to `127.0.0.1` (`NEXUS_BIND_HOST` override) in `management/ncp.py`.
- Scopes CORS to known local origins instead of `*` on both the backend and the memory service.
- Adds `TrustedHostMiddleware` to reject foreign `Host` headers, which defeats DNS-rebinding — something same-origin CORS cannot stop.
`NEXUS_ALLOWED_HOSTS` / `NEXUS_ALLOWED_ORIGINS` allow opt-in LAN exposure, intended to be paired with real authentication.
## Testing
- Verified services listen only on `127.0.0.1` after the change.
- Probed endpoints with foreign `Origin` and `Host` headers: foreign hosts get 400, CORS preflight only allows the local-origin allowlist.
- `pytest` smoke tests pass.
## Stack note
This is **PR 1 of 3** in a hardening series. Merge order: this PR → "SSRF guard + approval tokens" → "resource limits + model allowlist". The later PRs are stacked on this branch, so their diffs will show earlier commits until this one merges (use regular merge, not squash, so the follow-up diffs collapse cleanly).
The Synapse backend and memory service bound 0.0.0.0 with wildcard CORS and no
auth, exposing the full unauthenticated admin/data API to the LAN. Default the
uvicorn bind to 127.0.0.1 (NEXUS_BIND_HOST override), scope CORS to known local
origins instead of "*", and add TrustedHostMiddleware to reject foreign Host
headers (which defeats DNS-rebinding, something same-origin CORS cannot stop).
NEXUS_ALLOWED_HOSTS / NEXUS_ALLOWED_ORIGINS allow opt-in LAN exposure, intended
to be paired with real authentication.
Co-authored-by: Cursor <cursoragent@cursor.com>
enderofwings
marked the pull request as work in progress 2026-08-07 15:36:13 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
The Synapse backend and memory service bound
0.0.0.0with wildcard CORS and no auth, exposing the full unauthenticated admin/data API to the LAN. This PR:127.0.0.1(NEXUS_BIND_HOSToverride) inmanagement/ncp.py.*on both the backend and the memory service.TrustedHostMiddlewareto reject foreignHostheaders, which defeats DNS-rebinding — something same-origin CORS cannot stop.NEXUS_ALLOWED_HOSTS/NEXUS_ALLOWED_ORIGINSallow opt-in LAN exposure, intended to be paired with real authentication.Testing
127.0.0.1after the change.OriginandHostheaders: foreign hosts get 400, CORS preflight only allows the local-origin allowlist.pytestsmoke tests pass.Stack note
This is PR 1 of 3 in a hardening series. Merge order: this PR → "SSRF guard + approval tokens" → "resource limits + model allowlist". The later PRs are stacked on this branch, so their diffs will show earlier commits until this one merges (use regular merge, not squash, so the follow-up diffs collapse cleanly).
Pull request closed