fix: Enhance path sanitization in getAudiobooksDir to prevent directory traversal and update getMigratedDocumentFileName tests to assert truncated- prefix and hash suffix.
This commit is contained in:
parent
47d838039a
commit
9c941b57ed
2 changed files with 14 additions and 9 deletions
|
|
@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
|||
import { spawn } from 'child_process';
|
||||
import { readFile, writeFile, mkdir, unlink, rm, rename, readdir } from 'fs/promises';
|
||||
import { existsSync, createReadStream } from 'fs';
|
||||
import { basename, join } from 'path';
|
||||
import { basename, join, resolve } from 'path';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { AUDIOBOOKS_V1_DIR, isAudiobooksV1Ready } from '@/lib/server/docstore';
|
||||
import { encodeChapterFileName, encodeChapterTitleTag, listStoredChapters, ffprobeAudio } from '@/lib/server/audiobook';
|
||||
|
|
@ -15,7 +15,14 @@ function getAudiobooksRootDir(request: NextRequest): string {
|
|||
const raw = request.headers.get('x-openreader-test-namespace')?.trim();
|
||||
if (!raw) return AUDIOBOOKS_V1_DIR;
|
||||
const safe = raw.replace(/[^a-zA-Z0-9._-]/g, '');
|
||||
return safe ? join(AUDIOBOOKS_V1_DIR, safe) : AUDIOBOOKS_V1_DIR;
|
||||
if (!safe || safe === '.' || safe === '..' || safe.includes('..')) {
|
||||
return AUDIOBOOKS_V1_DIR;
|
||||
}
|
||||
const resolved = resolve(AUDIOBOOKS_V1_DIR, safe);
|
||||
if (!resolved.startsWith(resolve(AUDIOBOOKS_V1_DIR) + '/')) {
|
||||
return AUDIOBOOKS_V1_DIR;
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
interface ConversionRequest {
|
||||
|
|
|
|||
|
|
@ -26,13 +26,11 @@ test.describe('Docstore Filename Safety', () => {
|
|||
const result = getMigratedDocumentFileName(id, specialName);
|
||||
|
||||
expect(result.length).toBeLessThanOrEqual(240);
|
||||
if (result.includes('truncated-')) {
|
||||
expect(result).toContain('truncated-');
|
||||
} else {
|
||||
// If it fits (depends on length), just ensure it is valid
|
||||
// 30 * 4 = 120 chars raw, but encoded?
|
||||
// Let's ensure logic works.
|
||||
}
|
||||
expect(result).toContain('truncated-');
|
||||
// The implementation replaces the name with a hash, so it should NOT contain the original special chars
|
||||
// and might not contain % if the hash is hex.
|
||||
expect(result).toMatch(/truncated-[a-f0-9]{32}$/);
|
||||
expect(result.startsWith(`${id}__`)).toBeTruthy();
|
||||
});
|
||||
|
||||
test('should handle edge case length exactly', () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue