fix(audit): fix deserde for transitive npm audit actions (#31671)

Fixes https://github.com/denoland/deno/issues/31613
This commit is contained in:
Divy 2025-12-19 13:52:26 +05:30 committed by GitHub
parent dd47e25a30
commit d9a8d18a0b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 124 additions and 23 deletions

View file

@ -450,8 +450,8 @@ mod npm {
#[derive(Debug, Deserialize)]
pub struct AuditActionResolve {
pub id: i32,
pub path: Option<String>,
// TODO(bartlomieju): currently not used, commented out so it's not flagged by clippy
// pub path: String,
// pub dev: bool,
// pub optional: bool,
// pub bundled: bool,
@ -463,7 +463,7 @@ mod npm {
pub is_major: bool,
pub action: String,
pub resolves: Vec<AuditActionResolve>,
pub module: String,
pub module: Option<String>,
pub target: Option<String>,
}
@ -491,30 +491,41 @@ mod npm {
impl AuditAdvisory {
fn find_actions(&self, actions: &[AuditAction]) -> Vec<String> {
let mut acts = vec![];
let mut acts = Vec::new();
for action in actions {
if action
.resolves
.iter()
.any(|action_resolve| action_resolve.id == self.id)
{
acts.push(format!(
"{} {}{}{}",
action.action,
action.module,
if let Some(target) = &action.target {
format!("@{}", target)
} else {
"".to_string()
},
if action.is_major {
if !action.resolves.iter().any(|r| r.id == self.id) {
continue;
}
let module = action
.module
.as_deref()
.map(str::to_owned)
.or_else(|| {
// Fallback to infer from dependency path
action.resolves.first().and_then(|r| {
r.path
.as_deref()
.and_then(|p| p.split('>').next_back())
.map(|s| s.trim().to_string())
})
})
.unwrap_or_else(|| "<unknown>".to_string());
let target = action
.target
.as_deref()
.map(|t| format!("@{}", t))
.unwrap_or_default();
let major = if action.is_major {
" (major upgrade)"
} else {
""
}
))
}
};
acts.push(format!("{} {}{}{}", action.action, module, target, major));
}
acts

View file

@ -0,0 +1,3 @@
export function sayHello() {
return '@denotest/with-vuln3 says hello!';
}

View file

@ -0,0 +1,5 @@
{
"name": "@denotest/with-vuln3",
"version": "1.0.0",
"type": "module"
}

View file

@ -0,0 +1,3 @@
export function sayHello() {
return '@denotest/with-vuln3 says hello!';
}

View file

@ -0,0 +1,5 @@
{
"name": "@denotest/with-vuln3",
"version": "1.1.0",
"type": "module"
}

View file

@ -0,0 +1,14 @@
{
"tempDir": true,
"steps": [
{
"args": "install",
"output": "install.out"
},
{
"args": "audit",
"output": "audit.out",
"exitCode": 1
}
]
}

View file

@ -0,0 +1,11 @@
╭ @denotest/with-vuln3 has security vulnerability
│ Severity: high
│ Package: @edenotest/with-vuln3
│ Vulnerable: <1.1.0
│ Patched: >=1.1.0
│ Path: @denotest/with-vuln3
│ Info: https://example.com/vuln/303030
╰ Actions: install @denotest/with-vuln3@1.1.0
Found 1 vulnerabilities
Severity: 0 low, 0 moderate, 1 high, 0 critical

View file

@ -0,0 +1,5 @@
{
"imports": {
"@denotest/with-vuln3": "npm:@denotest/with-vuln3@1.0.0"
}
}

View file

@ -0,0 +1,6 @@
Download http://localhost:4260/@denotest%2fwith-vuln3
Download http://localhost:4260/@denotest/with-vuln3/1.0.0.tgz
Dependencies:
+ npm:@denotest/with-vuln3 1.0.0

View file

@ -474,6 +474,11 @@ fn process_npm_security_audits_body(
advisories.insert(202020, get_advisory_for_with_vuln2());
vuln_critical += 1;
}
if requires_map_keys.contains(&"@denotest/with-vuln3".to_string()) {
actions.push(get_action_for_with_vuln3());
advisories.insert(303030, get_advisory_for_with_vuln3());
vuln_high += 1;
}
Some(json!({
"actions": actions,
@ -573,3 +578,36 @@ fn get_advisory_for_with_vuln2() -> serde_json::Value {
"url": "https://example.com/vuln/202020"
})
}
fn get_action_for_with_vuln3() -> serde_json::Value {
json!({
"isMajor": false,
"action": "install",
"resolves": [{
"id": 303030,
"path": "@denotest/with-vuln3",
"dev": false,
"optional": false,
"bundled": false,
}],
// Note: "module" field is intentionally omitted to test fallback logic
"target": "1.1.0"
})
}
fn get_advisory_for_with_vuln3() -> serde_json::Value {
json!({
"findings": [
{"version": "1.0.0", "paths": ["@denotest/with-vuln3"]}
],
"id": 303030,
"overview": "Lorem ipsum dolor sit amet",
"title": "@denotest/with-vuln3 has security vulnerability",
"severity": "high",
"module_name": "@edenotest/with-vuln3",
"vulnerable_versions": "<1.1.0",
"recommendations": "Upgrade to version 1.1.0 or later",
"patched_versions": ">=1.1.0",
"url": "https://example.com/vuln/303030"
})
}