Skip to content

feat: 업로드 파일 내용(시그니처) 확인과 악성코드 검사 지점 - #116

Merged
RosieOh merged 1 commit into
mainfrom
feat/upload-signature-scan
Sep 22, 2026
Merged

RosieOh merged 1 commit into
mainfrom
feat/upload-signature-scan

Conversation

@RosieOh

@RosieOh RosieOh commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Refs #49 (S3·서명 URL 은 남아 있어 이슈는 열어 둔다)

이슈 할 일 대응

  • 허용 MIME/확장자/최대 크기 정책 — 기존 구현 + 문서화
  • 서버측 파일 시그니처 검증 — FileSignatureValidator
  • 바이러스 스캔 연동 지점 — FileScanner (NoOp 기본 / ClamAV), fail-closed
  • 외부 저장소(S3) + 서명 URL — 남음. 비용·계정 결정 필요. FileStorageService 구현체만 추가하면 된다
  • 접근 권한/만료 정책 — 권한은 기존(소유권 확인 후 서버가 내려줌), 만료는 서명 URL 과 함께
  • 실패 케이스/보안 테스트

오류 응답

경우 상태 코드
내용이 확장자 형식이 아님 400 C006
악성코드 탐지 400 C007
검사를 켰는데 검사기 장애 503 C008

테스트

  • FileSignatureValidatorTest — 7개 형식 인식, SVG/HTML/WAVE/isom/짧은 입력/모르는 확장자 거절
  • LocalFileStorageServiceSecurityTest — 위장 파일·악성 판정 시 디스크에 아무것도 남지 않음, 검사기 장애 503
  • ClamAvFileScannerTest — 가짜 clamd 로 INSTREAM 조각 전송(150KB → 3조각)·OK/FOUND 해석·연결 실패
  • 전체 534 tests, 실패 0, skip 0. docker compose config 통과

실제 clamd 컨테이너로는 돌려 보지 않았다(이미지가 시그니처 DB 포함 1GB+). 프로토콜은 가짜 서버로 확인했다.

확장자와 Content-Type 은 클라이언트가 정하는 값이라, HTML·SVG 를 .png 로 올리면
기존 검사를 모두 통과했다. 브라우저가 내용을 보고 문서로 해석하면 저장형 XSS 가 된다.

- FileSignatureValidator: 앞 16바이트가 확장자 형식(jpg/png/gif/webp/heic/pdf)인지 확인. 400 C006
- FileScanner 검사 지점: 기본 NoOp, STORAGE_SCAN_ENABLED=true 면 ClamAV(clamd INSTREAM, 의존성 없음)
  악성 400 C007, 검사기 장애는 받지 않는다(fail-closed) 503 C008
- 저장은 검사한 바이트 그대로 쓴다 (스트림을 다시 열지 않음)
- docker compose --profile scan 으로 clamav 를 함께 띄울 수 있다
- docs/reference/file-upload-security.md

S3 + 서명 URL 은 비용·계정 결정이 필요해 이 변경에 넣지 않았다.
@RosieOh
RosieOh merged commit 3439e73 into main Sep 22, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant