mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-10 22:21:22 -07:00
fix(core): address GCS path input (#11221)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: cornmander <shikhman@google.com>
This commit is contained in:
@@ -227,6 +227,35 @@ describe('GCSTaskStore', () => {
|
||||
'tar.c command failed to create',
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error if taskId contains path traversal sequences', async () => {
|
||||
const store = new GCSTaskStore('test-bucket');
|
||||
const maliciousTask: SDKTask = {
|
||||
id: '../../../malicious-task',
|
||||
metadata: {
|
||||
_internal: {
|
||||
agentSettings: {
|
||||
cacheDir: '/tmp/cache',
|
||||
dataDir: '/tmp/data',
|
||||
logDir: '/tmp/logs',
|
||||
tempDir: '/tmp/temp',
|
||||
},
|
||||
taskState: 'working',
|
||||
},
|
||||
},
|
||||
kind: 'task',
|
||||
status: {
|
||||
state: 'working',
|
||||
timestamp: new Date().toISOString(),
|
||||
},
|
||||
contextId: 'test-context',
|
||||
history: [],
|
||||
artifacts: [],
|
||||
};
|
||||
await expect(store.save(maliciousTask)).rejects.toThrow(
|
||||
'Invalid taskId: ../../../malicious-task',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('load', () => {
|
||||
@@ -323,6 +352,14 @@ describe('GCSTaskStore', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error if taskId contains path traversal sequences', async () => {
|
||||
const store = new GCSTaskStore('test-bucket');
|
||||
const maliciousTaskId = '../../../malicious-task';
|
||||
await expect(store.load(maliciousTaskId)).rejects.toThrow(
|
||||
`Invalid taskId: ${maliciousTaskId}`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('NoOpTaskStore', () => {
|
||||
|
||||
@@ -23,6 +23,13 @@ type ObjectType = 'metadata' | 'workspace';
|
||||
const getTmpArchiveFilename = (taskId: string): string =>
|
||||
`task-${taskId}-workspace-${uuidv4()}.tar.gz`;
|
||||
|
||||
// Validate the taskId to prevent path traversal attacks by ensuring it only contains safe characters.
|
||||
const isTaskIdValid = (taskId: string): boolean => {
|
||||
// Allow only alphanumeric characters, dashes, and underscores, and ensure it's not empty.
|
||||
const validTaskIdRegex = /^[a-zA-Z0-9_-]+$/;
|
||||
return validTaskIdRegex.test(taskId);
|
||||
};
|
||||
|
||||
export class GCSTaskStore implements TaskStore {
|
||||
private storage: Storage;
|
||||
private bucketName: string;
|
||||
@@ -78,6 +85,9 @@ export class GCSTaskStore implements TaskStore {
|
||||
}
|
||||
|
||||
private getObjectPath(taskId: string, type: ObjectType): string {
|
||||
if (!isTaskIdValid(taskId)) {
|
||||
throw new Error(`Invalid taskId: ${taskId}`);
|
||||
}
|
||||
return `tasks/${taskId}/${type}.tar.gz`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user