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

Function isSubstitutionCommand

src/tools/BashTool/sedValidation.ts:142–238  ·  view source on GitHub ↗

* Pattern 2: Check if this is a substitution command * Allows: sed 's/pattern/replacement/flags' where flags are only: g, p, i, I, m, M, 1-9 * When allowFileWrites is true, allows -i flag and file arguments for in-place editing * When allowFileWrites is false (default), requires stdout-only (no f

(
  command: string,
  expressions: string[],
  hasFileArguments: boolean,
  options?: { allowFileWrites?: boolean },
)

Source from the content-addressed store, hash-verified

140 * @internal Exported for testing
141 */
142function isSubstitutionCommand(
143 command: string,
144 expressions: string[],
145 hasFileArguments: boolean,
146 options?: { allowFileWrites?: boolean },
147): boolean {
148 const allowFileWrites = options?.allowFileWrites ?? false
149
150 // When not allowing file writes, must NOT have file arguments
151 if (!allowFileWrites && hasFileArguments) {
152 return false
153 }
154
155 const sedMatch = command.match(/^\s*sed\s+/)
156 if (!sedMatch) return false
157
158 const withoutSed = command.slice(sedMatch[0].length)
159 const parseResult = tryParseShellCommand(withoutSed)
160 if (!parseResult.success) return false
161 const parsed = parseResult.tokens
162
163 // Extract all flags
164 const flags: string[] = []
165 for (const arg of parsed) {
166 if (typeof arg === 'string' && arg.startsWith('-') && arg !== '--') {
167 flags.push(arg)
168 }
169 }
170
171 // Validate flags based on mode
172 // Base allowed flags for both modes
173 const allowedFlags = ['-E', '--regexp-extended', '-r', '--posix']
174
175 // When allowing file writes, also permit -i and --in-place
176 if (allowFileWrites) {
177 allowedFlags.push('-i', '--in-place')
178 }
179
180 if (!validateFlagsAgainstAllowlist(flags, allowedFlags)) {
181 return false
182 }
183
184 // Must have exactly one expression
185 if (expressions.length !== 1) {
186 return false
187 }
188
189 const expr = expressions[0]!.trim()
190
191 // STRICT ALLOWLIST: Must be exactly a substitution command starting with 's'
192 // This rejects standalone commands like 'e', 'w file', etc.
193 if (!expr.startsWith('s')) {
194 return false
195 }
196
197 // Parse substitution: s/pattern/replacement/flags
198 // Only allow / as delimiter (strict)
199 const substitutionMatch = expr.match(/^s\/(.*?)$/)

Callers 1

Calls 3

tryParseShellCommandFunction · 0.85
pushMethod · 0.45

Tested by

no test coverage detected