Changelog
1.0.0 — 2026-09-12
Initial release.
Added
- Core password gate: a single shared password protects any backend web service with no auth of its own (built for BlueMap, works with anything similar such as Dynmap), using a random server-side session token stored in an
HttpOnlycookie. default-password-mode(block/warn) — fails closed while the password is still the packaged default, unless explicitly opted out of for local demos/dev.- IP
ip-allow-list(bypasses the password entirely) andip-block-list(always denied), matched against the real TCP source address by default. trust-proxy-headers— explicit opt-in to trustX-Forwarded-For/X-Forwarded-Proto/CF-Visitor/Front-End-Httpswhen a reverse proxy sits in front, off by default.- Optional self-signed HTTPS (
tls-enabled) — certificate generated and reused automatically via the JDK's bundledkeytool, no external tools required. - Support for loading a real CA-issued certificate instead of self-signing one (⚠ unconfirmed/untested — see README).
- In-game/console commands:
/mapgate setpassword,/mapgate reload,/mapgate sessions,/mapgate regenerate-cert.
Fixed — automated security/code review pass
A GitHub Copilot review of the initial implementation surfaced 13 issues, all addressed before this release:
- Security: rejected negative/out-of-range CIDR prefixes that could bypass the allow-list entirely; switched
X-Forwarded-Forparsing to the rightmost (proxy-appended) entry instead of the spoofable leftmost one; the session cookie is now markedSecurewhenever the connection is confirmed encrypted; added per-IP login rate limiting (5 failed attempts/minute);/mapgate setpasswordnow invalidates all existing sessions immediately;/mapgate regenerate-certand first-run certificate generation now refuse to touch a keystore at a non-default path, so a user-supplied CA certificate can't be silently destroyed; the generated certificate's SHA-256 fingerprint is now actually logged (SECURITY.md already documented comparing it). - Resource exhaustion / lifecycle: replaced an unbounded cached thread pool with a bounded, properly-shut-down one; capped the login endpoint's request body at 8KB; added finite connect/read timeouts on the backend proxy connection; the TLS keystore is now loaded/validated before the public HTTPS socket is bound, so a bad certificate can't orphan a listener on the port.
- Correctness: fixed a bug where a genuine backend connection failure could skip the intended
502response; session cleanup now also runs on every new login rather than only when triggered elsewhere. - Docs: corrected the session cookie's description (random token, not cryptographically signed) and the Building From Source classpath separator (was Windows-style
;under ash-labeled command).
Known limitations
- The proxy only forwards a request body for
POST/PUT— aDELETEwith a body reaches the backend empty, andPATCHisn't supported at all (aHttpURLConnectionlimitation). Not an issue for BlueMap/Dynmap-style read-mostly services; fixing it generically would mean moving offHttpURLConnection. - Loading a real CA-issued certificate (as opposed to self-signing) is implemented but not yet verified end-to-end.
- No automated tests yet — planned alongside a move to Gradle in the next release.