diff --git a/src/cortex-cli/src/cli/handlers.rs b/src/cortex-cli/src/cli/handlers.rs index e92fa8632..7fa0d117a 100644 --- a/src/cortex-cli/src/cli/handlers.rs +++ b/src/cortex-cli/src/cli/handlers.rs @@ -538,7 +538,7 @@ pub async fn run_whoami() -> Result<()> { // Check environment variables first if let Ok(token) = std::env::var("CORTEX_AUTH_TOKEN") - && !token.is_empty() + && !token.trim().is_empty() { println!( "Authenticated via CORTEX_AUTH_TOKEN: {}", @@ -548,7 +548,7 @@ pub async fn run_whoami() -> Result<()> { } if let Ok(token) = std::env::var("CORTEX_API_KEY") - && !token.is_empty() + && !token.trim().is_empty() { println!( "Authenticated via CORTEX_API_KEY: {}", diff --git a/src/cortex-cli/src/login.rs b/src/cortex-cli/src/login.rs index 138451fc9..02b5f4ee6 100644 --- a/src/cortex-cli/src/login.rs +++ b/src/cortex-cli/src/login.rs @@ -132,7 +132,7 @@ pub async fn run_login_status(config_overrides: CliConfigOverrides) -> ! { // Check environment variables first (CORTEX_AUTH_TOKEN and CORTEX_API_KEY) if let Ok(token) = std::env::var("CORTEX_AUTH_TOKEN") - && !token.is_empty() + && !token.trim().is_empty() { print_success(&format!( "Authenticated via CORTEX_AUTH_TOKEN environment variable: {}", @@ -142,7 +142,7 @@ pub async fn run_login_status(config_overrides: CliConfigOverrides) -> ! { } if let Ok(token) = std::env::var("CORTEX_API_KEY") - && !token.is_empty() + && !token.trim().is_empty() { print_success(&format!( "Authenticated via CORTEX_API_KEY environment variable: {}", diff --git a/src/cortex-engine/src/auth_token.rs b/src/cortex-engine/src/auth_token.rs index ada5411d1..bd9960e06 100755 --- a/src/cortex-engine/src/auth_token.rs +++ b/src/cortex-engine/src/auth_token.rs @@ -17,6 +17,10 @@ use crate::error::{CortexError, Result}; +fn has_token_value(token: &str) -> bool { + !token.trim().is_empty() +} + /// Get authentication token with optional instance override. /// /// Priority order: @@ -44,7 +48,7 @@ use crate::error::{CortexError, Result}; pub fn get_auth_token(instance_token: Option<&str>) -> Result { // Priority 1: Instance token (if provided and non-empty) if let Some(token) = instance_token { - if !token.is_empty() { + if has_token_value(token) { tracing::debug!(source = "instance", "Using auth token from client instance"); return Ok(token.to_string()); } @@ -52,7 +56,7 @@ pub fn get_auth_token(instance_token: Option<&str>) -> Result { // Priority 2: CORTEX_AUTH_TOKEN environment variable if let Ok(token) = std::env::var("CORTEX_AUTH_TOKEN") { - if !token.is_empty() { + if has_token_value(&token) { tracing::debug!( source = "env_var", "Using auth token from CORTEX_AUTH_TOKEN" @@ -63,7 +67,7 @@ pub fn get_auth_token(instance_token: Option<&str>) -> Result { // Priority 3: CORTEX_API_KEY environment variable (alias for GitHub Actions workflow) if let Ok(token) = std::env::var("CORTEX_API_KEY") { - if !token.is_empty() { + if has_token_value(&token) { tracing::debug!(source = "env_var", "Using auth token from CORTEX_API_KEY"); return Ok(token); } @@ -95,17 +99,17 @@ pub fn get_auth_token_optional(instance_token: Option<&str>) -> Option { /// Useful for fast availability checks in UI. pub fn is_authenticated(instance_token: Option<&str>) -> bool { // Check instance token - if instance_token.map_or(false, |t| !t.is_empty()) { + if instance_token.is_some_and(has_token_value) { return true; } // Check CORTEX_AUTH_TOKEN env var - if std::env::var("CORTEX_AUTH_TOKEN").map_or(false, |t| !t.is_empty()) { + if std::env::var("CORTEX_AUTH_TOKEN").is_ok_and(|t| has_token_value(&t)) { return true; } // Check CORTEX_API_KEY env var (alias) - if std::env::var("CORTEX_API_KEY").map_or(false, |t| !t.is_empty()) { + if std::env::var("CORTEX_API_KEY").is_ok_and(|t| has_token_value(&t)) { return true; } @@ -142,9 +146,18 @@ mod tests { fn test_is_authenticated_with_instance() { assert!(is_authenticated(Some("token"))); assert!(!is_authenticated(Some(""))); + assert!(!is_authenticated(Some(" "))); assert!(!is_authenticated(None)); } + #[test] + fn test_has_token_value_rejects_whitespace_only_tokens() { + assert!(has_token_value("token")); + assert!(!has_token_value("")); + assert!(!has_token_value(" ")); + assert!(!has_token_value("\n\t")); + } + #[test] fn test_auth_header_format() { let header = auth_header(Some("my-token"));