--- checkId: check.security.apikey plugin: stellaops.doctor.security severity: warn tags: [security, apikey, authentication] --- # API Key Security ## What It Checks Validates API key configuration and security practices. The check only runs when an API key configuration section exists (`ApiKey`, `Authentication:ApiKey`, or `Security:ApiKey`). It inspects: | Setting | Threshold/Condition | Issue | |---|---|---| | `MinLength` | Less than 32 characters | Key too short (escalates to `fail` if < 16) | | `AllowInQueryString` | `true` | Keys in query strings get logged in access logs | | `HeaderName` | Equals `Authorization` | Conflicts with other auth schemes | | `RateLimitPerKey` | `false` or not set | Compromised key could abuse the API without limits | | `RotationDays` | Not set | No rotation policy configured | | `RotationDays` | Greater than 365 | Rotation period is very long | If API key authentication is explicitly disabled (`Enabled: false`), the check reports an informational result and exits. ## Why It Matters API keys are the primary authentication mechanism for service-to-service communication and CI/CD integrations. Short keys can be brute-forced. Keys passed in query strings are recorded in web server access logs, proxy logs, and browser history, creating exposure vectors. Without per-key rate limiting, a compromised key allows unlimited API abuse. Without rotation, a leaked key remains valid indefinitely. ## Common Causes - Minimum API key length configured below 32 characters - API keys allowed in query strings (`AllowInQueryString: true`) - Using the `Authorization` header for API keys, conflicting with JWT/OAuth - Per-key rate limiting not enabled - API key rotation policy not configured or set to more than 365 days ## How to Fix ### Docker Compose Set API key security configuration in environment variables: ```yaml environment: ApiKey__MinLength: "32" ApiKey__AllowInQueryString: "false" ApiKey__HeaderName: "X-API-Key" ApiKey__RateLimitPerKey: "true" ApiKey__RotationDays: "90" ``` ### Bare Metal / systemd Edit `appsettings.json`: ```json { "ApiKey": { "Enabled": true, "MinLength": 32, "HeaderName": "X-API-Key", "AllowInQueryString": false, "RateLimitPerKey": true, "RotationDays": 90 } } ``` ### Kubernetes / Helm Set in Helm values: ```yaml apiKey: minLength: 32 headerName: "X-API-Key" allowInQueryString: false rateLimitPerKey: true rotationDays: 90 ``` ## Verification ``` stella doctor run --check check.security.apikey ``` ## Related Checks - `check.security.ratelimit` — validates global rate limiting configuration - `check.security.secrets` — ensures API keys are not stored as plain text - `check.core.auth.config` — validates overall authentication configuration