mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-10 22:21:22 -07:00
fix: verify audio/video MIME types with content check (#16907)
This commit is contained in:
@@ -632,8 +632,6 @@ describe('fileUtils', () => {
|
||||
{ type: 'image', file: 'file.png', mime: 'image/png' },
|
||||
{ type: 'image', file: 'file.jpg', mime: 'image/jpeg' },
|
||||
{ type: 'pdf', file: 'file.pdf', mime: 'application/pdf' },
|
||||
{ type: 'audio', file: 'song.mp3', mime: 'audio/mpeg' },
|
||||
{ type: 'video', file: 'movie.mp4', mime: 'video/mp4' },
|
||||
{ type: 'binary', file: 'archive.zip', mime: 'application/zip' },
|
||||
{ type: 'binary', file: 'app.exe', mime: 'application/octet-stream' },
|
||||
])(
|
||||
@@ -644,6 +642,25 @@ describe('fileUtils', () => {
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
{ type: 'audio', ext: '.mp3', mime: 'audio/mpeg' },
|
||||
{ type: 'video', ext: '.mp4', mime: 'video/mp4' },
|
||||
])(
|
||||
'should detect $type type for binary files with $ext extension',
|
||||
async ({ type, ext, mime }) => {
|
||||
const filePath = path.join(tempRootDir, `test${ext}`);
|
||||
const binaryContent = Buffer.from([
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
]);
|
||||
actualNodeFs.writeFileSync(filePath, binaryContent);
|
||||
|
||||
mockMimeGetType.mockReturnValueOnce(mime);
|
||||
expect(await detectFileType(filePath)).toBe(type);
|
||||
|
||||
actualNodeFs.unlinkSync(filePath);
|
||||
},
|
||||
);
|
||||
|
||||
it('should detect svg type by extension', async () => {
|
||||
expect(await detectFileType('image.svg')).toBe('svg');
|
||||
expect(await detectFileType('image.icon.svg')).toBe('svg');
|
||||
@@ -664,6 +681,24 @@ describe('fileUtils', () => {
|
||||
// filePathForDetectTest is already a text file by default from beforeEach
|
||||
expect(await detectFileType(filePathForDetectTest)).toBe('text');
|
||||
});
|
||||
|
||||
it('should detect .adp files with XML content as text, not audio (#16888)', async () => {
|
||||
const adpFilePath = path.join(tempRootDir, 'test.adp');
|
||||
const xmlContent = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<AdapterType Name="ATimeOut" Comment="Adapter for timed events">
|
||||
<InterfaceList>
|
||||
<EventInputs>
|
||||
<Event Name="TimeOut"/>
|
||||
</EventInputs>
|
||||
</InterfaceList>
|
||||
</AdapterType>`;
|
||||
actualNodeFs.writeFileSync(adpFilePath, xmlContent);
|
||||
mockMimeGetType.mockReturnValueOnce('audio/adpcm');
|
||||
|
||||
expect(await detectFileType(adpFilePath)).toBe('text');
|
||||
|
||||
actualNodeFs.unlinkSync(adpFilePath);
|
||||
});
|
||||
});
|
||||
|
||||
describe('processSingleFileContent', () => {
|
||||
@@ -778,7 +813,10 @@ describe('fileUtils', () => {
|
||||
});
|
||||
|
||||
it('should process an audio file', async () => {
|
||||
const fakeMp3Data = Buffer.from('fake mp3 data');
|
||||
const fakeMp3Data = Buffer.from([
|
||||
0x49, 0x44, 0x33, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
]);
|
||||
actualNodeFs.writeFileSync(testAudioFilePath, fakeMp3Data);
|
||||
mockMimeGetType.mockReturnValue('audio/mpeg');
|
||||
const result = await processSingleFileContent(
|
||||
|
||||
@@ -306,11 +306,15 @@ export async function detectFileType(
|
||||
if (lookedUpMimeType.startsWith('image/')) {
|
||||
return 'image';
|
||||
}
|
||||
if (lookedUpMimeType.startsWith('audio/')) {
|
||||
return 'audio';
|
||||
}
|
||||
if (lookedUpMimeType.startsWith('video/')) {
|
||||
return 'video';
|
||||
// Verify audio/video with content check to avoid MIME misidentification (#16888)
|
||||
if (
|
||||
lookedUpMimeType.startsWith('audio/') ||
|
||||
lookedUpMimeType.startsWith('video/')
|
||||
) {
|
||||
if (!(await isBinaryFile(filePath))) {
|
||||
return 'text';
|
||||
}
|
||||
return lookedUpMimeType.startsWith('audio/') ? 'audio' : 'video';
|
||||
}
|
||||
if (lookedUpMimeType === 'application/pdf') {
|
||||
return 'pdf';
|
||||
|
||||
Reference in New Issue
Block a user