Repository navigation
Releases
Releases · lukepoo101/dsh-trusted-proxy-auth
v0.2.3: Intercept WebServer.match for runtime route normalisation
[0.2.3] - 2026-09-25
Fixed
- Intercept \webServer.match\ for runtime route normalisation:
- In DeepSeek Harness (@deepseek-ai/dsh-host-webserver@0.1.5-rc.2), \webServer.handle\ is a local closure inside [Service.init]()\ rather than an instance method on the \WebServer\ service. As a result, wrapping \webServer.handle\ alone did not intercept routes during live HTTP dispatch.
- Intercepted \webServer.match(pathname)\ instead, which dynamically decorates the matched route's \handler\ at dispatch time with loopback normalisation (
eq.headers.host\ -> \127.0.0.1:\ and
eq.headers.origin\ -> \http://127.0.0.1:). - Preserves DSH's internal routing table (\exact\ and \prefixes\ maps) untouched, ensuring clean disposal on plugin unload.
- Fixes HTTP 403 \untrusted origin\ on \dshmarket\ discovery and mutation endpoints (/dsh-market/discovery-compatibility, /dsh-market/update, etc.) when accessed through reverse proxies.
- Maintained \webServer.handle\ wrapping as a backward-compatible fallback for custom test harnesses and standalone web server implementations.
- Added unit test simulating the real-DSH \WebServer\ dispatch pattern without a \handle\ method (86 unit tests pass).
v0.2.2: Loopback route normalisation for third-party plugins
Added
- Loopback normalisation for third-party plugin routes:
- Decorates \webServer.handle\ to normalise incoming proxy-authenticated requests to the local loopback authority (\127.0.0.1:).
- Enables third-party plugins with strict loopback/same-origin checks (such as \dshmarket@1.65.1\ protecting /dsh-market/discovery-compatibility, /dsh-market/update, etc.) to operate seamlessly across reverse-proxied domains.
- Strict security fence: evaluates DSH's native Host/Origin/Cross-Site checks (
equestRejection) against real inbound headers before normalising; cross-origin CSRF attacks, cross-site fetch metadata, or untrusted Hosts are immediately rejected with HTTP 403 Forbidden. - Preserves incoming public authority in \X-Forwarded-Host\ and \X-Forwarded-Proto.
- Comprehensive third-party plugin route validation suite (85 unit tests pass).
Changed
- Cleaned up deprecated \�ttachBootstrapInjection\ stub.
- Generalised \captureMethod\ and \installWrapper\ for uniform transactional decoration across \connection\ and \webServer.
v0.2.1 - Fix 502 Bad Gateway via tapIndex and index-inject
[0.2.1] - 2026-09-25
Fixed
- Eliminated 502 Bad Gateway / empty HTTP reply on authenticated index requests: reverted ServerResponse.writeHead, write, and end monkey-patching in authorizeIndex. Response streaming and headers are now left entirely to DSH's native HTTP pipeline.
- Migrated ownsHost bootstrap injection to DSH's supported extension seams:
- webServer.tapIndex: registers a pure HTML transform applied by DSH's renderIndex pipeline.
- webserver/index-inject: listens for the structured injection event and pushes { kind: 'global', name: 'DSH_TRANSPORT', value: { ownsHost: true } }.
- Made HTML injection idempotent so that tapIndex skips injection if structured DSH_TRANSPORT injection is already present in the rendered document.
- Unit tests updated to verify native response preservation and extension seam registration (62 unit tests pass).
v0.2.0 - Proxy-authenticated browser settings bootstrap
Changelog
All notable changes to this project are documented here. The format is based on
Keep a Changelog and this project
adheres to Semantic Versioning.
[0.2.0] - 2026-09-25
Added
- Proxy-authenticated browser bootstrap injection: when
authorizeIndexverifies
a request carrying a validX-DSH-Proxy-Authsecret, it attaches a response
decorator that injectsglobalThis.__DSH_TRANSPORT__.ownsHost = trueinto the
servedindex.html. - Enables DSH host persistence (
ctx.remote.$host.isLoopback === true->
persistence = "host") for reverse-proxied domains (such as
dsh.terraurbs.com), fixing the issue where the Models directory, Plugin
settings, and Provider configuration appeared empty or reported "settings are
unavailable in this browser". - Server-verified: the bootstrap script is only injected when the reverse proxy
has supplied the correct shared secret. Unauthenticated or native loopback
access receives standard unmodified HTML. - Safe HTTP streaming handling: strips or suppresses stale
Content-Length
response headers so chunked encoding transfers the injected document cleanly
without truncation. - Unit tests covering bootstrap injection, HTML insertion rules (in
<head>,
before</head>, or prepended), andContent-Lengthremoval.
[0.1.0] - 2026-09-20
Added
dsh-trusted-proxy-authhost plugin for DeepSeek Harness that permits a
request authenticated by a trusted reverse proxy via theX-DSH-Proxy-Auth
header and theDSH_PROXY_AUTH_SECRETenvironment secret.- Constant-time secret comparison over UTF-8 bytes with a 32-byte minimum and a
printable-ASCII-minus-comma charset. requestRejectiondecoration that only converts an upstream401into a
permit, never an upstream403.authorizeIndexdecoration that keeps the Host/Origin fence while bypassing
native browser authentication for trusted-proxy requests.- Startup semantic invariant: activation probes the original
requestRejection
and refuses to start unless the trust fence still returns403and missing
native browser authentication still returns401. - Fail-closed, transactional activation: bad configuration fails the profile,
and any partial decoration (a write that failed verification, or a disposer
that failed to register) is rolled back. - Compare-and-swap cleanup that restores the original connection instance shape
and cannot stack wrappers across HMR/reload; wrappers carry a registered
(Symbol.for) marker so two module generations unwrap each other. - 50 unit tests and a 35-check real-DSH integration harness.
- CI with a pinned real-DSH integration gate on push/PR and a scheduled
@latestdrift watch. - Documentation: README, threat model, validation record, Traefik contract.
v0.1.0 — trusted-proxy authentication for DSH
First release.
Host-only DeepSeek Harness plugin that trusts authentication already performed by a reverse proxy (for example Traefik after Keycloak OIDC) via the X-DSH-Proxy-Auth header and DSH_PROXY_AUTH_SECRET, while keeping native DSH browser launch-token/cookie authentication as a fallback.
Highlights:
- only promotes an upstream 401; an upstream 403 (Host/Origin/DNS-rebinding fence) is always preserved
- startup semantic invariant proves 403/401 meaning on every boot
- constant-time comparison, 32-byte minimum, printable-ASCII-minus-comma charset
- fail-closed, transactional activation with exact-shape cleanup (no wrapper stacking)
- 50 unit tests and a 35-check real-DSH integration harness
- CI: pinned real-DSH integration gate on push/PR plus a scheduled @latest drift watch
Tested against DSH 0.1.5-rc.2 on Node v24.21.0 (CI Node 20/22/24).