Skip to content

[fix] 추억 노트 미디어 URL 무검증 저장 — 위험 스킴·비관리 URL이 원문 그대로 재서빙 #258

Closed

Description

@OnlyReadOneBook

증상

추억 노트(PLAYLIST) 생성·수정 요청의 미디어 URL 필드(videoUrl, thumbnailUrl, coverUrl, memorialPhotoUrl)가 쓰기 시점에 아무 검증 없이 저장되고, 조회 시 비관리 URL은 원문 그대로 재서빙됩니다. intent:·javascript: 같은 위험 스킴이나 평문 http:// URL도 서버가 그대로 에코합니다.

근거 코드

  • domain/afternote/dto/AfternoteCreateRequest.java — MemorialVideoRequest.videoUrl·thumbnailUrl, SongRequest.coverUrl 모두 검증 애노테이션 없는 평문 String
  • domain/image/service/S3Service.java promoteMediaKey — javadoc 명시대로 "관리되지 않는 URL이면 기존처럼 extract 결과(또는 원문)를 반환"해 비관리 값이 그대로 DB에 들어감
  • 같은 파일 generateGetPresignedUrl·resolvePublicUrl — extractStorageKey 가 비관리 http(s) URL에 null 을 주면 rawUrlOrKey 원문 반환
  • domain/afternote/service/AfternoteService.java 상세 매핑 — memorialVideo 의 videoUrl/thumbnailUrl 이 위 메서드를 그대로 지남

영향

  • 저장 API를 직접 호출하면 임의 문자열(위험 스킴 포함)이 저장되고, 수신자 상세 응답까지 원문으로 내려갑니다 — 작성자가 아닌 수신자 기기에서 발화할 수 있는 cross-user 벡터입니다.
  • 계약이 열려 있는 동안 FE 소비처마다 스킴 가드를 반복해야 합니다. 작성자 상세는 Afternote-FE#1336이 http/https allowlist 로 방어했지만, 수신자 상세는 무가드로 ACTION_VIEW 직행이 확인됐습니다(FE 후속 작업 별도 진행 중).
  • 정상 경로(FE presigned 업로드)는 전부 관리 S3(https)라, 비관리 통과가 실제로 지키는 데이터가 있는지 불명확합니다.

제안

  • 쓰기 시점 검증: 추억 노트 미디어 URL 필드는 관리 S3 키/URL 만 허용(최소한 https + host 필수)으로 강제.
  • 레거시 비관리 URL 실데이터 유무를 먼저 확인하고 마이그레이션 필요 여부 결정.
  • 같은 패턴이 다른 도메인(예: 타임레터 블록 videoUrl)에도 있을 수 있으나 담당이 달라 이 이슈 범위는 애프터노트 도메인으로 한정합니다.

Activity

  1. OnlyReadOneBook commented on Aug 28, 2026

    @OnlyReadOneBook
    ContributorAuthor

    FE 후속 메모: 이 검증이 반영되면 FE 영상 실행 가드(Afternote-FE#1336의 launchMemorialVideo, 수신자 화면 이식분)의 정책 거부 분기 발화가 «계약 위반 데이터» 신호가 됩니다. 지금은 레거시 비관리 URL이 정당하게 존재할 수 있어 기록을 붙이면 노이즈라 보류했고, 반영 후 FE 쪽에서 거부 분기 ErrorReporter 기록을 붙일지 재판단합니다.

  2. added a commit that references this issue on Aug 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions