Sanitize user input to prevent shell escape

This commit is contained in:
2026-03-12 13:33:51 +05:00
parent 9f09ac1ad0
commit 0d5a73251c
3 changed files with 52 additions and 14 deletions

View File

@@ -76,9 +76,10 @@ fun CreateImgDialog(
val fullFileName = if (fileName.isNotBlank()) "$fileName.img" else ""
val fileExists = fullFileName.isNotEmpty() && existingFiles.contains(fullFileName)
val hasInvalidChars = fileName.any { !it.isLetterOrDigit() && it !in "-_. ()[]+," }
val isValidInput = fileName.isNotBlank() &&
!fileName.contains("/") &&
!hasInvalidChars &&
sizeValue.toLongOrNull()?.let { it > 0 } == true &&
!fileExists
@@ -135,11 +136,11 @@ fun CreateImgDialog(
// File name input
OutlinedTextField(
value = fileName,
onValueChange = { fileName = it.replace("/", "") },
onValueChange = { fileName = it },
label = { Text("File Name") },
suffix = { Text(".img") },
singleLine = true,
isError = fileExists,
isError = fileExists || hasInvalidChars,
modifier = Modifier.fillMaxWidth()
)
@@ -153,6 +154,16 @@ fun CreateImgDialog(
)
}
// Show error if invalid characters
if (hasInvalidChars) {
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "Invalid file name",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.error
)
}
Spacer(modifier = Modifier.height(16.dp))
// Size input

View File

@@ -170,7 +170,8 @@ private fun RenameDialog(
val nameWithoutExtension = currentName.removeSuffix(extension)
var newName by remember { mutableStateOf(nameWithoutExtension) }
val isValid = newName.isNotBlank() && !newName.contains("/")
val hasInvalidChars = newName.any { !it.isLetterOrDigit() && it !in "-_. ()[]+," }
val isValid = newName.isNotBlank() && !hasInvalidChars
AlertDialog(
onDismissRequest = onDismiss,
@@ -179,12 +180,22 @@ private fun RenameDialog(
Column {
OutlinedTextField(
value = newName,
onValueChange = { newName = it.replace("/", "") },
onValueChange = { newName = it },
label = { Text("File Name") },
suffix = { Text(extension) },
singleLine = true,
isError = hasInvalidChars,
modifier = Modifier.fillMaxWidth()
)
if (hasInvalidChars) {
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "Invalid file name",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.error
)
}
}
},
confirmButton = {

View File

@@ -489,6 +489,7 @@ private fun DirectoryBrowserDialog(
scope.launch {
val trimmedName = name.trim()
if (trimmedName.isEmpty()) return@launch
val newPath = "$currentPath/$trimmedName"
RootManager.executeCommand("mkdir -p \"$newPath\"")
// Create marker file to indicate this folder was created by the app
@@ -716,6 +717,9 @@ private fun DirectoryBrowserDialog(
// Create folder dialog
if (showCreateFolderDialog) {
val hasInvalidChars = newFolderName.any { !it.isLetterOrDigit() && it !in "-_. ()[]+," }
val isValidInput = newFolderName.isNotBlank() && !hasInvalidChars
AlertDialog(
onDismissRequest = {
showCreateFolderDialog = false
@@ -723,24 +727,36 @@ private fun DirectoryBrowserDialog(
},
title = { Text("Create Directory") },
text = {
OutlinedTextField(
value = newFolderName,
onValueChange = { newFolderName = it },
label = { Text("Directory name") },
singleLine = true,
modifier = Modifier.fillMaxWidth()
)
Column {
OutlinedTextField(
value = newFolderName,
onValueChange = { newFolderName = it },
label = { Text("Directory name") },
singleLine = true,
isError = hasInvalidChars,
modifier = Modifier.fillMaxWidth()
)
if (hasInvalidChars) {
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "Invalid directory name",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.error
)
}
}
},
confirmButton = {
TextButton(
onClick = {
if (newFolderName.isNotBlank()) {
if (isValidInput) {
createFolder(newFolderName)
showCreateFolderDialog = false
newFolderName = ""
}
},
enabled = newFolderName.isNotBlank()
enabled = isValidInput
) {
Text("Create")
}