라이트업 작성 규격
이 문서는 팀 내부 문서지만 공개해 둡니다. 글마다 형식이 달라지면 읽는 쪽이 매번 구조를 다시 파악해야 하고, 무엇보다 민감정보 검토를 빠뜨리기 쉬워집니다.
새 글은 src/content/articles/<lang>/<slug>.md 에 만듭니다. 한국어판과 영어판은 같은 slug 를 써야 언어 스위처가 동작합니다.
프론트매터
스키마는 src/content.config.ts 에 정의되어 있고 .strict() 입니다. 정의되지 않은 키를 쓰면 빌드가 즉시 실패합니다. 오타 난 키가 조용히 무시되는 것보다 낫습니다.
아래는 형식을 보여주기 위한 가상의 예시입니다. 값은 실제 제보가 아닙니다.
---
title: "내부 API 접두사가 게이트웨이 인증을 우회하던 문제"
description: "라우터가 공개 접두사 한 개만 특수 처리해서, 이름이 비슷한 내부 네임스페이스 전체가 인증 없이 프록시되던 문제. 패치 기준으로 재현 절차와 영향 범위를 정리했습니다."
pubDate: 2026-09-19
updatedDate: 2026-09-22
lang: ko
tags: ["web", "authorization", "code-audit"]
author: chwrld
severity: high
target: "Example Gateway 1.4.2"
cve: ["CVE-2026-00000"]
bounty: "$750"
draft: false
---
필드별 규칙:
| 필드 | 필수 | 규칙 |
|---|---|---|
title | 필수 | 목록 카드와 <title> 에 같이 쓰입니다. 벤더명을 앞에 붙이지 말고 결함 자체를 적습니다 |
description | 필수 | meta description 겸 RSS 요약 겸 카드 발췌. 한 문단, 줄바꿈 없이. 1~2문장 |
pubDate | 필수 | 2026-09-19 — 따옴표 없이 쓰면 YAML이 날짜로 파싱합니다 |
updatedDate | 선택 | 본문을 의미 있게 고쳤을 때만. 오타 수정으로는 올리지 않습니다 |
lang | 필수 | ko 또는 en. 파일이 들어 있는 디렉터리와 반드시 일치해야 합니다 |
tags | 선택 | 소문자 kebab-case. 그대로 URL이 됩니다 (/articles/tags/web/) |
author | 선택 | 기본값 chwrld. src/data/team.ts 의 handle 과 맞춥니다 |
draft | 선택 | true 면 프로덕션 목록·RSS·사이트맵에서 빠집니다. 개발 서버에서는 DRAFT 뱃지로 보입니다 |
severity | 선택 | critical / high / medium / low / info. 취약점 글이 아니면 생략 |
target | 선택 | 대상 제품과 버전. 버전 없는 target 은 6개월 뒤에 아무 의미가 없습니다 |
cve | 선택 | 배열. 실제로 발급된 번호만. 신청만 한 상태라면 적지 않습니다 |
bounty | 선택 | 벤더 공지 표기를 그대로. 금액 추측·환산 금지 |
heroImage | 선택 | public/ 기준 절대 경로 (/og/cdap.png) |
slug 키는 쓰지 않습니다. slug는 파일명이 유일한 출처입니다.
draft 와 _ 접두사의 차이
둘 다 글을 숨기지만 용도가 다릅니다.
draft: true— 빌드에는 포함되고 목록에서만 빠집니다. URL을 직접 아는 사람은 볼 수 있으므로 리뷰용 링크 공유에 씁니다.- 파일명을
_wip-foo.md로 — 컬렉션에 아예 로드되지 않습니다. 스키마 검증도 통과할 필요가 없습니다. 아직 프론트매터도 안 채운 초고에 씁니다.
미공개 취약점 세부가 들어 있는 초고는 draft: true 가 아니라 _ 접두사를 쓰세요. draft는 URL을 아는 사람에게 노출됩니다.
본문 규칙
<h1> 은 레이아웃이 title 로 만듭니다. 본문은 ## 부터 시작합니다.
코드블록
언어를 반드시 명시합니다. Shiki가 하이라이팅하는 기준이고, 없으면 회색 덩어리가 됩니다.
```http
GET /internalapi/v1/namespaces/default/config HTTP/1.1
Host: gateway.example
Authorization: REDACTED
```
요청·응답은 http, 셸은 bash, 설정 파일은 yaml / json. 디컴파일 결과나 패치 diff는 diff 를 쓰면 + / - 가 색으로 구분됩니다.
긴 출력은 잘라냅니다. 스택트레이스 200줄을 그대로 붙이는 대신 관련된 프레임만 남기고 [...] 로 표시합니다. 자른 사실을 표시하지 않고 자르면 재현하는 사람이 혼란스러워집니다.
이미지
public/articles/<slug>/아래에 두고/articles/<slug>/foo.png로 참조합니다.- alt 텍스트는 필수입니다. “스크린샷” 이 아니라 그 스크린샷에서 봐야 하는 것을 적습니다.
- 가능하면 스크린샷 대신 코드블록을 씁니다. 텍스트는 검색되고 복사되고 diff가 되지만 PNG는 안 됩니다.
- 스크린샷이 꼭 필요하면 브라우저 창 전체가 아니라 필요한 영역만 찍습니다. 전체 창에는 다른 탭 제목, 북마크, 알림이 같이 찍힙니다.
표
표는 재현 절차가 아니라 비교에 씁니다 — 버전별 동작 차이, 파라미터별 응답 차이. 절차는 번호 목록이 낫습니다. 열은 4개를 넘기지 않습니다. 모바일에서 가로 스크롤이 생깁니다.
인용
벤더 공지나 커밋 메시지를 인용할 때는 출처를 함께 적습니다.
> 인용문.
> <cite>벤더 권고문 SA-2026-001</cite>
공개 전 체크리스트
공개 전에 글쓴이가 아닌 다른 사람이 이 목록을 확인합니다. 자기 글에서 자기 실수를 찾는 건 잘 안 됩니다.
자격증명 · 토큰
- 실제 세션 쿠키, Bearer 토큰, API 키가 본문·코드블록·스크린샷에 없는지
- 있던 자리는
REDACTED또는 명백한 더미값(eyJhbG...TRUNCATED)으로 대체했는지 - 토큰 일부만 지운 곳이 없는지 — 앞 8자만 가린 JWT는 여전히 유효한 토큰입니다
- 테스트에 쓴 계정 비밀번호가 본문에 없는지
- 벤더 내부 호스트명·IP가 공개되어도 무해한지 확인했는지
타인의 데이터
- 다른 사용자의 이메일·전화번호·이름·주문번호가 응답 예시에 없는지
- 스크린샷 모서리, 브라우저 탭 제목, 자동완성 드롭다운에 개인정보가 없는지
- 내부 식별자(UUID, 계정 ID)가 실제 사용자에 연결되지 않는 값인지
페이로드 범위
- PoC가 결함의 존재를 보이는 범위에서 멈추는지
- 그대로 실행하면 타인의 계정을 탈취하거나 데이터를 파괴하는 완성된 스크립트가 아닌지
- 자동화 도구(대량 스캐너, 계정 열거 스크립트)를 첨부하지 않았는지
공개 가능 여부
- 벤더가 패치를 배포했는지 확인했는지
- 벤더가 공개에 동의했는지, 또는 공개 권고문이 이미 나왔는지
- 버그바운티 프로그램·플랫폼 약관이 공개를 제한하지 않는지
- 같은 코드베이스에서 찾은 아직 미패치인 변형이 글에 새어 들어가지 않았는지
마지막 항목이 실제로 가장 위험합니다. 변형 분석을 하면서 찾은 두 번째 결함이 첫 번째 글의 “이 패턴은 다른 곳에도 있습니다” 문장에 그대로 담기는 경우가 있습니다. 미패치 변형은 별도 제보가 끝날 때까지 언급하지 않습니다.
자세한 공개 판단 기준은 책임 있는 공개 정책에 있습니다.