MCPcopy Index your code
hub / github.com/codeaashu/claude-code / isReadOnlyCommand

Function isReadOnlyCommand

src/tools/PowerShellTool/readOnlyValidation.ts:1168–1305  ·  view source on GitHub ↗
(
  command: string,
  parsed?: ParsedPowerShellCommand,
)

Source from the content-addressed store, hash-verified

1166 * @returns true if the command is read-only, false otherwise
1167 */
1168export function isReadOnlyCommand(
1169 command: string,
1170 parsed?: ParsedPowerShellCommand,
1171): boolean {
1172 const trimmedCommand = command.trim()
1173 if (!trimmedCommand) {
1174 return false
1175 }
1176
1177 // If no parsed AST available, conservatively return false
1178 if (!parsed) {
1179 return false
1180 }
1181
1182 // If parsing failed, reject
1183 if (!parsed.valid) {
1184 return false
1185 }
1186
1187 const security = deriveSecurityFlags(parsed)
1188 // Reject commands with script blocks — we can't verify the code inside them
1189 // e.g., Get-Process | ForEach-Object { Remove-Item C:\foo } looks like a safe pipeline
1190 // but the script block contains destructive code
1191 if (
1192 security.hasScriptBlocks ||
1193 security.hasSubExpressions ||
1194 security.hasExpandableStrings ||
1195 security.hasSplatting ||
1196 security.hasMemberInvocations ||
1197 security.hasAssignments ||
1198 security.hasStopParsing
1199 ) {
1200 return false
1201 }
1202
1203 const segments = getPipelineSegments(parsed)
1204
1205 if (segments.length === 0) {
1206 return false
1207 }
1208
1209 // SECURITY: Block compound commands that contain a cwd-changing cmdlet
1210 // (Set-Location/Push-Location/Pop-Location/New-PSDrive) alongside any other
1211 // statement. This was previously scoped to cd+git only, but that overlooked
1212 // the isReadOnlyCommand auto-allow path for cd+read compounds (finding #27):
1213 // Set-Location ~; Get-Content ./.ssh/id_rsa
1214 // Both cmdlets are in CMDLET_ALLOWLIST, so without this guard the compound
1215 // auto-allows. Path validation resolved ./.ssh/id_rsa against the STALE
1216 // validator cwd (e.g. /project), missing any Read(~/.ssh/**) deny rule.
1217 // At runtime PowerShell cd's to ~, reads ~/.ssh/id_rsa.
1218 //
1219 // Any compound containing a cwd-changing cmdlet cannot be auto-classified
1220 // read-only when other statements may use relative paths — those paths
1221 // resolve differently at runtime than at validation time. BashTool has the
1222 // equivalent guard via compoundCommandHasCd threading into path validation.
1223 const totalCommands = segments.reduce(
1224 (sum, seg) => sum + seg.commands.length,
1225 0,

Callers 2

isReadOnlyFunction · 0.85

Calls 6

deriveSecurityFlagsFunction · 0.85
getPipelineSegmentsFunction · 0.85
isCwdChangingCmdletFunction · 0.85
isNullRedirectionTargetFunction · 0.85
isAllowlistedCommandFunction · 0.85
isSafeOutputCommandFunction · 0.85

Tested by

no test coverage detected