MCPcopy
hub / github.com/codeaashu/claude-code / validatePath

Function validatePath

src/tools/PowerShellTool/pathValidation.ts:1013–1264  ·  view source on GitHub ↗

* Validates a file system path, handling tilde expansion.

(
  filePath: string,
  cwd: string,
  toolPermissionContext: ToolPermissionContext,
  operationType: FileOperationType,
)

Source from the content-addressed store, hash-verified

1011 * Validates a file system path, handling tilde expansion.
1012 */
1013function validatePath(
1014 filePath: string,
1015 cwd: string,
1016 toolPermissionContext: ToolPermissionContext,
1017 operationType: FileOperationType,
1018): ResolvedPathCheckResult {
1019 // Remove surrounding quotes if present
1020 const cleanPath = expandTilde(filePath.replace(/^['"]|['"]$/g, ''))
1021
1022 // SECURITY: PowerShell Core normalizes backslashes to forward slashes on all
1023 // platforms, but path.resolve on Linux/Mac treats them as literal characters.
1024 // Normalize before resolution so traversal patterns like dir\..\..\etc\shadow
1025 // are correctly detected.
1026 const normalizedPath = cleanPath.replace(/\\/g, '/')
1027
1028 // SECURITY: Backtick (`) is PowerShell's escape character. It is a no-op in
1029 // many positions (e.g., `/ === /) but defeats Node.js path checks like
1030 // isAbsolute(). Redirection targets use raw .Extent.Text which preserves
1031 // backtick escapes. Treat any path containing a backtick as unvalidatable.
1032 if (normalizedPath.includes('`')) {
1033 // Red-team P3: backtick is already resolved for StringConstant args
1034 // (parser uses .value); this guard primarily fires for redirection
1035 // targets which use raw .Extent.Text. Strip is a no-op for most special
1036 // escapes (`n → n) but that's fine — wrong guess → no deny match →
1037 // falls to ask.
1038 const backtickStripped = normalizedPath.replace(/`/g, '')
1039 const denyHit = checkDenyRuleForGuessedPath(
1040 backtickStripped,
1041 cwd,
1042 toolPermissionContext,
1043 operationType,
1044 )
1045 if (denyHit) {
1046 return {
1047 allowed: false,
1048 resolvedPath: denyHit.resolvedPath,
1049 decisionReason: { type: 'rule', rule: denyHit.rule },
1050 }
1051 }
1052 return {
1053 allowed: false,
1054 resolvedPath: normalizedPath,
1055 decisionReason: {
1056 type: 'other',
1057 reason:
1058 'Backtick escape characters in paths cannot be statically validated and require manual approval',
1059 },
1060 }
1061 }
1062
1063 // SECURITY: Block module-qualified provider paths. PowerShell allows
1064 // `Microsoft.PowerShell.Core\FileSystem::/etc/passwd` which resolves to
1065 // `/etc/passwd` via the FileSystem provider. The `::` is the provider
1066 // path separator and doesn't match the simple `^[a-z]{2,}:` regex.
1067 if (normalizedPath.includes('::')) {
1068 // Strip everything up to and including the first :: — handles both
1069 // FileSystem::/path and Microsoft.PowerShell.Core\FileSystem::/path.
1070 // Double-:: (Foo::Bar::/x) strips first only → 'Bar::/x' → resolve

Callers 3

validateCommandPathsFunction · 0.50

Calls 10

getPlatformFunction · 0.85
containsPathTraversalFunction · 0.85
safeResolvePathFunction · 0.85
getFsImplementationFunction · 0.85
matchingRuleForInputFunction · 0.85
expandTildeFunction · 0.70
isPathAllowedFunction · 0.70
getGlobBaseDirectoryFunction · 0.70
resolveFunction · 0.50

Tested by

no test coverage detected