---
title: "HitKeep Security Model for Analytics Deployments | HitKeep"
description: "Review HitKeep security controls for analytics deployments, including zero third-party frontend requests, JWT auth, WebAuthn, TOTP, rate limits, and cross-origin request protection."
canonical: "https://hitkeep.com/reference/security/"
---

# HitKeep Security Model for Analytics Deployments

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.

## Zero Third-Party Frontend Requests

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.

| Asset | Source |
| --- | --- |
| Angular dashboard (JS, CSS) | your-instance.example.com |
| OpenNG icons, fonts | Bundled into the Angular app — served from your instance |
| hk.js tracking snippet | your-instance.example.com/hk.js |
| Favicon images | Server-side proxied (see below) — no browser-to-third-party requests |
| API calls | your-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
- **Restricted-network deployments** — the dashboard works without third-party frontend assets or external analytics calls

## Favicon Proxy

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.go` — `handleGetFavicon()`

## Zero Telemetry

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

| What doesn’t happen | Notes |
| --- | --- |
| Version check to external server | Never performed |
| Crash/error reporting to external service | Errors log locally via slog only |
| Feature flag fetch from external endpoint | No feature flag service used |
| License validation against external server | MIT license — no validation needed |
| Anonymous usage statistics | Not collected |

You can run HitKeep core analytics in a restricted network with no outbound internet access when optional outbound features, including configured operational webhooks, are disabled.

**Verification:** The full source is MIT-licensed on [GitHub](https://github.com/pascalebeier/hitkeep). Audit `cmd/` and `internal/` for outbound integrations such as favicon lookup, mail delivery, S3 backup/archive paths, or optional AI provider calls before using HitKeep in a tightly restricted network.

## Optional AI Provider Calls

AI-powered product features are off by default. When `HITKEEP_AI_ENABLED=true` and a provider/model are configured, HitKeep can send a structured, feature-specific request to the configured provider or gateway.

Route production AI through a gateway

HitKeep has a rudimentary global AI request and token limiter. It is a coarse process-level safeguard, not per-user, per-site, per-provider-key, or a security policy engine. For production use, route model traffic through an AI gateway or provider policy layer that can enforce detailed quotas, model allowlists, key isolation, audit logging, redaction, and network controls. See GoAI’s [supported provider options](https://goai.sh/providers/) and [generic OpenAI-compatible provider](https://goai.sh/providers/compat.html) docs for the underlying base URL, token, header, and custom endpoint patterns.

For Opportunities, detectors create the recommendation candidate first. HitKeep accepts only approved translation keys, interpolation params, and cited evidence IDs from the provider response. Output that does not match the detector contract is rejected before saving.

HitKeep does not persist raw prompts, raw provider responses, raw external error bodies, or provider secrets. AI run records keep audit metadata, hashes, token/request usage where available, lifecycle events, safe error categories, and the final validated structured output.

## Authentication

### JWT (Session Tokens)

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

| Property | Value |
| --- | --- |
| Storage | HTTP-only cookie (not accessible to JavaScript) |
| Expiry | Short. Defaults to 15 minutes and is configured with -auth-session-minutes |
| Algorithm | HMAC-SHA256 |
| Secret | Set via HITKEEP_JWT_SECRET environment variable — minimum 32 bytes recommended |
| Scope | Per-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.

The dashboard shows the remaining session time and opens an accessibility-friendly warning before expiry. Users can extend the session with one action. Operators can configure the warning lead time with `-auth-session-warning-seconds`.

If a user signs out, or the session ends before the next request can refresh it, HitKeep returns to the login screen with a short status message that distinguishes intentional sign-out from an ended session. The message is announced through an accessible polite status region; a direct visit to `/login` does not show either notice.

When remember-me is enabled by the user, HitKeep stores a separate HTTP-only remembered sign-in token. Its lifetime defaults to 30 days and is configured with `-auth-remember-me-days`. The dashboard session API exposes both the remembered expiry and configured duration so the frontend reflects the operator policy instead of hardcoding it.

### Two-Factor Authentication (TOTP)

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

### Passkeys (WebAuthn / FIDO2)

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

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

See [Two-Factor Authentication →](https://hitkeep.com/guides/security/two-factor-authentication/)

### Social Sign-In

Instance operators can enable Google, GitHub, and Microsoft as additional primary login methods. HitKeep uses authorization code flow with browser-bound one-time state and PKCE S256. Google and Microsoft use OIDC nonce validation. GitHub uses its numeric user ID plus a primary verified email. Provider access, ID, and refresh tokens are discarded after the exchange.

Google and GitHub must return a verified email. Microsoft identities are keyed by tenant ID plus object ID and require HitKeep email confirmation when an authenticated session or matching invitation has not already proved the target account. Existing HitKeep MFA still runs before a social login receives a browser session.

Users can link or unlink providers under **Settings → Security**. HitKeep refuses to remove the last usable primary login method.

See [Configure Social Sign-In →](https://hitkeep.com/guides/security/social-sign-in/)

### Team Single Sign-On (OIDC)

Team owners and admins can connect a team to one OpenID Connect provider. HitKeep uses Authorization Code flow with PKCE S256, provider discovery, state, nonce, issuer and audience validation, and a required verified-email claim. Provider tokens are not stored after HitKeep creates its normal browser session. Managed-cloud discovery and provider requests are restricted to bounded HTTPS responses from publicly routable addresses; self-hosted operators can use reachable internal providers.

SSO is an additional login method. Password and passkey sign-in remain available, and provider groups are not mapped to HitKeep roles. HitKeep Cloud gates team SSO behind the Business plan; self-hosted deployments include it without a plan gate.

See [Configure OIDC Single Sign-On →](https://hitkeep.com/guides/security/single-sign-on/)

## Authorization (RBAC)

HitKeep enforces role-based access control at two levels:

| Level | Roles |
| --- | --- |
| Instance | owner (full instance control), admin (operational administration), user (site-scoped access) |
| Site | owner (full site control), admin (site administration), editor (goals and funnels), 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 →](https://hitkeep.com/guides/admin/permissions/)

## Rate Limiting

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

| Endpoint | Default behavior |
| --- | --- |
| POST /ingest | Per-IP rate limited to absorb burst traffic safely |
| POST /api/ingest/server/* | API-client-only server-side ingest for non-browser clients. Does not require browser Origin/Referer headers, uses the ingest limiter, and forwards from followers to the leader in clustered deployments |
| POST /api/login | Stricter rate limit to prevent brute-force attacks |
| GET /api/* | Per-IP rate limited |

Rate limits are configurable via flags. See [Configuration Reference →](https://hitkeep.com/reference/configuration/)

MCP uses the API limiter and API client bearer-token authorization. AI fetch ingest uses the authenticated API surface, so crawler log forwarders should use scoped API client tokens instead of dashboard cookies.

## Cross-Origin Request Protection

HitKeep uses Go’s standard cross-origin protection as a defense-in-depth control for cookie-authenticated browser requests. Unsafe browser methods such as `POST`, `PUT`, `PATCH`, and `DELETE` are rejected when `Sec-Fetch-Site` identifies a cross-site or same-site initiator. When Fetch Metadata is unavailable, the server compares `Origin` with the request host.

Safe `GET`, `HEAD`, and `OPTIONS` requests remain available for normal navigation and token-bound authentication callbacks. Requests without `Sec-Fetch-Site` or `Origin` are treated as same-origin or non-browser traffic and continue to normal authentication and authorization. Server-to-server API clients, MCP clients, signed webhooks, and crawler forwarders should not synthesize browser-only headers.

The three public tracker ingest routes intentionally accept cross-origin browser POSTs. Their handlers validate the browser `Origin`, resolve the matching site, apply custom tracking-host checks, and enforce ingest rate limits before accepting analytics data.

This protection complements JWT authentication, API-client bearer tokens, callback state validation, and SameSite cookies; it does not replace them.

## TLS / HTTPS

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.

## Security Headers

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.

## Restricted-Network Operation

HitKeep core analytics can run with no outbound internet access:

- No license server calls
- No telemetry
- No external CDN dependencies for assets
- Optional features such as favicon lookup, SMTP delivery, S3 backups, Search Console sync, configured operational webhooks, and AI provider enrichment can add outbound calls
- Docker image can be pulled once, pushed to a private registry, and used offline indefinitely

## Vulnerability Reporting

HitKeep has a coordinated disclosure policy. To report a security vulnerability, use [GitHub Security Advisories](https://github.com/pascalebeier/hitkeep/security/advisories).

See [SECURITY.md on GitHub →](https://github.com/pascalebeier/hitkeep/blob/main/SECURITY.md)

## Related

- [Two-Factor Authentication](https://hitkeep.com/guides/security/two-factor-authentication/)
- [Social Sign-In](https://hitkeep.com/guides/security/social-sign-in/)
- [Single Sign-On (OIDC)](https://hitkeep.com/guides/security/single-sign-on/)
- [API Clients](https://hitkeep.com/guides/security/api-clients/)
- [Official MCP Server](https://hitkeep.com/guides/integrations/mcp/)
- [Signed Outbound Webhooks](https://hitkeep.com/guides/integrations/webhooks/)
- [HitKeep Agent Skills](https://hitkeep.com/guides/integrations/hitkeep-agent-skills/)
- [AI Fetch Ingest](https://hitkeep.com/guides/tracking/ai-fetch-ingest/)
- [AI Fetch on AWS](https://hitkeep.com/guides/tracking/ai-fetch-aws/)
- [Opportunity Recommendations](https://hitkeep.com/guides/analytics/opportunities/)
- [Permissions & Roles](https://hitkeep.com/guides/admin/permissions/)
- [Architecture](https://hitkeep.com/reference/architecture/)
- [Configuration Reference](https://hitkeep.com/reference/configuration/)
- [Trusted Proxies](https://hitkeep.com/guides/installation/trusted-proxies/)

HitKeep Cloud uses the same product security model in managed EU or US infrastructure with region-specific hosting. [Start with HitKeep Cloud →](https://cloud.hitkeep.eu/signup?plan=free&billing=monthly&utm_source=hitkeep_docs&utm_medium=referral&utm_campaign=cloud_signup&utm_content=docs_inline)

[Previous Technology stack](https://hitkeep.com/reference/tech-stack/)[Next REST API](https://hitkeep.com/api/)
