Skip to content
☁️ HitKeep Cloud is coming! Join the Early Access waitlist →

Security Overview

Enterprise and government deployments require auditability at every layer. This page documents every security control in HitKeep — from the HTTP server to the browser, and everything in between.

When a visitor loads your HitKeep dashboard, their browser makes zero requests to third-party domains. Every asset — the Angular application, fonts, icons, and the tracking snippet — is served from your own instance.

AssetSource
Angular dashboard (JS, CSS)your-instance.example.com
PrimeIcons, fontsBundled into the Angular app — served from your instance
hk.js tracking snippetyour-instance.example.com/hk.js
Favicon imagesServer-side proxied (see below) — no browser-to-third-party requests
API callsyour-instance.example.com/api/* exclusively

This is verifiable: open your browser’s Network tab with HitKeep loaded and filter by third-party requests. There are none.

This matters for:

  • Content Security Policy (CSP) — you can write a restrictive default-src 'self' policy without allowlisting external domains
  • GDPR Article 44+ — no data transfer to third countries via asset loading
  • Zero Trust network policies — HitKeep dashboard users do not need outbound internet access
  • Air-gapped deployments — the dashboard works with no external connectivity whatsoever

The dashboard displays site favicons to help identify tracked domains. Favicons are fetched via DuckDuckGo’s public favicon service (icons.duckduckgo.com), but the request is made server-side by HitKeep, not by the browser.

The browser requests:

GET /api/favicon/{domain} ← your HitKeep instance only

HitKeep’s server then fetches:

GET https://icons.duckduckgo.com/ip3/{domain}.ico

The browser never contacts DuckDuckGo. The favicon is proxied back with a 24-hour cache header.

Security properties of the proxy implementation:

  • Domain is validated and normalized before the upstream request is constructed
  • URL is built programmatically using url.URL (no string interpolation) to prevent injection
  • HTTP redirects from the upstream are NOT followed (prevents SSRF via redirect chaining)
  • 5-second upstream timeout enforced
  • The //go:build comment on the handler documents the intent explicitly: the URL is constrained to DuckDuckGo’s fixed host only

Source: internal/server/sites/handlers.gohandleGetFavicon()

HitKeep contains no telemetry, no usage reporting, and no phone-home mechanism of any kind.

What doesn’t happenNotes
Version check to external serverNever performed
Crash/error reporting to external serviceErrors log locally via slog only
Feature flag fetch from external endpointNo feature flag service used
License validation against external serverMIT license — no validation needed
Anonymous usage statisticsNot collected

You can run HitKeep in an air-gapped environment with no outbound internet access and it will operate identically to an internet-connected deployment.

Verification: The full source is MIT-licensed on GitHub. Audit cmd/ and internal/ for any net/http calls — they are exclusively inbound (serving requests) or the single server-side favicon proxy described above.

HitKeep uses JSON Web Tokens stored in HTTP-only cookies for session authentication.

PropertyValue
StorageHTTP-only cookie (not accessible to JavaScript)
ExpiryShort — configured by the operator via -jwt-duration flag
AlgorithmHMAC-SHA256
SecretSet via HITKEEP_JWT_SECRET environment variable — minimum 32 bytes recommended
ScopePer-user claims, not shared

HTTP-only cookies eliminate the risk of token theft via XSS — even if a malicious script runs in the page, it cannot read the session cookie.

RFC 6238 time-based one-time passwords. Compatible with any standard authenticator app (Authy, Google Authenticator, 1Password, Bitwarden).

  • Secret stored per-user in DuckDB on your server
  • QR code is generated server-side and shown once during enrollment
  • TOTP is enforced at every login after enrollment

FIDO2-compliant challenge-response authentication. Supports hardware security keys (YubiKey, etc.) and platform authenticators (Face ID, Touch ID, Windows Hello).

  • No password required
  • Private key never leaves the user’s device or security key
  • Phishing-resistant by design (origin-bound)

See Two-Factor Authentication →

HitKeep enforces role-based access control at two levels:

LevelRoles
Instanceadmin (full access), user (site-scoped access)
Siteowner (full site control), viewer (read-only)

All role checks are enforced server-side in Go. The Angular dashboard reflects the current user’s roles, but access control is not dependent on frontend enforcement.

See Permissions & Roles →

All public and authenticated endpoints are protected by per-IP token bucket rate limiters.

EndpointDefault behavior
POST /ingestPer-IP rate limited to absorb burst traffic safely
POST /api/loginStricter rate limit to prevent brute-force attacks
GET /api/*Per-IP rate limited

Rate limits are configurable via flags. See Configuration Reference →

State-changing requests are validated against Sec-Fetch-* headers sent by modern browsers. This adds a layer of CSRF protection — requests that don’t originate from a browser navigation (e.g., cross-origin form submissions or programmatic fetch calls without the correct context) are rejected.

This is in addition to, not a replacement for, JWT authentication.

HitKeep serves HTTP on the configured port. TLS termination is handled by your reverse proxy (Caddy, Traefik, nginx, or a cloud load balancer). This is the standard practice for Go applications.

Recommendation for production: Run behind Caddy with automatic HTTPS — it handles Let’s Encrypt certificate provisioning and renewal with a single reverse_proxy directive.

Configure security headers at your reverse proxy layer. Recommended headers for HitKeep deployments:

Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), camera=(), microphone=()

Because HitKeep serves all assets from the same origin, a default-src 'self' policy is achievable without allowlisting external CDNs.

HitKeep is fully operational with no outbound internet access:

  • No license server calls
  • No telemetry
  • No external CDN dependencies for assets
  • Favicon proxy is the only outbound call — and it’s optional (favicons degrade gracefully if the upstream is unreachable)
  • Docker image can be pulled once, pushed to a private registry, and used offline indefinitely

HitKeep has a coordinated disclosure policy. To report a security vulnerability, use GitHub Security Advisories.

See SECURITY.md on GitHub →

HitKeep Cloud runs this same security model in dedicated infrastructure (EU Frankfurt / US Virginia) with additional perimeter controls. Join the waitlist →