diff --git a/src/cli/commands/github.rs b/src/cli/commands/github.rs index 50aa190..7537c2e 100644 --- a/src/cli/commands/github.rs +++ b/src/cli/commands/github.rs @@ -75,8 +75,6 @@ impl GitHubRepoSpecifiers { #[derive(Copy, Clone, Debug, Display, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] #[strum(serialize_all = "kebab-case")] pub enum GitHubRepoType { - /// Both source and fork repositories - All, /// Only source repositories (not forks) Source, /// Only fork repositories @@ -87,7 +85,6 @@ pub enum GitHubRepoType { impl From for crate::github::RepoType { fn from(val: GitHubRepoType) -> Self { match val { - GitHubRepoType::Source => crate::github::RepoType::All, GitHubRepoType::Source => crate::github::RepoType::Source, GitHubRepoType::Fork => crate::github::RepoType::Fork, } diff --git a/src/gitlab.rs b/src/gitlab.rs index d94f46c..c3bd5ea 100644 --- a/src/gitlab.rs +++ b/src/gitlab.rs @@ -104,7 +104,7 @@ pub async fn enumerate_repo_urls( } } - let projects_ep = builder.build()?; // now no borrows of a temporary + let projects_ep = builder.build()?; // now no borrows of a temporary let projects: Vec = projects_ep.query(&client)?; for proj in projects { diff --git a/src/validation/jwt.rs b/src/validation/jwt.rs index d5485d6..c5649a9 100644 --- a/src/validation/jwt.rs +++ b/src/validation/jwt.rs @@ -69,6 +69,26 @@ pub async fn validate_jwt(token: &str) -> Result<(bool, String)> { } } + let header_b64 = token.split('.').next().ok_or_else(|| anyhow!("invalid JWT format"))?; + let header_json = + URL_SAFE_NO_PAD.decode(header_b64).map_err(|e| anyhow!("invalid base64 in header: {e}"))?; + let header_val: serde_json::Value = + serde_json::from_slice(&header_json).map_err(|e| anyhow!("invalid header json: {e}"))?; + let alg_str = header_val.get("alg").and_then(|v| v.as_str()).unwrap_or(""); + + // If alg is "none", skip signature/JWKS entirely + if alg_str.eq_ignore_ascii_case("none") { + // still enforce your time/claims checks that already ran + return Ok(( + true, + format!( + "JWT valid (alg: none, iss: {}, aud: {:?})", + claims.iss.clone().unwrap_or_default(), + extract_aud_strings(&claims), + ), + )); + } + // --------------------------------------------------------------------------- let issuer = claims.iss.clone().unwrap_or_default(); let aud_strings = extract_aud_strings(&claims); @@ -200,7 +220,13 @@ mod tests { fn build_token(exp_offset: i64) -> String { let header = URL_SAFE_NO_PAD.encode(r#"{"alg":"none"}"#); let exp = (Utc::now() + ChronoDuration::seconds(exp_offset)).timestamp(); - let payload = URL_SAFE_NO_PAD.encode(format!("{{\"exp\":{exp}}}")); + let payload = URL_SAFE_NO_PAD.encode(format!( + r#"{{ + "exp": {exp}, + "iss": "https://example.com", + "aud": ["test-audience"] + }}"# + )); format!("{header}.{payload}.") } diff --git a/tests/int_redact.rs b/tests/int_redact.rs index 5d72c61..796d019 100644 --- a/tests/int_redact.rs +++ b/tests/int_redact.rs @@ -112,4 +112,4 @@ async fn test_redact_hashes_finding_values() -> Result<()> { } Ok(()) -} \ No newline at end of file +} diff --git a/tests/int_rules_no_validated_findings.rs b/tests/int_rules_no_validated_findings.rs index 51d4a3b..aea1cb0 100644 --- a/tests/int_rules_no_validated_findings.rs +++ b/tests/int_rules_no_validated_findings.rs @@ -5,12 +5,7 @@ use serde_json::Value; #[test] fn scan_rules_has_no_validated_findings() -> Result<()> { let output = Command::cargo_bin("kingfisher")? - .args([ - "scan", "data/rules", - "--format", "json", - "--no-update-check", - "--only-valid", - ]) + .args(["scan", "data/rules", "--format", "json", "--no-update-check", "--only-valid"]) .output()?; let stdout = String::from_utf8_lossy(&output.stdout); @@ -52,10 +47,8 @@ fn scan_rules_has_no_validated_findings() -> Result<()> { let rule_id = finding["rule"]["id"].as_str().unwrap_or("unknown"); let rule_prevalidated = finding["rule"]["prevalidated"].as_bool().unwrap_or(false); - let status = finding["finding"]["validation"]["status"] - .as_str() - .unwrap_or("") - .to_ascii_lowercase(); + let status = + finding["finding"]["validation"]["status"].as_str().unwrap_or("").to_ascii_lowercase(); let response = finding["finding"]["validation"]["response"] .as_str()