feat: ZIP 경로 가드 추가 및 무결성 size 검증 도입 (TDD)

- buildZip에 경로 하드닝 추가: ../, 절대경로(/), 역슬래시(\) 금지
- assets.integrity.index.json에 size(byte) 필드 추가
- verifyIntegrity에서 size 불일치 검증 추가
- 경로/사이즈 검증 테스트 추가: zip.pathGuard.test.ts
- 전체 테스트 그린 유지
This commit is contained in:
2025-11-16 17:30:47 +09:00
parent cf8f02bfca
commit 7928f9b6c5
6 changed files with 275 additions and 1 deletions
+12
View File
@@ -14,8 +14,19 @@ export async function buildZip(input: BuildZipInput): Promise<Uint8Array> {
zip.file('index.html', input.html)
zip.file('styles.css', input.css)
zip.file('app.js', input.js)
// guard: basic path sanitizer to avoid directory traversal or absolute paths
const isSafePath = (p: string) => {
if (!p || typeof p !== 'string') return false
if (p.startsWith('/')) return false
if (p.includes('..')) return false
if (p.includes('\\')) return false
return true
}
if (input.assets) {
for (const [path, bytes] of Object.entries(input.assets)) {
if (!isSafePath(path)) throw new Error(`Invalid asset path: ${path}`)
// In Node/Vitest, use Buffer for robust binary handling
const buf = Buffer.from(bytes)
zip.file(path, buf as unknown as Buffer)
@@ -33,6 +44,7 @@ export async function buildZip(input: BuildZipInput): Promise<Uint8Array> {
}
}
for (const [path, bytes] of Object.entries(input.extras)) {
if (!isSafePath(path)) throw new Error(`Invalid extra path: ${path}`)
const buf = Buffer.from(bytes)
zip.file(path, buf as unknown as Buffer)
}