feat: complete 7/7 bash security checks
Added: - Standalone semicolon check: blocks ; outside quotes (use && instead) - Sensitive redirection check: blocks > to /etc/passwd, .bashrc, .ssh/authorized_keys, .env, etc. Now all 7 security checks are active: 1. Incomplete commands, 2. Control characters, 3. Newline injection, 4. Command substitution, 5. Dangerous variables, 6. Semicolons, 7. Sensitive redirections
This commit is contained in:
@@ -55,9 +55,12 @@ func ValidateCommand(cmd string) *SecurityViolation {
|
||||
if v := checkDangerousVars(cmd); v != nil {
|
||||
return v
|
||||
}
|
||||
// Metacharacters and redirection are warnings, not blocks in M1.
|
||||
// The LLM legitimately uses pipes and redirects.
|
||||
// Full compound command parsing (mvdan.cc/sh) comes in M5.
|
||||
if v := checkStandaloneSemicolon(cmd); v != nil {
|
||||
return v
|
||||
}
|
||||
if v := checkSensitiveRedirection(cmd); v != nil {
|
||||
return v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -181,6 +184,60 @@ func checkCmdSubstitution(cmd string) *SecurityViolation {
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkStandaloneSemicolon blocks standalone semicolons used to chain commands.
|
||||
// Pipes (|) and && / || are allowed (handled by compound command parsing).
|
||||
func checkStandaloneSemicolon(cmd string) *SecurityViolation {
|
||||
inSingle := false
|
||||
inDouble := false
|
||||
escaped := false
|
||||
|
||||
for _, r := range cmd {
|
||||
if escaped {
|
||||
escaped = false
|
||||
continue
|
||||
}
|
||||
if r == '\\' && !inSingle {
|
||||
escaped = true
|
||||
continue
|
||||
}
|
||||
if r == '\'' && !inDouble {
|
||||
inSingle = !inSingle
|
||||
continue
|
||||
}
|
||||
if r == '"' && !inSingle {
|
||||
inDouble = !inDouble
|
||||
continue
|
||||
}
|
||||
if !inSingle && !inDouble && r == ';' {
|
||||
return &SecurityViolation{
|
||||
Check: CheckMetacharacters,
|
||||
Message: "standalone semicolon (use && for chaining)",
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkSensitiveRedirection blocks output redirection to sensitive paths.
|
||||
func checkSensitiveRedirection(cmd string) *SecurityViolation {
|
||||
sensitiveTargets := []string{
|
||||
"/etc/passwd", "/etc/shadow", "/etc/sudoers",
|
||||
".bashrc", ".zshrc", ".profile", ".bash_profile",
|
||||
".ssh/authorized_keys", ".ssh/config",
|
||||
".env",
|
||||
}
|
||||
|
||||
for _, target := range sensitiveTargets {
|
||||
if strings.Contains(cmd, "> "+target) || strings.Contains(cmd, ">>"+target) {
|
||||
return &SecurityViolation{
|
||||
Check: CheckRedirection,
|
||||
Message: fmt.Sprintf("redirection to sensitive path: %s", target),
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkDangerousVars blocks attempts to manipulate IFS or PATH.
|
||||
func checkDangerousVars(cmd string) *SecurityViolation {
|
||||
upper := strings.ToUpper(cmd)
|
||||
|
||||
Reference in New Issue
Block a user