Skip to content

[ENHANCEMENT] 在某些情况下自动执行命令会失效 #865

@TaiyakiOffical

Description

@TaiyakiOffical

Problem (one or two sentences)

在某些情况下即使我明确设定了Allowed Auto-ExecuteCommands为"*"时,某些命令仍会要求我手动批准执行。例如,当我向agent对话时输入:“python -c ‘
a=(0,1)

请执行以上命令”

按道理来说,agent会自动执行以上命令并用python为我创建一个a的元组(尽管这样做没什么意义,但我这里只是举例子),agent仍需要我的批准才能执行

Context (who is affected and when)

需要做大规模评测的场景,我希望他能自动执行任务而不是需要我参与人工批准某些编程语句

Desired behavior (conceptual, not technical)

我希望他能自动执行所有任务而不是需要我参与人工批准

Constraints / preferences (optional)

No response

Request checklist

  • I've searched existing Issues and Discussions for duplicates
  • This describes a specific problem with clear context and impact

Acceptance criteria (optional)

No response

Proposed approach (optional)

事实上,任何语句中出现"=("的执行语句都需要手动批准,这是因为src\core\auto-approval\commands.ts中以下函数的影响,被“zshProcessSubstitution=/=([^)]+)/.test(source)”误伤了。

会命中的例子(在zsh里确实是进程替换):
-diff file =(sort file)→命中【=(sort file)】
-cat =(echo hello)→命中【=(echo hello)】

也会命中的“误伤”例子(并不一定真会执行):
-python -c "a=(0,1)"→命中【=(0,1)】
-echo "x=(1)"→命中【=(1)】

真实zsh的=(...)进程替换几乎总是以“独立token”出现,前面通常有空白或分隔符,比如diff a =(sort b)。
现在的正则会把任何地方的=(都当危险,包括编程语言里的a=(0,1)、字符串里的"x=(1)"。

把它改成“前面必须是行首/空白/常见分隔符”,就能避免你这种误伤:
const zshProcessSubstitution = /(^|[\s;&|()])=([^)]+)/.test(source)

export function containsDangerousSubstitution(source: string): boolean {
// Check for dangerous parameter expansion operators that can execute commands
// ${var@P} - Prompt string expansion (interprets escape sequences and executes embedded commands)
// ${var@Q} - Quote removal
// ${var@E} - Escape sequence expansion
// ${var@A} - Assignment statement
// ${var@a} - Attribute flags
const dangerousParameterExpansion = /${[^}]@[PQEAa][^}]}/.test(source)
// Check for parameter expansions with assignments that could contain escape sequences
// ${var=value} or ${var:=value} can embed commands via escape sequences like \140 (backtick)
// Also check for ${var+value}, ${var:-value}, ${var:+value}, ${var:?value}
const parameterAssignmentWithEscapes =
/${[^}][=+-?][^}]\[0-7]{3}[^}]}/.test(source) || // octal escapes
/${[^}]
[=+-?][^}]\x[0-9a-fA-F]{2}[^}]}/.test(source) || // hex escapes
/${[^}][=+-?][^}]\u[0-9a-fA-F]{4}[^}]}/.test(source) // unicode escapes
// Check for indirect variable references that could execute commands
// ${!var} performs indirect expansion which can be dangerous with crafted variable names
const indirectExpansion = /${![^}]+}/.test(source)
// Check for here-strings with command substitution
// <<<$(...) or <<<... can execute commands
const hereStringWithSubstitution = /<<<\s
($(|`)/.test(source)

// Check for zsh process substitution =(...) which executes commands
// =(...) creates a temporary file containing the output of the command, but executes it
const zshProcessSubstitution = /=\([^)]+\)/.test(source)

// Check for zsh glob qualifiers with code execution (e:...:)
// Patterns like *(e:whoami:) or ?(e:rm -rf /:) execute commands during glob expansion
// This regex matches patterns like *(e:...:), ?(e:...:), +(e:...:), @(e:...:), !(e:...:)
const zshGlobQualifier = /[*?+@!]\(e:[^:]+:\)/.test(source)
// Return true if any dangerous pattern is detected
return (
	dangerousParameterExpansion ||
	parameterAssignmentWithEscapes ||
	indirectExpansion ||
	hereStringWithSubstitution ||
	zshProcessSubstitution ||
	zshGlobQualifier
)

}

Trade-offs / risks (optional)

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions