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
Authorizationheader 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:
environment:
ApiKey__MinLength: "32"
ApiKey__AllowInQueryString: "false"
ApiKey__HeaderName: "X-API-Key"
ApiKey__RateLimitPerKey: "true"
ApiKey__RotationDays: "90"
Bare Metal / systemd
Edit appsettings.json:
{
"ApiKey": {
"Enabled": true,
"MinLength": 32,
"HeaderName": "X-API-Key",
"AllowInQueryString": false,
"RateLimitPerKey": true,
"RotationDays": 90
}
}
Kubernetes / Helm
Set in Helm values:
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 configurationcheck.security.secrets— ensures API keys are not stored as plain textcheck.core.auth.config— validates overall authentication configuration
