use crate::evidence::Confidence;
use crate::patterns::{Pattern, PatternCategory, PatternTier, Severity};
pub const PATTERNS: &[Pattern] = &[
Pattern {
id: "py.code_exec.eval",
description: "eval() runs dynamic code",
query: r#"(call function: (identifier) @id (#eq? @id "eval")) @vuln"#,
severity: Severity::High,
tier: PatternTier::A,
category: PatternCategory::CodeExec,
confidence: Confidence::High,
},
Pattern {
id: "py.code_exec.exec",
description: "exec() runs dynamic code",
query: r#"(call function: (identifier) @id (#eq? @id "exec")) @vuln"#,
severity: Severity::High,
tier: PatternTier::A,
category: PatternCategory::CodeExec,
confidence: Confidence::High,
},
Pattern {
id: "py.code_exec.compile",
description: "compile() with exec/eval mode compiles code from a string",
query: r#"(call function: (identifier) @id (#eq? @id "compile")) @vuln"#,
severity: Severity::Medium,
tier: PatternTier::A,
category: PatternCategory::CodeExec,
confidence: Confidence::High,
},
Pattern {
id: "py.cmdi.os_system",
description: "os.system() runs a shell command",
query: r#"(call
function: (attribute
object: (identifier) @pkg (#eq? @pkg "os")
attribute: (identifier) @fn (#eq? @fn "system")))
@vuln"#,
severity: Severity::High,
tier: PatternTier::A,
category: PatternCategory::CommandExec,
confidence: Confidence::High,
},
Pattern {
id: "py.cmdi.os_popen",
description: "os.popen() runs a shell command",
query: r#"(call
function: (attribute
object: (identifier) @pkg (#eq? @pkg "os")
attribute: (identifier) @fn (#eq? @fn "popen")))
@vuln"#,
severity: Severity::High,
tier: PatternTier::A,
category: PatternCategory::CommandExec,
confidence: Confidence::High,
},
Pattern {
id: "py.cmdi.subprocess_shell",
description: "subprocess call with shell=True",
query: r#"(call
function: (attribute
object: (identifier) @pkg (#eq? @pkg "subprocess"))
arguments: (argument_list
(keyword_argument
name: (identifier) @k (#eq? @k "shell")
value: (true))))
@vuln"#,
severity: Severity::High,
tier: PatternTier::B,
category: PatternCategory::CommandExec,
confidence: Confidence::Medium,
},
Pattern {
id: "py.deser.pickle_loads",
description: "pickle.loads/load deserializes arbitrary objects",
query: r#"(call
function: (attribute
object: (identifier) @pkg (#eq? @pkg "pickle")
attribute: (identifier) @fn (#match? @fn "^loads?$")))
@vuln"#,
severity: Severity::High,
tier: PatternTier::A,
category: PatternCategory::Deserialization,
confidence: Confidence::High,
},
Pattern {
id: "py.deser.yaml_load",
description: "yaml.load() without SafeLoader instantiates arbitrary objects",
query: r#"(call
function: (attribute
object: (identifier) @pkg (#eq? @pkg "yaml")
attribute: (identifier) @fn (#eq? @fn "load")))
@vuln"#,
severity: Severity::High,
tier: PatternTier::A,
category: PatternCategory::Deserialization,
confidence: Confidence::High,
},
Pattern {
id: "py.deser.shelve_open",
description: "shelve.open() performs pickle-backed deserialization",
query: r#"(call
function: (attribute
object: (identifier) @pkg (#eq? @pkg "shelve")
attribute: (identifier) @fn (#eq? @fn "open")))
@vuln"#,
severity: Severity::Medium,
tier: PatternTier::A,
category: PatternCategory::Deserialization,
confidence: Confidence::High,
},
Pattern {
id: "py.sqli.execute_format",
description: "cursor.execute with string concatenation risks SQL injection",
query: r#"(call
function: (attribute
attribute: (identifier) @fn (#eq? @fn "execute"))
arguments: (argument_list
(binary_operator) @arg))
@vuln"#,
severity: Severity::Medium,
tier: PatternTier::B,
category: PatternCategory::SqlInjection,
confidence: Confidence::Medium,
},
Pattern {
id: "py.crypto.md5",
description: "hashlib.md5() uses a weak hash algorithm",
query: r#"(call
function: (attribute
object: (identifier) @pkg (#eq? @pkg "hashlib")
attribute: (identifier) @fn (#eq? @fn "md5")))
@vuln"#,
severity: Severity::Low,
tier: PatternTier::A,
category: PatternCategory::Crypto,
confidence: Confidence::Medium,
},
Pattern {
id: "py.crypto.sha1",
description: "hashlib.sha1() uses a weak hash algorithm",
query: r#"(call
function: (attribute
object: (identifier) @pkg (#eq? @pkg "hashlib")
attribute: (identifier) @fn (#eq? @fn "sha1")))
@vuln"#,
severity: Severity::Low,
tier: PatternTier::A,
category: PatternCategory::Crypto,
confidence: Confidence::Medium,
},
Pattern {
id: "py.xss.jinja_from_string",
description: "jinja2.Template from string risks template injection",
query: r#"(call
function: (attribute
attribute: (identifier) @fn (#eq? @fn "from_string")))
@vuln"#,
severity: Severity::Medium,
tier: PatternTier::A,
category: PatternCategory::Xss,
confidence: Confidence::High,
},
];