Perform a dummy LDAP bind when SearchDN fails so that the response time
is indistinguishable between unknown users and wrong passwords.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add self-hosted style.css replacing Bootstrap CDN dependency
- Add profile.html with tabbed view (account info, emails/aliases, API token)
- Refactor login handler to pass structured data to template instead of building HTML strings
- Add brand-name and brand-logo flags/env vars for UI customization
- Update CSP to allow brand logo domain and remove CDN references
- Update all templates to pass template vars to header/footer and use new CSS classes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace map[string]interface{} with map[string]any, ioutil.ReadAll with
io.ReadAll, and simplify redundant fmt.Sprintf/w.Write calls.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Integrate go-altcha to protect login, change password, lost password,
and reset password forms against automated submissions. Serves the
altcha widget JS from the embedded library, exposes a challenge
endpoint, validates responses server-side with replay prevention, and
updates the CSP to allow self-hosted scripts and WebAssembly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace hardcoded "docker-registry" check with a configurable secret via
DOCKER_REGISTRY_SECRET env var. When the env var is unset, the anonymous
docker registry bypass is disabled entirely, closing the unauthenticated
access path if the service is accidentally exposed directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implement sliding window rate limiter to prevent brute-force attacks:
- /auth and /login: 20 requests/minute per IP
- /change: 10 POST requests/minute per IP
- /lost: 5 POST requests/minute per IP (prevents email spam and user enumeration)
- /reset: 10 POST requests/minute per IP
- /api/v1/aliases: 30 requests/minute per IP
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use html.EscapeString for attribute names and values when building HTML.
Move dynamic data (alias URL, API token) to data-* attributes and use
a self-contained onclick function to read them, eliminating JS string
injection via LDAP-controlled values.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>