{"record":{"id":"a5134f4779dc26a3","repo":"zeroclaw-labs/zeroclaw","slug":"empty-bearer-token","errorCode":null,"errorMessage":"empty bearer token","messagePattern":"empty bearer token","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/security/nevis.rs","lineNumber":138,"sourceCode":"        Ok(Self {\n            instance_url,\n            realm,\n            client_id,\n            client_secret,\n            validation_mode,\n            jwks_url,\n            require_mfa,\n            session_timeout: Duration::from_secs(session_timeout_secs),\n            http_client,\n        })\n    }\n\n    /// Validate a bearer token and resolve the caller's identity.\n    /// Returns `NevisIdentity` on success, or an error if the token is invalid,\n    /// expired, or MFA requirements are not met.\n    pub async fn validate_token(&self, token: &str) -> Result<NevisIdentity> {\n        if token.is_empty() {\n            bail!(\"empty bearer token\");\n        }\n\n        let identity = match self.validation_mode {\n            TokenValidationMode::Local => self.validate_token_local(token).await?,\n            TokenValidationMode::Remote => self.validate_token_remote(token).await?,\n        };\n\n        if self.require_mfa && !identity.mfa_verified {\n            bail!(\n                \"MFA is required but user '{}' has not completed MFA verification\",\n                crate::security::redact(&identity.user_id)\n            );\n        }\n\n        let now = std::time::SystemTime::now()\n            .duration_since(std::time::UNIX_EPOCH)\n            .unwrap_or_default()\n            .as_secs();","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/security/nevis.rs#L120-L156","documentation":"NevisAuthProvider::validate_token rejects the call before any network or signature work when the token string is empty (nevis.rs:137-139). It is a fail-fast input guard: it always fires immediately and never contacts the Nevis instance. Hitting it means your code extracted no bearer token from the request but still called the validator.","triggerScenarios":"Calling validate_token with an empty string — typically because the Authorization header was missing, used a different scheme or header name, or the 'Bearer ' prefix stripping left an empty value; tests pass an unset env var or String::new().","commonSituations":"Gateway middleware forwards an empty string when the Authorization header is absent; client sends the token in x-api-key instead; config template ships an empty token value; integration tests forget to inject the token.","solutions":["Reject requests whose Authorization header is missing or has no token before calling validate_token (return 401 early)","Check token.trim().is_empty() in your middleware and log which header name was inspected","Verify your header parsing strips the 'Bearer ' scheme and uses the same header name your clients send"],"exampleFix":"// before\nlet token = auth_header.unwrap_or_default();\nlet identity = provider.validate_token(&token).await?;\n\n// after\nlet token = auth_header\n    .and_then(|h| h.strip_prefix(\"Bearer \"))\n    .map(str::trim)\n    .filter(|t| !t.is_empty())\n    .ok_or_else(|| anyhow::anyhow!(\"missing bearer token\"))?;\nlet identity = provider.validate_token(token).await?;","handlingStrategy":"validation","validationCode":"fn extract_bearer(header: Option<&str>) -> Option<&str> {\n    header?\n        .strip_prefix(\"Bearer \")\n        .map(str::trim)\n        .filter(|t| !t.is_empty())\n}","typeGuard":null,"tryCatchPattern":"If validate_token still errors, match on err.to_string().contains(\"empty bearer token\") and return 401 immediately — never retry and never treat it as an IdP outage.","preventionTips":["Centralize Authorization header extraction in one middleware that returns 401 on empty","Log which header name was inspected, never the token value","Add a unit test that a missing Authorization header never reaches validate_token"],"tags":["auth","nevis","bearer-token","input-validation","rust"],"backgroundTag":"empty-bearer-token","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}