Skip to content

Harden CORS proxy and add deployment config - #75

Open
patrickunterwegs wants to merge 1 commit into
mainfrom
claude/cors-proxy-review-deploy-mo7c1l
Open

Harden CORS proxy and add deployment config#75
patrickunterwegs wants to merge 1 commit into
mainfrom
claude/cors-proxy-review-deploy-mo7c1l

Conversation

@patrickunterwegs

Copy link
Copy Markdown
Member

The Web (WASM) build routes CalDAV/WebDAV traffic through the Ktor proxy in server/ to work around browser CORS. This makes the proxy safe to host publicly and adds the artifacts to deploy it.

Proxy hardening (server/Application.kt):

  • SSRF/open-relay guard: validate the caller-supplied target — scheme check, optional host allow-list, https-only, and block loopback/link-local/private/ unique-local addresses (e.g. 169.254.169.254).
  • Configurable via env: PORT, PROXY_ALLOWED_ORIGINS, PROXY_ALLOWED_TARGET_HOSTS, PROXY_REQUIRE_HTTPS_TARGET, PROXY_ALLOW_PRIVATE_TARGETS.
  • CORS restricted to configured origins (was anyHost + credentials).
  • Forward the request body whenever one is present, fixing WebDAV LOCK.
  • Don't forward Origin/Referer/Cookie; drop upstream Access-Control-* on the response; use slf4j logging instead of println.
  • Add the package declaration so the configured mainClass resolves.

Wire up the in-app proxy setting (shared):

  • HttpClientFactory now resolves the proxy URL per request via a provider, so the "Proxy server" setting takes effect (previously the preference was never passed to the client). Modules.kt injects UserAppPreferencesStore.
  • Fix the settings preset/help text (localhost, not 0.0.0.0).

Tests: rewrite ApplicationTest to compile against the real module() and cover the health endpoint, rejected targets (allow-list, https, private SSRF guard), CORS preflight, and a full proxied round-trip (7 tests).

Deploy: server/Dockerfile (fat JAR), .dockerignore, fly.toml (Fly.io template), a GHCR image-publish workflow, and server/README.md documenting self-hosting and the credential-in-transit trust caveat. Update the main README accordingly.

Claude-Session: https://claude.ai/code/session_01VSN8H3sD3ZFXMbGb36Ls8q

The Web (WASM) build routes CalDAV/WebDAV traffic through the Ktor proxy in
server/ to work around browser CORS. This makes the proxy safe to host publicly
and adds the artifacts to deploy it.

Proxy hardening (server/Application.kt):
- SSRF/open-relay guard: validate the caller-supplied target — scheme check,
  optional host allow-list, https-only, and block loopback/link-local/private/
  unique-local addresses (e.g. 169.254.169.254).
- Configurable via env: PORT, PROXY_ALLOWED_ORIGINS, PROXY_ALLOWED_TARGET_HOSTS,
  PROXY_REQUIRE_HTTPS_TARGET, PROXY_ALLOW_PRIVATE_TARGETS.
- CORS restricted to configured origins (was anyHost + credentials).
- Forward the request body whenever one is present, fixing WebDAV LOCK.
- Don't forward Origin/Referer/Cookie; drop upstream Access-Control-* on the
  response; use slf4j logging instead of println.
- Add the package declaration so the configured mainClass resolves.

Wire up the in-app proxy setting (shared):
- HttpClientFactory now resolves the proxy URL per request via a provider, so
  the "Proxy server" setting takes effect (previously the preference was never
  passed to the client). Modules.kt injects UserAppPreferencesStore.
- Fix the settings preset/help text (localhost, not 0.0.0.0).

Tests: rewrite ApplicationTest to compile against the real module() and cover
the health endpoint, rejected targets (allow-list, https, private SSRF guard),
CORS preflight, and a full proxied round-trip (7 tests).

Deploy: server/Dockerfile (fat JAR), .dockerignore, fly.toml (Fly.io template),
a GHCR image-publish workflow, and server/README.md documenting self-hosting and
the credential-in-transit trust caveat. Update the main README accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VSN8H3sD3ZFXMbGb36Ls8q
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.

2 participants