@@ -40,11 +40,6 @@ object ShellSyntaxSafetyCheck {
40
40
41
41
return Pair (false , " " )
42
42
}
43
-
44
- // Public API to register custom checkers
45
- fun registerChecker (checker : ShellCommandChecker ) {
46
- checkerRegistry.register(checker)
47
- }
48
43
}
49
44
50
45
class ShellCommandCheckerRegistry {
@@ -91,9 +86,10 @@ class RmCommandChecker : BaseShellCommandChecker() {
91
86
if (! ShellCommandUtils .isCommandWithName(command, " rm" )) return checkNext(command, fullCommandText)
92
87
93
88
val options = ShellCommandUtils .getCommandOptions(command)
94
- if (options.contains(" -rf" ) || options.contains(" -fr" ) ||
95
- options.contains(" -r" ) && options.contains(" -f" ) ||
96
- options.contains(" -f" ) && ! options.contains(" -i" )
89
+ if (options.containsAll(listOf (" -r" , " -f" )) ||
90
+ options.containsAll(listOf (" -rf" )) ||
91
+ options.containsAll(listOf (" -fr" )) ||
92
+ (options.contains(" -f" ) && ! options.contains(" -i" ))
97
93
) {
98
94
return Pair (true , " Dangerous rm command detected" )
99
95
}
@@ -110,6 +106,11 @@ class SudoCommandChecker : BaseShellCommandChecker() {
110
106
if (sudoArgs.contains(" rm" )) {
111
107
return Pair (true , " Removing files with elevated privileges" )
112
108
}
109
+ // Consider more advanced parsing of the command after sudo if needed
110
+ // Example: if (sudoArgs.isNotEmpty()) {
111
+ // val commandAfterSudo = sudoArgs.joinToString(" ")
112
+ // // Potentially recursively call checkDangerousCommand on commandAfterSudo
113
+ // }
113
114
114
115
return checkNext(command, fullCommandText)
115
116
}
@@ -123,15 +124,26 @@ class GenericCommandChecker(private val commandName: String, private val dangerM
123
124
}
124
125
return checkNext(command, fullCommandText)
125
126
}
127
+ // Consider adding checks based on arguments for specific generic commands if needed
126
128
}
127
129
128
130
class ChmodCommandChecker : BaseShellCommandChecker () {
129
131
override fun check (command : ShCommand , fullCommandText : String ): Pair <Boolean , String >? {
130
132
if (! ShellCommandUtils .isCommandWithName(command, " chmod" )) return checkNext(command, fullCommandText)
131
133
134
+ val commandText = command.text
132
135
if (ShellCommandUtils .hasRecursiveFlag(command) && ShellCommandUtils .hasInsecurePermissions(command)) {
133
- return Pair (true , " Recursive chmod with insecure permissions" )
136
+ return Pair (true , " Recursive chmod with insecure permissions (e.g., 777)" )
137
+ }
138
+
139
+ // Example of checking for other potentially dangerous permission changes:
140
+ // Giving execute permission to 'others' without a clear reason might be risky.
141
+ // This is a simplified check and might need refinement based on your security policy.
142
+ if (commandText.contains(" o+x" ) && ! commandText.contains(" a+x" )) {
143
+ return Pair (true , " Granting execute permission to others (o+x) might be dangerous" )
134
144
}
145
+ // You can add more checks here for other insecure permission patterns,
146
+ // like removing write permissions from group or others unexpectedly.
135
147
136
148
return checkNext(command, fullCommandText)
137
149
}
@@ -142,6 +154,12 @@ class RootDirectoryOperationChecker : BaseShellCommandChecker() {
142
154
if (ShellCommandUtils .operatesOnRootDirectory(command)) {
143
155
return Pair (true , " Operation targeting root directory" )
144
156
}
157
+ // Consider more precise checks for operations directly on the root directory
158
+ // For example, commands like `rm -rf /` or `mv /some/file /`
159
+ val tokens = ShellCommandUtils .getCommandArgs(command)
160
+ if (tokens.size > 1 && tokens.drop(1 ).any { it == " /" }) {
161
+ return Pair (true , " Operation targeting root directory" )
162
+ }
145
163
return checkNext(command, fullCommandText)
146
164
}
147
165
}
@@ -167,8 +185,7 @@ object ShellCommandUtils {
167
185
}
168
186
169
187
fun isCommandWithName (cmd : ShCommand , name : String ): Boolean {
170
- val tokens = cmd.text.trim().split(" \\ s+" .toRegex())
171
- return tokens.firstOrNull() == name
188
+ return getCommandArgs(cmd).firstOrNull()?.equals(name) ? : false
172
189
}
173
190
174
191
fun hasRecursiveFlag (cmd : ShCommand ): Boolean {
@@ -180,7 +197,7 @@ object ShellCommandUtils {
180
197
}
181
198
182
199
fun operatesOnRootDirectory (cmd : ShCommand ): Boolean {
183
- val tokens = cmd.text.trim().split( " \\ s+ " .toRegex() )
200
+ val tokens = getCommandArgs(cmd )
184
201
return tokens.any { it == " /" }
185
202
}
186
- }
203
+ }
0 commit comments