Skip to content

Commit 72ed670

Browse files
committed
fix(terminal): improve shell syntax safety check for dangerous commands
- Enhance rm command checking to detect various dangerous combinations - Improve sudo command checking to identify risky rm usage - Add more precise root directory operation checks - Considerations for future enhancements in command checking
1 parent 73640d7 commit 72ed670

File tree

2 files changed

+31
-14
lines changed

2 files changed

+31
-14
lines changed

exts/ext-terminal/src/main/kotlin/cc/unitmesh/terminal/sketch/ShellSyntaxSafetyCheck.kt

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,6 @@ object ShellSyntaxSafetyCheck {
4040

4141
return Pair(false, "")
4242
}
43-
44-
// Public API to register custom checkers
45-
fun registerChecker(checker: ShellCommandChecker) {
46-
checkerRegistry.register(checker)
47-
}
4843
}
4944

5045
class ShellCommandCheckerRegistry {
@@ -91,9 +86,10 @@ class RmCommandChecker : BaseShellCommandChecker() {
9186
if (!ShellCommandUtils.isCommandWithName(command, "rm")) return checkNext(command, fullCommandText)
9287

9388
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"))
9793
) {
9894
return Pair(true, "Dangerous rm command detected")
9995
}
@@ -110,6 +106,11 @@ class SudoCommandChecker : BaseShellCommandChecker() {
110106
if (sudoArgs.contains("rm")) {
111107
return Pair(true, "Removing files with elevated privileges")
112108
}
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+
// }
113114

114115
return checkNext(command, fullCommandText)
115116
}
@@ -123,15 +124,26 @@ class GenericCommandChecker(private val commandName: String, private val dangerM
123124
}
124125
return checkNext(command, fullCommandText)
125126
}
127+
// Consider adding checks based on arguments for specific generic commands if needed
126128
}
127129

128130
class ChmodCommandChecker : BaseShellCommandChecker() {
129131
override fun check(command: ShCommand, fullCommandText: String): Pair<Boolean, String>? {
130132
if (!ShellCommandUtils.isCommandWithName(command, "chmod")) return checkNext(command, fullCommandText)
131133

134+
val commandText = command.text
132135
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")
134144
}
145+
// You can add more checks here for other insecure permission patterns,
146+
// like removing write permissions from group or others unexpectedly.
135147

136148
return checkNext(command, fullCommandText)
137149
}
@@ -142,6 +154,12 @@ class RootDirectoryOperationChecker : BaseShellCommandChecker() {
142154
if (ShellCommandUtils.operatesOnRootDirectory(command)) {
143155
return Pair(true, "Operation targeting root directory")
144156
}
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+
}
145163
return checkNext(command, fullCommandText)
146164
}
147165
}
@@ -167,8 +185,7 @@ object ShellCommandUtils {
167185
}
168186

169187
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
172189
}
173190

174191
fun hasRecursiveFlag(cmd: ShCommand): Boolean {
@@ -180,7 +197,7 @@ object ShellCommandUtils {
180197
}
181198

182199
fun operatesOnRootDirectory(cmd: ShCommand): Boolean {
183-
val tokens = cmd.text.trim().split("\\s+".toRegex())
200+
val tokens = getCommandArgs(cmd)
184201
return tokens.any { it == "/" }
185202
}
186-
}
203+
}

exts/ext-terminal/src/test/kotlin/cc/unitmesh/terminal/sketch/ShellSyntaxSafetyCheckTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class ShellSyntaxSafetyCheckTest : BasePlatformTestCase() {
2323
"sudo rm file.txt" to "Removing files with elevated privileges",
2424
"mkfs /dev/sda1" to "Filesystem formatting command",
2525
"dd if=/dev/zero of=/dev/sda" to "Low-level disk operation",
26-
"chmod -R 777 /var" to "Recursive chmod with insecure permissions",
26+
"chmod -R 777 /var" to "Recursive chmod with insecure permissions (e.g., 777)",
2727
"rm /" to "Operation targeting root directory"
2828
)
2929

0 commit comments

Comments
 (0)