mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-14 02:15:57 +00:00
fix(exec): stop privilege-escalation su deny matching non-ASCII text (#1389)
Go's regexp (RE2) treats \b as an ASCII-only word boundary, so the privilege_escalation deny pattern \bsu\b matched the ASCII "su" inside non-ASCII words such as the Vietnamese "suất" — the accented 'ấ' is not an ASCII word char, so \b sees a spurious word boundary right after "su". Any exec command containing such a word (for example a Vietnamese document embedded in a python heredoc to render a PDF) was wrongly blocked as a privilege-escalation attempt. Replace the pattern with a Unicode-aware boundary (\pL, \pN) that still matches the real su command.
This commit is contained in:
1 parent
e65f70e2ef
commit
8367a9bd0c
2 files changed
+25
-9
No files matched your search
@@ -4,6 +4,17 @@ import (
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// unicodeCmdWord matches a command name (or alternation) as a standalone
|
||||
// word using a Unicode-aware boundary. Go's RE2 \b is ASCII-only, so a
|
||||
// pattern like \bsu\b matches the "su" inside non-ASCII words such as the
|
||||
// Vietnamese "suất" (the accented 'ấ' is not an ASCII word char, so \b
|
||||
// sees a spurious boundary right after "su"). Treating Unicode letters and
|
||||
// digits (\pL, \pN) as word chars avoids those false positives while still
|
||||
// matching the real `su` command.
|
||||
func unicodeCmdWord(alt string) *regexp.Regexp {
|
||||
return regexp.MustCompile(`(?:^|[^\pL\pN_])(?:` + alt + `)(?:[^\pL\pN_]|$)`)
|
||||
}
|
||||
|
||||
// DenyGroup is a named set of shell command deny patterns.
|
||||
type DenyGroup struct {
|
||||
Name string // machine name: "package_install"
|
||||
@@ -83,7 +94,7 @@ var DenyGroupRegistry = map[string]*DenyGroup{
|
||||
Default: true,
|
||||
Patterns: []*regexp.Regexp{
|
||||
regexp.MustCompile(`\bsudo\b`),
|
||||
regexp.MustCompile(`\bsu\b`),
|
||||
unicodeCmdWord("su"),
|
||||
regexp.MustCompile(`\bdoas\b`),
|
||||
regexp.MustCompile(`\bpkexec\b`),
|
||||
regexp.MustCompile(`\brunuser\b`),
|
||||
|
||||
@@ -130,14 +130,19 @@ func TestPrivilegeEscalationGaps(t *testing.T) {
|
||||
)
|
||||
|
||||
mustAllow(t, patterns,
|
||||
"summit", // not "su"
|
||||
"sugar", // not "su"
|
||||
"surplus", // not "su"
|
||||
"issue", // not "su"
|
||||
"result", // not "su"
|
||||
"resume", // not "su"
|
||||
"visual", // not "su"
|
||||
"sushi", // not "su"
|
||||
"summit", // not "su"
|
||||
"sugar", // not "su"
|
||||
"surplus", // not "su"
|
||||
"issue", // not "su"
|
||||
"result", // not "su"
|
||||
"resume", // not "su"
|
||||
"visual", // not "su"
|
||||
"sushi", // not "su"
|
||||
// non-ASCII (Vietnamese) text: ASCII "su" adjacent to an accented
|
||||
// vowel must NOT match the su command (Go RE2 word boundaries are ASCII-only).
|
||||
"hiệu suất",
|
||||
"năng suất",
|
||||
"báo cáo hiệu suất tháng",
|
||||
"doaspkg", // not "doas" (no word boundary)
|
||||
"pkexecute", // not "pkexec" (no word boundary)
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user