7928f9b6c5
- buildZip에 경로 하드닝 추가: ../, 절대경로(/), 역슬래시(\) 금지 - assets.integrity.index.json에 size(byte) 필드 추가 - verifyIntegrity에서 size 불일치 검증 추가 - 경로/사이즈 검증 테스트 추가: zip.pathGuard.test.ts - 전체 테스트 그린 유지
30 lines
1.0 KiB
TypeScript
30 lines
1.0 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import { buildZip } from '@/lib/exporter/zip'
|
|
|
|
function u8(s: string): Uint8Array {
|
|
return new TextEncoder().encode(s)
|
|
}
|
|
|
|
describe('buildZip path guard', () => {
|
|
it('rejects dangerous asset paths with .. segments', async () => {
|
|
await expect(
|
|
buildZip({ html: '', css: '', js: '', assets: { '../evil.txt': u8('x') } })
|
|
).rejects.toThrow(/invalid asset path/i)
|
|
})
|
|
|
|
it('rejects dangerous extras with absolute path and backslashes', async () => {
|
|
await expect(
|
|
buildZip({ html: '', css: '', js: '', extras: { '/abs.txt': u8('x') } })
|
|
).rejects.toThrow(/invalid extra path/i)
|
|
|
|
await expect(
|
|
buildZip({ html: '', css: '', js: '', extras: { 'assets\\x.bin': u8('x') } })
|
|
).rejects.toThrow(/invalid extra path/i)
|
|
})
|
|
|
|
it('accepts safe relative paths under assets/', async () => {
|
|
const zip = await buildZip({ html: '', css: '', js: '', assets: { 'assets/a.bin': u8('ok') } })
|
|
expect(zip.byteLength).toBeGreaterThan(0)
|
|
})
|
|
})
|