Skip to content

마크다운 링크 protocol 필터 회귀 테스트 - #215

Merged
i3months merged 1 commit into
devfrom
test/markdown-url-protocol-guard
Aug 23, 2026
Merged

마크다운 링크 protocol 필터 회귀 테스트#215
i3months merged 1 commit into
devfrom
test/markdown-url-protocol-guard

Conversation

@i3months

Copy link
Copy Markdown
Member

배경

#213MarkdownContent 를 리뷰하다 발견한 테스트 공백이다. 렌더러 자체는 안전하다 — raw HTML 미허용 + rehype-sanitize. 문제는 그 방어가 테스트로 고정돼 있지 않다는 점이다.

기존 테스트:

it('raw HTML(script 포함)은 실행 가능한 요소로 렌더되지 않는다')

이 케이스는 rehype-sanitize 를 빼도 통과한다. react-markdown 이 기본적으로 raw HTML 을 escape 하기 때문이다. 즉 sanitize 플러그인이 실제로 붙어 동작하는지는 아무것도 검증하지 못하고 있었다.

링크 protocol 필터링은 오직 rehype-sanitize 만 막아준다 — 여기가 그 플러그인의 실질 담당 구역이다.

무엇

javascript:alert(1)                    → href 제거
JaVaScRiPt:alert(1)  (대소문자 우회)    → href 제거
data:text/html;base64,...              → href 제거
https://example.com/a  (정상 링크)      → 그대로 유지

마지막 케이스는 과잉 차단 회귀를 막는다 — 필터를 조이다 정상 링크까지 죽이면 AI 리포트의 참고 링크가 전부 먹통이 된다.

실효성 확인

rehype-sanitize 를 제거하고 돌리면 앞 3개만 실패하고 정상 링크 케이스는 통과한다. 테스트가 의도한 지점을 정확히 겨냥하고 있다는 뜻이다.

왜 지금

Markdown 의 렌더 대상이 사용자 입력에서 파생된다:

사용처 내용
DocumentList 이력서·레포 분석 마크다운 (사용자 이력서에서 파생)
AnswerCoachingAccordion answerRewrite사용자 답변을 AI 가 다시 쓴 것
FeedbackAiReport / ReviewBlock AI 리포트·코칭

AI 를 거치긴 하지만 사용자 텍스트가 흘러 들어가는 경로다. 지금은 안전한데, 나중에 sanitize 스키마를 커스터마이즈하거나(테이블 정렬·클래스 허용 등 자연스러운 요구다) 플러그인을 걷어내는 변경이 조용히 통과하면 안 된다.

확인했고 문제없던 것 (리뷰 결과)

  • MarkdownContentrehype-raw 없음, 링크에 target="_blank" rel="noreferrer"
  • Markdown 사용처 5곳 모두 AI 생성 필드 — 사용자 원문 직접 렌더 없음 ✅
  • AI 리포트(feedback_report.py)에 사용자 답변 원문 미포함, 질문은 개행 정규화 후 헤딩 삽입 ✅
  • 리포트 프록시(GET /feedback/report)는 ownedFeedback 소유권 검증, 키는 DB 출처라 경로 주입 없음 ✅
  • 공개 응답에서 내부 S3 키 제거됨 ✅

기존 XSS 테스트(raw HTML/script)는 react-markdown 이 raw HTML 을 escape 하므로
rehype-sanitize 가 없어도 통과한다 — 즉 sanitize 플러그인이 실제로 붙어 있는지는
검증하지 못한다. 링크 protocol 필터링은 오직 rehype-sanitize 만 막아주므로
그 경로를 덮는다.

javascript: / 대소문자 우회 / data:text/html 세 가지에서 href 가 제거되는지,
그리고 정상 https 링크는 살아남는지(과잉 차단 아님) 확인한다.

rehype-sanitize 를 빼면 앞 3개만 실패하는 것을 확인했다.

렌더 대상(분석 문서 마크다운·answerRewrite)이 사용자 이력서·답변에서 파생되므로,
스키마를 커스터마이즈하거나 플러그인을 빼는 변경이 조용히 통과하면 안 된다.
@i3months
i3months merged commit b62c52c into dev Aug 23, 2026
5 checks passed
@i3months
i3months deleted the test/markdown-url-protocol-guard branch August 23, 2026 15:47
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