Security: Unsafe shell execution with user-controlled pager command#355
Security: Unsafe shell execution with user-controlled pager command#355tomaioo wants to merge 1 commit into
Conversation
The `pagePlainText` function in `src/core/pager.ts` spawns a pager command with `shell: true` using the `resolveTextPagerCommand` result. While the function attempts to prevent recursive `hunk` launches via regex, the `PAGER` or `HUNK_TEXT_PAGER` environment variable is passed directly to the shell without proper sanitization. An attacker who can control these environment variables could inject arbitrary shell commands (e.g., `PAGER='$(malicious)'` or backtick injection). The regex check `/(^|\s)hunk(\s|$)/` is insufficient to prevent command injection. Signed-off-by: tomaioo <203048277+tomaioo@users.noreply.github.com>
Greptile SummaryThis PR eliminates a shell-injection risk in
Confidence Score: 3/5Safe to merge once the broken test is fixed; the core security change is correct but the test suite as-is will not pass. The implementation change itself is sound — removing src/core/pager.test.ts — the Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["pagePlainText(text, env, deps)"] --> B{stdout.isTTY?}
B -- No --> C["deps.stdout.write(text)"]
B -- Yes --> D["resolveTextPagerCommand(env)"]
D --> E{HUNK_TEXT_PAGER or PAGER set?}
E -- No --> F["return 'less -R'"]
E -- Yes --> G{matches /hunk/ regex?}
G -- Yes --> F
G -- No --> H["return candidate string"]
F --> I["parsePagerCommand(command)"]
H --> I
I --> J["tokenise: split on whitespace,\nrespect quoted segments"]
J --> K["[executable, ...args]"]
K --> L["spawn(executable, args,\n{ shell: false })"]
L --> M["pager.stdin.end(text)"]
M --> N["await 'close' event"]
N --> O{exit code === 0?}
O -- Yes --> P["done"]
O -- No --> Q["throw Error('Pager command failed')"]
Reviews (1): Last reviewed commit: "fix(core): unsafe shell execution with u..." | Re-trigger Greptile |
|
More exhaustive solution with tests in #358 |
Summary
Security: Unsafe shell execution with user-controlled pager command
Problem
Severity:
High| File:src/core/pager.ts:L45The
pagePlainTextfunction insrc/core/pager.tsspawns a pager command withshell: trueusing theresolveTextPagerCommandresult. While the function attempts to prevent recursivehunklaunches via regex, thePAGERorHUNK_TEXT_PAGERenvironment variable is passed directly to the shell without proper sanitization. An attacker who can control these environment variables could inject arbitrary shell commands (e.g.,PAGER='$(malicious)'or backtick injection). The regex check/(^|\s)hunk(\s|$)/is insufficient to prevent command injection.Solution
Avoid
shell: trueand instead parse the pager command into arguments using a safe argument parser, or useexecFilewith an explicit array of arguments. If shell is required, strictly validate the pager command against an allowlist of known safe pagers, or useshell: falsewithspawnand pass the command as an first argument with any flags as subsequent array elements.Changes
src/core/pager.ts(modified)