fix: align shell allowlist handling (#11510) (#11813)

This commit is contained in:
cornmander
2025-10-23 16:55:01 -04:00
committed by GitHub
parent 48ff9e1555
commit 5e70a7dd46
3 changed files with 76 additions and 5 deletions

View File

@@ -61,6 +61,28 @@ function getDisallowedFileReadCommand(testFile: string): {
}
}
function getChainedEchoCommand(): { allowPattern: string; command: string } {
const secondCommand = getAllowedListCommand();
switch (shell) {
case 'powershell':
return {
allowPattern: 'Write-Output',
command: `Write-Output "foo" && ${secondCommand}`,
};
case 'cmd':
return {
allowPattern: 'echo',
command: `echo "foo" && ${secondCommand}`,
};
case 'bash':
default:
return {
allowPattern: 'echo',
command: `echo "foo" && ${secondCommand}`,
};
}
}
describe('run_shell_command', () => {
it('should be able to run a shell command', async () => {
const rig = new TestRig();
@@ -405,6 +427,35 @@ describe('run_shell_command', () => {
expect(failureLog!.toolRequest.success).toBe(false);
});
it('should reject chained commands when only the first segment is allowlisted in non-interactive mode', async () => {
const rig = new TestRig();
await rig.setup(
'should reject chained commands when only the first segment is allowlisted',
);
const chained = getChainedEchoCommand();
const shellInjection = `!{${chained.command}}`;
await rig.run(
{
stdin: `${shellInjection}\n`,
yolo: false,
},
`--allowed-tools=ShellTool(${chained.allowPattern})`,
);
// CLI should refuse to execute the chained command without scheduling run_shell_command.
const toolLogs = rig
.readToolLogs()
.filter((log) => log.toolRequest.name === 'run_shell_command');
// Success is false because tool is in the scheduled state.
for (const log of toolLogs) {
expect(log.toolRequest.success).toBe(false);
expect(log.toolRequest.args).toContain('&&');
}
});
it('should allow all with "ShellTool" and other specific tools', async () => {
const rig = new TestRig();
await rig.setup(