남의 웹사이트에서 버그를 하나 찾았다. 대단한 건 아니고 — 노출된 관리자 엔드포인트, 새는 API, 누군가 폐기를 깜빡한 서브도메인. 알려줄 의무는 없다. 하지만 당신은 알려주고 싶어 하는 부류라 시도한다. 그리고 발견한다. 그럴 준비가 안 된 조직에 취약점을 제보하는 일이 인터넷에서 가장 맥 빠지는 심부름 중 하나라는 걸.

연락처 페이지엔 영업 폼이 있다. 고객지원은 주문번호를 묻는다. 범용 info@ 함은 답이 없거나, 티켓 번호와 침묵으로 답한다. 링크드인으로 보안 엔지니어에게 메시지 보내는 건 정신 나간 짓 같고, 절반은 당신이 보낼 그 메시지 — “안녕하세요, 제가 귀사 고객 데이터를 읽을 수 있는 것 같아요” — 가 바로 당신을 공격자로 몰 경보를 울린다. 사람들은 이보다 덜한 일로도 소송 위협을 받아 왔다. 그래서 자주 포기하고, 버그는 열린 채 남고, 정문이 없었다는 이유로 모두가 더 나빠진다.

security.txt는 그 정문을 고치는 해법이다. 아름답도록 작은 아이디어인데, RFC가 된 지 4년이 지나도 거의 아무도 갖고 있지 않다.

표준 전체가 냅킨 한 장에 들어간다

RFC 9116은 2022년 4월 Ed Foudil과 Yakov Shafranovich가 낸 것으로, 고정되고 예측 가능한 위치에 두는 평문 파일을 표준화한다: /.well-known/security.txt. 뭔가 제보하려는 연구자 — 또는 봇 — 는 그 한 경로만 확인하면 어디로 보낼지 알아낸다. 개념 전체가 그거다. API도, 계정도, 협상도 없다. “우리가 망가졌다고 알려주는 법”을 위한 잘 알려진 주소.

파일은 필드 목록이고, RFC가 필수로 못 박은 건 정확히 둘이다:

Contact: mailto:security@example.com
Expires: 2027-01-01T00:00:00.000Z

Contact이 이 모든 것의 요점이다: 제보가 갈 이메일, 전화번호, 또는 폼 URL. 나머지는 전부 선택이다 — Encryption(PGP 키 링크), Policy(공개 규칙), Acknowledgments(명예의 전당), Preferred-Languages, Canonical(파일의 공식 위치). RFC는 심지어 파일에 OpenPGP 서명을 하라고 권한다. 누군가 연락처 주소를 조작해 제보를 조용히 자기에게 돌리지 못하게. 잘 설계된 작은 표준이다. 뻔한 공격을 예상했다. 거의 아무것도 요구하지 않는다.

그런데도: 리포팅 서비스 URIports가 상위 100만 도메인을 훑었을 때 security.txt가 있는 곳은 2024년 4월 0.7%, 2025년 1월 **1.25%**였다. 어떻게 반올림하든 — 텍스트 파일 하나와 10분이면 되는 이 표준을, 지구에서 가장 많이 방문되는 사이트의 98% 넘는 곳이 4년째 무시하고 있다.

Expires 필드에서 웃겨진다

“덜 쓰인다”를 더 뼈아픈 것으로 바꾸는 디테일이 여기 있다. RFC 9116은 Expires를 필수로 만들었고, 일부러 그랬다: 조용히 낡아버린 보안 연락처는 함정이니까. 목록에 적힌 사람은 2년 전에 퇴사했고, 함은 아무도 안 보고, PGP 키는 분실됐다. 그래서 RFC는 모든 파일에 만료일을 달게 강제하고 1년 미만으로 설정하길 권한다 — 살아 있는 파일은 갱신돼야 하도록. 누군가 아직 챙기고 있음을 증명하는 작고 반복되는 행위.

문제가 벌써 보인다. 지속적 관심을 요구하는 유일한 필드가, 그 관심을 아무도 안 주고 있음을 드러내는 필드다. 그리고 실제로 존재하는 파일을 감사해 보면 그게 드러난다. URIports의 2025년 1월 조사에서 파일의 45%는 Expires 필드가 아예 없었고, 13%는 이미 지난 날짜를 달고 있었다. 사이트는 성실함이 발작하던 어느 날 security.txt를 한 번 게시하고는, Expires 필드가 잡아내려고 설계된 바로 그 짓을 했다: 잊어버렸다. 그 조사에서 RFC를 완전히 준수한 파일은 44%뿐이었고, 빠졌거나 지난 Expires가 가장 흔한 이유 중 하나다.

만료된 security.txt는 없느니만 못하다. 없는 파일은 정직하다: 연구자에게 “여긴 공식 채널이 없으니 알아서 하라”고 말한다. 만료된 파일은 거짓말한다. 관리되는 프로세스의 자신만만한 태도로 연락처 주소를 내밀고, 연구자는 공들인 보고서를 security@로 보내고, 그건 그걸 설정한 인턴이 떠난 뒤로 아무도 안 연 함에 떨어진다. 제보는 이뤄졌다. 다만 수신되지 않았을 뿐. 그리고 모든 걸 제대로 한 연구자는 그 차이를 알 방법이 없다.

파일은 프로세스의 대리물이고, 프로세스는 위조할 수 없다

이게 내가 실제로 주장하고 싶은 부분이다. “채택률이 낮으니 더 노력하라”는 지루한 결론이고 게다가 틀렸으니까.

security.txt는 배포가 사소하다. 그런데 배포되지 않았다면, 그건 기술 문제가 아니고 사실 게으름 문제도 아니다. 파일 게시는 쉽다. 그걸 진심으로 하는 건 안 쉽다. security.txt를 정직하게 게시하려면 조직은 그 뒤의 어려운 질문에 이미 답해 있어야 한다: 들어온 취약점 제보는 누가 읽나? 금요일 저녁 6시에 우리가 데이터를 흘린다는 제보가 오면 뭘 하나? 제보자에게 감사할까, 위협할까? 보안 주장을 분류할 사람이 있나, 아니면 비밀번호 재설정 뒤에 줄 선 고객지원 큐에 묻힐까? security@에 이름이 붙어 있나, 아니면 브랜딩만 좋은 블랙홀인가?

파일은 그 작업의 마지막 5분이다. 그게 없는 조직은 대개 5분째에서 시간이 모자란 게 아니다. 1분부터 55분까지를 아예 안 한 곳들이다 — 제보를 받을 프로세스가 없어서 Contact 필드에 적을 참말이 없는 곳들. security.txt는 채택에 실패한 게 아니다. 불편한 뭔가를 측정하는 데 성공했다: 대부분의 조직엔 자기가 망가졌다는 걸 들을 작동하는 방법이 없고, 필수 텍스트 파일은 그걸 만들어낼 수 없다는 것. 없는 사람을 잘 알려진 URI로 덮을 수는 없다.

낡은 파일들은 같은 얘기를 반대편에서 한다. 만료된 security.txt는 딱 하루 오후 동안 존재했던 프로세스의 화석이다. 누군가 게시할 만큼은 신경 썼고 갱신할 만큼은 안 썼다 — 즉 의도는 진짜였고 프로세스는 결코 아니었다. Expires 필드는 거의 우연히, 조직의 보안 연락 프로세스가 살아 있는지 방부 처리됐는지를 재는 최선의 공개 센서가 됐다.

실제로 뭐에 좋은가

“이 표준은 망했다”로 끝내고 싶진 않다. 안 망했고, 냉소를 견디는 쓸모가 있으니까.

채택률 1%에서도 security.txt는 진심으로 할 거라면 게시할 값어치가 있다 — 뛰어난 버그 제보가 쏟아져서가 아니라, 대안이 내가 서두에 연 그 미로이고, 그 미로가 당신을 조용히 구해줬을 단 한 명의 정직한 제보자를 잃게 하기 때문이다. 파일을 두고, Contact에 실제로 모니터링되는 주소를 넣고, 그리고 — 이게 규율 전체다 — Expires 날짜에 캘린더 알림을 걸어라. 알림이 진짜 제품이다. 텍스트 파일은 그 영수증일 뿐이다.

그리고 안 짚고 넘기기엔 너무 좋은 정찰(recon) 각도가 있다. 파일이 고정된 공개 경로에 살기 때문에, 그 존재·내용, 그리고 결정적으로 그 신선도가 전부 밖에서, 대규모로, 건드리면 안 될 것을 건드리지 않고 관측된다. 조직이 security.txt를 갖고 있는지, 그 Expires 날짜가 과거인지는 그들의 보안 기능에 사람이 있는지에 대한 작지만 진짜인 신호다 — 좋은 정찰이 쌓아 올리는, 외부에서 교차 검증 가능한 그런 단서. 아무도 읽지 않는 표준은, 읽는 쪽이 당신이라면 꽤 읽을 만한 것으로 드러난다. 다만 그게 알려주는 것 대부분은 이거다: 여긴 아무도 없다.