GHSA-5wp8-q9mx-8jx8 is a critical-severity (CVSS 10) remote code execution vulnerability in zeptoclaw. O3 Security confirms whether GHSA-5wp8-q9mx-8jx8 is actually reachable in your code before you act, and blocks exploitation at runtime until you patch.
zeptoclaw has Shell allowlist-blocklist bypass via command/argument injection and file name wildcards
Real-World Exposure
zeptoclawReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects crates.io packages — download data is not available via public APIs for these ecosystems.
Description
Summary
zeptoclaw implements a allowlist combined with a blocklist to prevent malicious shell commands in src/security/shell.rs. However, even in the Strict mode, attackers can completely bypass all the guards from allowlist and blocklist:
- to bypass the
allowlist, command injection is enough, such as;,$()etc. - to bypass the
REGEX_BLOCKED_PATTERNS, argument injection is enough, such as thepython3 -P -c "..." - to bypass the
LITERAL_BLOCKED_PATTERNS, file name wildcards can do the work, such ascat /etc/pass[w]d
Details
In code src/security/shell.rs#L218-L243, one can see the allowlist only checks the first token and thus makes command injection possible.
// Allowlist check (runs after blocklist)
if self.allowlist_mode != ShellAllowlistMode::Off && !self.allowlist.is_empty() {
let first_token = command
.split_whitespace()
.next()
.unwrap_or("")
.to_lowercase();
// Strip path prefix (e.g. /usr/bin/git -> git)
let executable = first_token.rsplit('/').next().unwrap_or(&first_token);
if !self.allowlist.iter().any(|a| a == executable) {
match self.allowlist_mode {
ShellAllowlistMode::Strict => {
return Err(ZeptoError::SecurityViolation(format!(
"Command '{}' not in allowlist",
executable
)));
}
ShellAllowlistMode::Warn => {
tracing::warn!(
command = %command,
executable = %executable,
"Command not in allowlist"
);
}
ShellAllowlistMode::Off => {} // unreachable
}
!self.allowlist.is_empty() makes the empty allowlist overlook the allowlist check, if it is in ShellAllowlistMode::Strict mode, empty allowlist should direct reject all the commands.
As the code in src/security/shell.rs#L18-L70, we can find the REGEX_BLOCKED_PATTERNS only apply \s+ in between the command and arguments, making argument injection possible, and the LITERAL_BLOCKED_PATTERNS just uses specific file name, totally overlooking the file name wildcards:
const REGEX_BLOCKED_PATTERNS: &[&str] = &[
// Piped shell execution (curl/wget to sh/bash)
r"curl\s+.*\|\s*(sh|bash|zsh)",
r"wget\s+.*\|\s*(sh|bash|zsh)",
r"\|\s*(sh|bash|zsh)\s*$",
// Reverse shells
r"bash\s+-i\s+>&\s*/dev/tcp",
r"nc\s+.*-e\s+(sh|bash|/bin)",
r"/dev/tcp/",
r"/dev/udp/",
// Destructive root operations (various flag orderings)
r"rm\s+(-[rf]{1,2}\s+)*(-[rf]{1,2}\s+)*/\s*($|;|\||&)",
r"rm\s+(-[rf]{1,2}\s+)*(-[rf]{1,2}\s+)*/\*\s*($|;|\||&)",
// Format/overwrite disk
r"mkfs(\.[a-z0-9]+)?\s",
r"dd\s+.*if=/dev/(zero|random|urandom).*of=/dev/[sh]d",
r">\s*/dev/[sh]d[a-z]",
// System-wide permission changes
r"chmod\s+(-R\s+)?777\s+/\s*$",
r"chmod\s+(-R\s+)?777\s+/[a-z]",
// Fork bombs
r":\(\)\s*\{\s*:\|:&\s*\}\s*;:",
r"fork\s*\(\s*\)",
// Encoded/indirect execution (common blocklist bypasses)
r"base64\s+(-d|--decode)",
r"python[23]?\s+-c\s+",
r"perl\s+-e\s+",
r"ruby\s+-e\s+",
r"node\s+-e\s+",
r"\beval\s+",
r"xargs\s+.*sh\b",
r"xargs\s+.*bash\b",
// Environment variable exfiltration
r"\benv\b.*>\s*/",
r"\bprintenv\b.*>\s*/",
];
/// Literal substring patterns (credentials, sensitive paths)
const LITERAL_BLOCKED_PATTERNS: &[&str] = &[
"/etc/shadow",
"/etc/passwd",
"~/.ssh/",
".ssh/id_rsa",
".ssh/id_ed25519",
".ssh/id_ecdsa",
".ssh/id_dsa",
".ssh/authorized_keys",
".aws/credentials",
".kube/config",
// ZeptoClaw's own config (contains API keys and channel tokens)
".zeptoclaw/config.json",
".zeptoclaw/config.yaml",
];
PoC
#[test]
fn test_allowlist_bypass() {
let config =
ShellSecurityConfig::new().with_allowlist(vec!["git"], ShellAllowlistMode::Strict);
assert!(config.validate_command("/usr/bin/git status; python -P -c 'import os; os.system(\"rm -rf /\")'; cat /etc/pass[w]d").is_ok());
}
Impact
Unauthorized command execution.
Credit
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🦀crates.io | zeptoclaw | all versions | 0.6.2 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for zeptoclaw. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.
Fix
Update zeptoclaw to 0.6.2 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-5wp8-q9mx-8jx8 is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 pinpoints whether GHSA-5wp8-q9mx-8jx8 is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.
Tailored to GHSA-5wp8-q9mx-8jx8. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Frequently Asked Questions
Is GHSA-5wp8-q9mx-8jx8 in your dependencies?
O3 detects GHSA-5wp8-q9mx-8jx8 across crates.io dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.