사이드프로젝트 slecs

포트폴리오에서 비공개 저장소 링크 노출 차단

목차

비공개 저장소 링크 제거하다 발견한 권한 누수

포트폴리오 페이지에 프로젝트 리스트 뿌리는데, 비공개 레포까지 그냥 클릭 가능한 링크로 박혀있던 걸 뒤늦게 발견함. 외부에서 클릭하면 404로 튕기긴 하지만, 그 자체로 "여기 비공개 레포 있음"을 노출하는 거라 좋은 그림은 아님.

뭐가 문제였는지

  • 카드 컴포넌트에서 repo.url 을 무조건 앵커 태그로 감쌌음
  • isPrivate 플래그는 데이터에 있었지만 렌더링 분기를 안 탔음
  • 결과적으로 외부 노출용 페이지에 내부 레포 이름 + 깨진 링크가 같이 노출됨

내부에서만 보던 시절엔 문제 안 됐는데, 이커머스 파트너 쪽에 공유하는 외부 페이지로 용도가 확장되면서 드러남. 권한 분기 빠진 UI 컴포넌트의 전형적인 케이스.

고친 방식

분기 단순하게 가져감. 비공개면 링크 빼고 자물쇠 아이콘 + "Private" 라벨로 표시함.

{repo.isPrivate ? (
  <span className="repo-card locked" role="text">
    <LockIcon /> {repo.name}
    <em>Private</em>
  </span>
) : (
  <a href={repo.url} className="repo-card">
    {repo.name}
  </a>
)}

자물쇠 아이콘은 디자인 시스템에 이미 있던 거 그대로 가져다 씀. 새로 그릴 필요 없었음.

디테일에서 막힌 부분

이슈 원인 처리
호버 커서가 여전히 pointer 공통 스타일 상속 locked 변형에 cursor: default
스크린리더가 "링크"로 읽음 앵커 태그 잔존 role="text" 로 교체
자물쇠 색이 본문과 동일 토큰 미지정 muted 색상 토큰 적용

호버 커서랑 접근성 부분은 처음 PR 올렸을 때 리뷰에서 잡혀서 한 번 더 돌렸음. UI 분기 한 줄 같아 보여도 디자인 토큰/접근성/시멘틱까지 같이 봐야 한다는 거 다시 확인함.

회고

  • 데이터에 권한 플래그가 있다고 끝이 아님. 렌더링 레이어에서 분기를 실제로 타는지 까지 확인해야 함
  • 내부 전용 컴포넌트가 외부 노출 경로에 그대로 흘러가는 케이스는 항상 의심
  • 자물쇠 아이콘 같은 시각적 신호는 "여기 못 봄"을 명시적으로 알려줘서 오히려 어색하지 않음. 숨기는 것보다 표시하는 게 나을 때도 있음

다음

댓글 0

첫 댓글 달아줘.