You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The GitHub Copilot CLI's path-access scanner misclassifies quoted shell-command arguments that happen to start with / as filesystem paths the action intends to read or write, even when the receiving command is a no-op or treats the argument as literal data.
The scanner inspects bash-tool command text before execution. In the tested forms, a quoted argument whose first character is / triggers an interactive "Allow directory access" permission prompt, presenting the argument as a candidate directory the action may read or write.
The trigger appears to depend on the token's leading character (a forward slash) rather than on whether the receiving command opens the token as a filesystem path, and rather than on whether the token names an existing directory. Strings such as /)) (which does not name an existing directory and is not accessed by the receiving command) and /tmp is a sentence (whose /tmp prefix is allowlisted in the bare unquoted form but is not protected once the quoted argument is extended with non-path characters) both trigger the prompt.
The scanner appears to treat echo and the tested awk program-argument form differently from other tested commands: those pass, while most other tested commands trigger the prompt, including no-ops such as true and :, and data-only commands such as printf.
This is closely related to #774, which describes a similar lexical-scanning failure mode rejecting command-like words in text arguments passed to non-bash tools. The present report covers a complementary case within the bash-tool path: arguments are scanned by token shape rather than by whether the receiving command would actually open them.
Steps to Reproduce
Invoke one of the tested non-exempt commands, such as true, :, or printf, with a quoted argument whose first character is a forward slash (/). In the tested cases, the remainder of the string varied widely — from an allowlisted-prefix extension like /tmp is a sentence, to a path-shaped sensitive substring like /etc/passwd, to a string that does not name any directory in the tested environment like /)) — and the prompt fired in every case.
The string need not be a valid path; it need not exist on disk; the command need not access files.
The scanner intercepts the call before bash runs with an "Allow directory access" permission prompt that defaults to "Yes, and add these directories to the allowed list".
Example
Quoted string starting with / passed to true
true'/))'
The CLI displays this interactive prompt before executing:
╭─ Allow directory access ─────────────────────────────────────────╮
│ │
│ This action may read or write the following path outside your │
│ allowed directory list. │
│ │
│ ╭──────────────────────────────────────────────────────────────╮ │
│ │ /)) │ │
│ ╰──────────────────────────────────────────────────────────────╯ │
│ │
│ Do you want to allow this? │
│ │
│ 1. Yes │
│ ❯ 2. Yes, and add these directories to the allowed list │
│ 3. No (Esc) │
│ │
│ ↑↓ to navigate · Enter to select · Esc to cancel │
╰──────────────────────────────────────────────────────────────────╯
true is the universal POSIX no-op: it ignores every argument and returns success. The argument /)) does not name an existing directory in the tested environment, is not sensitive-looking, and is not accessed by true — it is simply a string that happens to start with /. Yet the prompt's title — "Allow directory access" — and the candidate text shown in its own bordered box indicate the CLI is treating /)) as a filesystem path the action may read or write. The default option ("Yes, and add these directories to the allowed list") would proceed with the call; based on that option's label, I would expect accepting it to also persist /)) in the allowed-directory list.
Quoted argument that begins with an allowlisted bare token (/tmp)
true'/tmp is a sentence'
Same prompt, with /tmp is a sentence shown as the candidate directory. This is striking because the unquoted variant true /tmp passes (see Contrast table below): the allowlist that protects /tmp does not carry through to a quoted argument whose first character is /, even when the quoted content starts with the same allowlisted prefix.
Quoted path-shaped string passed to the null builtin
:'/tmp is a noop arg'
Same prompt, with /tmp is a noop arg shown as the candidate directory. : is the shell null command and never inspects its arguments.
Argument to printf
printf'%s\n''/tmp is a noop arg'
Same prompt, with the quoted argument shown as the candidate directory. printf treats this argument as data substituted into the format string, not as a path to read. A separately tested format-string case, printf '/tmp is a noop arg\n', also triggers the same prompt, so the observed scan is not limited to printf's data arguments; both tested positions are subject to it.
command builtin does not change the outcome
commandtrue'/tmp is a sentence'
Same prompt, with the quoted argument shown as the candidate directory. Wrapping the command with the command builtin does not change the scanner's classification.
Contrast: tested forms that the scanner passes
Form
Result
echo '/etc/passwd is a sentence'
passes
echo /etc/passwd (unquoted)
passes
echo '/var/log was the locus'
passes
awk '/error/ {print}' (the awk regex starts with /)
passes
true /foo
passes
true /tmp
passes
true /xyz
passes
The scanner clearly recognizes single-quoting (it extracts the full quoted content as a single candidate path) and appears to treat echo and the tested awk form differently from other commands: echo arguments pass in both quoted and unquoted forms, and the tested awk program-argument form passes even when its first character is /. Comparable arguments to true, :, and printf trigger the permission prompt. Additionally, the tested forms true /foo, true /tmp, and true /xyz pass even though the receiving command is true — which does trigger the prompt for other tested arguments. What is not modeled in the tested forms is the receiving command's semantics: true, :, and printf never open files at the named path in the tested forms, yet their arguments are still subject to the path-access rule. Conversely, a quoted argument whose first character is not / does not trigger the prompt even when / appears later in the token: true '(/ 10 2)' passes, supporting the inference that the trigger condition is the token's leading character rather than the presence of / anywhere in the token.
Asymmetry: commands that pass vs. true
echo '/etc/passwd is a sentence' passes but true '/etc/passwd is a sentence' triggers the permission prompt. Similarly, awk '/error/ {print}' passes — the awk regex argument's leading / is not flagged — but the same content passed to true (true '/error/ {print}') does trigger the permission prompt. The tested commands have the same filesystem-access semantics with respect to these arguments: none of them opens the argument as a file. The asymmetry suggests command-specific treatment for echo and the tested awk form rather than a general rule about whether the argument can be opened as a path.
I have not exhaustively tested every command, every leading-/ argument shape, every allowlisted path, or every argument position. The claims here are limited to the tested contrast cases above and to the reproducible permission prompts.
Expected Behavior
A semantics-aware path-access guard would:
Distinguish between commands that use arguments as filesystem paths (e.g., cat, mv, cp, chmod) and commands that do not open the tested argument positions as paths (e.g., true, :, printf, and echo).
Apply the path-access rule only to arguments at positions where the receiving command will treat the argument as a filesystem path.
Treat literal text data passed to data-only commands as data, not as path-access claims.
Actual Behavior
The observed behavior is consistent with the scanner inspecting quoted leading-/ arguments for the tested non-exempt commands and treating them as candidate directory-access strings without distinguishing:
Whether the receiving command opens arguments as filesystem paths.
Whether any argument position of the receiving command can open filesystem paths; in the tested printf cases, both format-string and data positions are scanned even though neither is opened as a path.
Whether the bytes name an existing directory or just happen to have a leading /.
Within the tested forms, the scanner appears to recognize quoting (it extracts the entire quoted content as a single candidate path) and to pass arguments to echo and the tested awk form, but it does not pass comparable arguments to other tested commands or argument positions.
Impact
Requires interactive approval for string operations that do not access files: print operations such as printf '%s' '/tmp is a noop arg' trigger the permission prompt; no-op operations such as true '/tmp was the locus' trigger the permission prompt.
Interrupts legitimate agent actions before execution: the agent can choose a command whose runtime behavior would not open the named path, but the pre-execution scanner still intercepts the action with a permission prompt based on the argument text alone.
May pollute the allowed-directory list if the default option is accepted: the prompt's default option ("Yes, and add these directories to the allowed list") is labeled as adding the candidate string to the allowed list; based on that label, I would expect accepting it to persist non-path strings such as /tmp is a sentence as registered allowed directories. A user who casually accepts the default could then accumulate arbitrary English-prose fragments in their allowed-list configuration.
Requires indirect workarounds: routing all data through echo or the tested awk program-argument form, splitting strings to avoid a leading /, paraphrasing prose, or piping through unrelated transformations to obscure the leading slash.
Environment
GitHub Copilot CLI version: 1.0.48
OS: Linux
Use case: passing literal strings (English prose, JSON data, command examples) that incidentally begin with system-path-like substrings.
Suggested Fix
One narrow fix would be to make the scanner command-semantics-aware:
Maintain a per-command path-argument-position table for common commands.
Apply the same observed behavior of passing echo arguments and the tested awk program-argument form to other known data-only / no-op commands such as true, :, and printf.
For commands that do have path-bearing argument positions, such as cat, cp, mv, or chmod, inspect only the positions that the command can actually use as filesystem paths.
A runtime filesystem-access signal, where available, could complement these lexical checks. A narrower available fix is to avoid applying path-access rules to known data-only argument positions.
Note: the scanner already passes arguments to echo and the tested awk form, and it passes the tested forms true /foo, true /tmp, and true /xyz. The fix is to extend comparable behavior to other data-only commands (true, :, printf) and to no-op builtins generally.
Workaround
Route data through echo — or through the tested awk program-argument form — instead of other commands when the data starts with /.
Avoid any quoted argument whose first character is /, where possible. (Often impossible when the data is determined by the user's request.)
Bug: CLI intercepts command names in text responses and attempts to execute them #774 — Related report: a similar lexical-scanning failure mode rejects command-like words in text arguments passed to non-bash tools (e.g., the session tool). Both reports describe interception behavior when text containing pattern-matching tokens flows through contexts where the surrounding grammar makes clear the text is data, not the protected form the scanner pattern-matches against.
Sentences containing the word kill in a heredoc body are misinterpreted as kill commands #3334 — Related report: heredoc-body scanning misinterprets ordinary words like kill, pkill, killall in heredoc payload as shell kill commands without arguments. Similar lexical-scanning failure mode: text that looks like a protected pattern is rejected even though the surrounding grammar makes clear it is data.
Note: Together with #774 and #3334, this report describes interception behavior across multiple contexts that follow a similar lexical-scanning failure mode. The scanner already passes echo arguments, the tested awk form, and the tested unquoted paths /foo, /tmp, and /xyz for true, so a change to extend command-semantics awareness to other commands could be scoped specifically to a per-command path-argument-position table.
Describe the bug
Description
The GitHub Copilot CLI's path-access scanner misclassifies quoted shell-command arguments that happen to start with
/as filesystem paths the action intends to read or write, even when the receiving command is a no-op or treats the argument as literal data.The scanner inspects bash-tool command text before execution. In the tested forms, a quoted argument whose first character is
/triggers an interactive "Allow directory access" permission prompt, presenting the argument as a candidate directory the action may read or write.The trigger appears to depend on the token's leading character (a forward slash) rather than on whether the receiving command opens the token as a filesystem path, and rather than on whether the token names an existing directory. Strings such as
/))(which does not name an existing directory and is not accessed by the receiving command) and/tmp is a sentence(whose/tmpprefix is allowlisted in the bare unquoted form but is not protected once the quoted argument is extended with non-path characters) both trigger the prompt.The scanner appears to treat
echoand the testedawkprogram-argument form differently from other tested commands: those pass, while most other tested commands trigger the prompt, including no-ops such astrueand:, and data-only commands such asprintf.This is closely related to #774, which describes a similar lexical-scanning failure mode rejecting command-like words in text arguments passed to non-bash tools. The present report covers a complementary case within the bash-tool path: arguments are scanned by token shape rather than by whether the receiving command would actually open them.
Steps to Reproduce
true,:, orprintf, with a quoted argument whose first character is a forward slash (/). In the tested cases, the remainder of the string varied widely — from an allowlisted-prefix extension like/tmp is a sentence, to a path-shaped sensitive substring like/etc/passwd, to a string that does not name any directory in the tested environment like/))— and the prompt fired in every case.Example
Quoted string starting with
/passed totrueThe CLI displays this interactive prompt before executing:
trueis the universal POSIX no-op: it ignores every argument and returns success. The argument/))does not name an existing directory in the tested environment, is not sensitive-looking, and is not accessed bytrue— it is simply a string that happens to start with/. Yet the prompt's title — "Allow directory access" — and the candidate text shown in its own bordered box indicate the CLI is treating/))as a filesystem path the action may read or write. The default option ("Yes, and add these directories to the allowed list") would proceed with the call; based on that option's label, I would expect accepting it to also persist/))in the allowed-directory list.Quoted argument that begins with an allowlisted bare token (
/tmp)Same prompt, with
/tmp is a sentenceshown as the candidate directory. This is striking because the unquoted varianttrue /tmppasses (see Contrast table below): the allowlist that protects/tmpdoes not carry through to a quoted argument whose first character is/, even when the quoted content starts with the same allowlisted prefix.Quoted path-shaped string passed to the null builtin
Same prompt, with
/tmp is a noop argshown as the candidate directory.:is the shell null command and never inspects its arguments.Argument to printf
Same prompt, with the quoted argument shown as the candidate directory.
printftreats this argument as data substituted into the format string, not as a path to read. A separately tested format-string case,printf '/tmp is a noop arg\n', also triggers the same prompt, so the observed scan is not limited to printf's data arguments; both tested positions are subject to it.commandbuiltin does not change the outcomeSame prompt, with the quoted argument shown as the candidate directory. Wrapping the command with the
commandbuiltin does not change the scanner's classification.Contrast: tested forms that the scanner passes
echo '/etc/passwd is a sentence'echo /etc/passwd(unquoted)echo '/var/log was the locus'awk '/error/ {print}'(the awk regex starts with/)true /footrue /tmptrue /xyzThe scanner clearly recognizes single-quoting (it extracts the full quoted content as a single candidate path) and appears to treat
echoand the testedawkform differently from other commands:echoarguments pass in both quoted and unquoted forms, and the testedawkprogram-argument form passes even when its first character is/. Comparable arguments totrue,:, andprintftrigger the permission prompt. Additionally, the tested formstrue /foo,true /tmp, andtrue /xyzpass even though the receiving command istrue— which does trigger the prompt for other tested arguments. What is not modeled in the tested forms is the receiving command's semantics:true,:, andprintfnever open files at the named path in the tested forms, yet their arguments are still subject to the path-access rule. Conversely, a quoted argument whose first character is not/does not trigger the prompt even when/appears later in the token:true '(/ 10 2)'passes, supporting the inference that the trigger condition is the token's leading character rather than the presence of/anywhere in the token.Asymmetry: commands that pass vs.
trueecho '/etc/passwd is a sentence'passes buttrue '/etc/passwd is a sentence'triggers the permission prompt. Similarly,awk '/error/ {print}'passes — the awk regex argument's leading/is not flagged — but the same content passed totrue(true '/error/ {print}') does trigger the permission prompt. The tested commands have the same filesystem-access semantics with respect to these arguments: none of them opens the argument as a file. The asymmetry suggests command-specific treatment forechoand the testedawkform rather than a general rule about whether the argument can be opened as a path.I have not exhaustively tested every command, every leading-
/argument shape, every allowlisted path, or every argument position. The claims here are limited to the tested contrast cases above and to the reproducible permission prompts.Expected Behavior
A semantics-aware path-access guard would:
cat,mv,cp,chmod) and commands that do not open the tested argument positions as paths (e.g.,true,:,printf, andecho).Actual Behavior
The observed behavior is consistent with the scanner inspecting quoted leading-
/arguments for the tested non-exempt commands and treating them as candidate directory-access strings without distinguishing:printfcases, both format-string and data positions are scanned even though neither is opened as a path./.Within the tested forms, the scanner appears to recognize quoting (it extracts the entire quoted content as a single candidate path) and to pass arguments to
echoand the testedawkform, but it does not pass comparable arguments to other tested commands or argument positions.Impact
printf '%s' '/tmp is a noop arg'trigger the permission prompt; no-op operations such astrue '/tmp was the locus'trigger the permission prompt./tmp is a sentenceas registered allowed directories. A user who casually accepts the default could then accumulate arbitrary English-prose fragments in their allowed-list configuration./, similar to the impact described in Bug: CLI intercepts command names in text responses and attempts to execute them #774 for thesessiontool.echoor the testedawkprogram-argument form, splitting strings to avoid a leading/, paraphrasing prose, or piping through unrelated transformations to obscure the leading slash.Environment
Suggested Fix
One narrow fix would be to make the scanner command-semantics-aware:
echoarguments and the testedawkprogram-argument form to other known data-only / no-op commands such astrue,:, andprintf.cat,cp,mv, orchmod, inspect only the positions that the command can actually use as filesystem paths.A runtime filesystem-access signal, where available, could complement these lexical checks. A narrower available fix is to avoid applying path-access rules to known data-only argument positions.
Note: the scanner already passes arguments to
echoand the testedawkform, and it passes the tested formstrue /foo,true /tmp, andtrue /xyz. The fix is to extend comparable behavior to other data-only commands (true,:,printf) and to no-op builtins generally.Workaround
echo— or through the testedawkprogram-argument form — instead of other commands when the data starts with/./, where possible. (Often impossible when the data is determined by the user's request.)Related
sessiontool). Both reports describe interception behavior when text containing pattern-matching tokens flows through contexts where the surrounding grammar makes clear the text is data, not the protected form the scanner pattern-matches against.kill,pkill,killallin heredoc payload as shellkillcommands without arguments. Similar lexical-scanning failure mode: text that looks like a protected pattern is rejected even though the surrounding grammar makes clear it is data.Note: Together with #774 and #3334, this report describes interception behavior across multiple contexts that follow a similar lexical-scanning failure mode. The scanner already passes
echoarguments, the testedawkform, and the tested unquoted paths/foo,/tmp, and/xyzfortrue, so a change to extend command-semantics awareness to other commands could be scoped specifically to a per-command path-argument-position table.Affected version
GitHub Copilot CLI 1.0.48.
Steps to reproduce the behavior
No response
Expected behavior
No response
Additional context
No response