Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 24 additions & 45 deletions crates/goose/src/security/patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,16 @@ impl RiskLevel {

/// Comprehensive list of dangerous command patterns
pub const THREAT_PATTERNS: &[ThreatPattern] = &[
// Critical filesystem destruction patterns
ThreatPattern {
name: "rm_rf_root",
pattern: r"rm\s+(-[rf]*[rf][rf]*|--recursive|--force).*[/\\]",
description: "Recursive file deletion with rm -rf",
risk_level: RiskLevel::High,
name: "rm_rf_root_bare",
pattern: r"rm\s+(-[rRfF]+\s+)*(-[rRfF]+|--recursive|--force|--no-preserve-root)(\s+(-[rRfF]+|--recursive|--force|--no-preserve-root))*\s+['\x22]?/['\x22]?(\s|$)",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Detect root wildcard deletes in rm rule

The new rm_rf_root_bare regex only matches a bare / argument, so destructive variants like rm -rf /* (a common way to avoid GNU rm's root safeguard) no longer match any filesystem-destruction pattern. In pattern-based fallback when command ML is unavailable, this can drop confidence to 0 and let a full-root wipe command pass unflagged.

Useful? React with 👍 / 👎.

description: "Recursive deletion of root filesystem",
risk_level: RiskLevel::Critical,
category: ThreatCategory::FileSystemDestruction,
},
ThreatPattern {
name: "rm_rf_system",
pattern: r"rm\s+(-[rf]*[rf][rf]*|--recursive|--force).*(bin|etc|usr|var|sys|proc|dev|boot|lib|opt|srv|tmp)",
pattern: r"rm\s+(-[rf]*[rf][rf]*|--recursive|--force).*/(bin|etc|usr|var|sys|proc|dev|boot|lib|opt|srv)\b",
Comment thread
dorien-koelemeijer marked this conversation as resolved.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Match relative system directory deletes

Requiring /(bin|etc|usr|...) in rm_rf_system misses destructive relative paths like cd / && rm -rf etc or cd / && rm -rf var, which are valid commands that delete system directories from root. Before this change these commands matched the critical system-delete rule; now they can evade pattern-based detection entirely in fallback mode.

Useful? React with 👍 / 👎.

description: "Recursive deletion of system directories",
risk_level: RiskLevel::Critical,
category: ThreatCategory::FileSystemDestruction,
Expand Down Expand Up @@ -114,8 +113,8 @@ pub const THREAT_PATTERNS: &[ThreatPattern] = &[
},
ThreatPattern {
name: "password_file_access",
pattern: r"(cat|grep|awk|sed).*(/etc/passwd|/etc/shadow|\.password|\.env)",
description: "Password file access",
pattern: r"(cat|grep|awk|sed).*(/etc/shadow|\.password)",
description: "Password/shadow file access",
risk_level: RiskLevel::High,
category: ThreatCategory::DataExfiltration,
},
Expand Down Expand Up @@ -143,7 +142,7 @@ pub const THREAT_PATTERNS: &[ThreatPattern] = &[
},
ThreatPattern {
name: "hosts_file_modification",
pattern: r"echo.*>.*(/etc/hosts|hosts\.txt)",
pattern: r"echo.*>(>?)\s*(/etc/hosts|hosts\.txt)|echo.*\|\s*(sudo\s+)?tee\s+(-a\s+)?/etc/hosts",
description: "Hosts file modification",
risk_level: RiskLevel::Medium,
category: ThreatCategory::SystemModification,
Expand Down Expand Up @@ -200,21 +199,15 @@ pub const THREAT_PATTERNS: &[ThreatPattern] = &[
risk_level: RiskLevel::High,
category: ThreatCategory::PrivilegeEscalation,
},
// Command injection patterns
ThreatPattern {
name: "command_substitution",
pattern: r"\$\([^)]*[;&|><][^)]*\)|`[^`]*[;&|><][^`]*`",
description: "Command substitution with shell operators",
risk_level: RiskLevel::High,
category: ThreatCategory::CommandInjection,
},
ThreatPattern {
name: "shell_metacharacters",
pattern: r"[;&|`$(){}[\]\\]",
description: "Shell metacharacters in input",
risk_level: RiskLevel::Low,
category: ThreatCategory::CommandInjection,
},
// NOTE: command_substitution and shell_metacharacters patterns removed.
// They caused excessive false positives on legitimate shell scripts:
// VAR=$(grep ... | head -1) — variable assignment
// echo "$(date)" && ls — command substitution
// RESULT=$(echo "1+1" | bc) — arithmetic
// $(wc -c < file) — file size checks
// The ML classifier handles these patterns with much higher accuracy.
// When the classifier is unavailable, these patterns generated ~75% of
// all false positives at exactly 0.675 confidence.
ThreatPattern {
name: "encoded_commands",
pattern: r"(base64|hex|url).*decode.*\|\s*(bash|sh)",
Expand All @@ -237,20 +230,10 @@ pub const THREAT_PATTERNS: &[ThreatPattern] = &[
risk_level: RiskLevel::High,
category: ThreatCategory::CommandInjection,
},
ThreatPattern {
name: "string_concatenation_obfuscation",
pattern: r"(\$\{[^}]*\}|\$[A-Za-z_][A-Za-z0-9_]*){3,}",
description: "String concatenation obfuscation",
risk_level: RiskLevel::Medium,
category: ThreatCategory::CommandInjection,
},
ThreatPattern {
name: "character_escaping",
pattern: r"\\[x][0-9a-fA-F]{2}|\\[0-7]{3}|\\[nrtbfav\\]",
description: "Character escaping for obfuscation",
risk_level: RiskLevel::Low,
category: ThreatCategory::CommandInjection,
},
// NOTE: string_concatenation_obfuscation removed — matched JS template
// literals like ${Utils.escapeHtml(doc.url)} in heredocs and code files.
// NOTE: character_escaping removed — \\n, \\t, etc. are standard in shell
// scripts and code. Too noisy for practical use.
ThreatPattern {
name: "eval_with_variables",
pattern: r"eval\s+\$[A-Za-z_][A-Za-z0-9_]*|\beval\s+.*\$\{",
Expand All @@ -265,13 +248,9 @@ pub const THREAT_PATTERNS: &[ThreatPattern] = &[
risk_level: RiskLevel::Medium,
category: ThreatCategory::CommandInjection,
},
ThreatPattern {
name: "environment_variable_abuse",
pattern: r"(export|env)\s+[A-Z_]+=.*[;&|]|PATH=.*[;&|]",
description: "Environment variable manipulation",
risk_level: RiskLevel::Medium,
category: ThreatCategory::SystemModification,
},
// NOTE: environment_variable_abuse removed — `export PATH=...; command`
// and `export VAR=value && tool` are standard shell patterns used
// constantly by goose for tool setup (slack-cli, gdrive-cli, hermit, etc.).
ThreatPattern {
name: "unicode_obfuscation",
pattern: r"\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}",
Expand Down
Loading