forked from mirrors/kingfisher
JWT tokens without both 'iss' and 'aud' are no longer reported as active credentials
This commit is contained in:
parent
b3ddc119a4
commit
0bdd68c900
5 changed files with 32 additions and 16 deletions
|
|
@ -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<GitHubRepoType> 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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<SimpleProject> = projects_ep.query(&client)?;
|
||||
|
||||
for proj in projects {
|
||||
|
|
|
|||
|
|
@ -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}.")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -112,4 +112,4 @@ async fn test_redact_hashes_finding_values() -> Result<()> {
|
|||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue