mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-06-28 04:07:32 -07:00
Fix/command injection shell (#24170)
Co-authored-by: David Pierce <davidapierce@google.com>
This commit is contained in:
committed by
GitHub
parent
1c43deee07
commit
2a52611e71
@@ -1020,3 +1020,119 @@ export async function* execStreaming(
|
||||
prepared.cleanup?.();
|
||||
}
|
||||
}
|
||||
|
||||
export function detectCommandSubstitution(command: string): boolean {
|
||||
const shell = getShellConfiguration().shell;
|
||||
const isPowerShell =
|
||||
typeof shell === 'string' &&
|
||||
(shell.toLowerCase().includes('powershell') ||
|
||||
shell.toLowerCase().includes('pwsh'));
|
||||
if (isPowerShell) {
|
||||
return detectPowerShellSubstitution(command);
|
||||
}
|
||||
return detectBashSubstitution(command);
|
||||
}
|
||||
|
||||
function detectBashSubstitution(command: string): boolean {
|
||||
let inSingleQuote = false;
|
||||
let inDoubleQuote = false;
|
||||
let i = 0;
|
||||
while (i < command.length) {
|
||||
const char = command[i];
|
||||
if (char === "'" && !inDoubleQuote) {
|
||||
inSingleQuote = !inSingleQuote;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (char === '"' && !inSingleQuote) {
|
||||
inDoubleQuote = !inDoubleQuote;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (inSingleQuote) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (char === '\\' && i + 1 < command.length) {
|
||||
if (inDoubleQuote) {
|
||||
const next = command[i + 1];
|
||||
if (['$', '`', '"', '\\', '\n'].includes(next)) {
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (char === '$' && command[i + 1] === '(') {
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
!inDoubleQuote &&
|
||||
(char === '<' || char === '>') &&
|
||||
command[i + 1] === '('
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if (char === '`') {
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const POWERSHELL_KEYWORD_RE =
|
||||
/\b(if|elseif|else|foreach|for|while|do|switch|try|catch|finally|until|trap|function|filter)(\s+[-\w]+)*\s*$/i;
|
||||
|
||||
function detectPowerShellSubstitution(command: string): boolean {
|
||||
let inSingleQuote = false;
|
||||
let inDoubleQuote = false;
|
||||
let i = 0;
|
||||
while (i < command.length) {
|
||||
const char = command[i];
|
||||
|
||||
if (char === "'" && !inDoubleQuote) {
|
||||
inSingleQuote = !inSingleQuote;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (char === '"' && !inSingleQuote) {
|
||||
inDoubleQuote = !inDoubleQuote;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inSingleQuote) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (char === '`' && i + 1 < command.length) {
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
if (char === '$' && command[i + 1] === '(') {
|
||||
return true;
|
||||
}
|
||||
if (!inDoubleQuote && char === '@' && command[i + 1] === '(') {
|
||||
return true;
|
||||
}
|
||||
if (!inDoubleQuote && char === '(') {
|
||||
const before = command.slice(0, i).trimEnd();
|
||||
const prevChar = before[before.length - 1];
|
||||
if (prevChar === '(') {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (POWERSHELL_KEYWORD_RE.test(before)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user