보안 정책
Herkos는 비밀키와 암호화된 메시지를 다루므로 보안 신고를 진지하게 받아들이며, 문제는 늦게보다 일찍 듣는 편을 원합니다.
취약점 신고
보안 문제는 공개 이슈로 올리지 마세요.
GitHub의 비공개 취약점 신고를 이용하거나 security@herkos.email 로 이메일을 보내 비공개로 신고해 주세요.
포함하면 좋은 내용: 문제가 무엇인지, 어떻게 재현하는지, 어떤 플랫폼과 버전에서 시험했는지, 공격자가 무엇을 할 수 있는지. 개념 증명(PoC)이 있으면 큰 도움이 됩니다.
신고에 여러분 자신의 nsec, 비밀키, 벙커 비밀값을 절대 넣지 마세요.
신고는 며칠 안에 확인 회신을 드리는 것을 목표로 합니다. Herkos는 작은 프로젝트이므로 공개하기 전에 수정할 수 있도록 합리적인 시간을 주시기 바랍니다. 원하지 않으시는 경우가 아니라면 보안 권고문에 기꺼이 이름을 올려 드립니다.
대상 범위
Herkos 애플리케이션 자체: 키 처리와 저장, 메시지 암호화와 복호화(NIP-59 발신자
검사와 local_packages/nostr_mail의 숨은 참조(Bcc) 격리 포함), 앱 잠금, 릴레이 및
브리지 통신, 첨부파일 처리, 빌드와 릴리스 파이프라인.
범위 밖
- Nostr 프로토콜과 그 NIP 자체. 상위 프로젝트에 신고하세요.
- 제3자가 운영하는 릴레이, 브리지, Blossom 서버. Herkos는 기본값을 제공하지만 그것들을 운영하지 않습니다. 해당 운영자에게 신고하세요.
- 상위 프로젝트 Nostr Mail Client. 단, Herkos에서 변경한 부분에 특유한 문제라면 대상입니다.
- 이미 알려진 한계로 문서화한 보강 미비(아래 참조).
알려진 한계, 솔직하게
이것들은 취약점이 아니라 설계상의 절충입니다. 누군가 어렵게 알아내기보다 미리 적어 두는 편을 택했습니다:
- 기존 주소로 보내는 메일은 종단 간 암호화되지 않습니다. Nostr 사용자 사이의 메시지는 NIP-17 기프트 랩을 사용하며 종단 간 암호화됩니다. 일반 이메일 주소로 보내면 브리지가 메시지를 변환하며 내용을 읽을 수 있습니다.
- 앱 잠금(PIN과 생체 인식)은 편의를 위한 장벽이지 저장 데이터 암호화가 아닙니다. 잠금이 풀린 기기를 집어 든 사람은 막지만, 기기나 그 저장소에 완전히 접근할 수 있는 공격자로부터는 보호하지 못합니다.
- Windows에서는 생체 인식만으로 인증하도록 강제할 수 없습니다. Windows Hello는 인증 방식을 고르게 해 주지 않으므로, 시스템 PIN이 항상 대체 수단으로 남습니다.
- 키를 잃으면 계정을 잃습니다. 복구는 설계상 없습니다.
- 메타데이터가 완전히 숨겨지지는 않습니다. 릴레이는 연결 패턴을 관찰할 수 있고, 메시지 내용을 읽지 못하더라도 모든 릴레이가 여러분의 IP 주소를 봅니다. Herkos가 (2026년 9월 30일부터) 내주지 않는 것은 릴레이가 NIP-42 인증을 요구할 때 누가 누구에게 쓰는지입니다:
- 배달할 곳 조회. 수신자의 릴레이 목록과 Blossom 목록은 여러분을 절대 식별하지
않는 별도 연결로 요청하며, 먼저 인증을 요구하지 않는 릴레이(
purplepag.es,user.kindpag.es,nos.lol,offchain.pub)에 묻습니다. - 프로필과 예약 발송기. 다른 사람에게 표시되는 이름과 사진(kind 0), 그리고 이메일을 예약하거나 취소할 때 예약 DVM의 릴레이 목록도 같은 방식으로 요청합니다. 먼저 익명으로, 릴레이가 고집하면 아래에 설명하는 임시 키로 묻고, 여러분의 키는 절대 쓰지 않습니다(2026년 10월 1일부터. 그 전에는 인증을 요구한 릴레이가 여러분의 키를 받아, 여러분이 누구의 프로필을 보고 있는지 알 수 있었습니다). 여러분 자신의 프로필만 여전히 여러분으로서 읽습니다.
- 배달. 기프트 랩은 같은 별도 연결로 수신자의 DM 릴레이에 갑니다. 그중 하나가 인증을 요구하면 Herkos는 여러분의 키가 아니라 이 용도로 만들어 메모리에만 두는 키로 응답합니다. 기기의 계정마다 각자의 키가 있습니다. 릴레이는 여전히 한 세션 동안 같은 기기(같은 IP, 같은 임시 키)가 여러 봉투를 보냈다는 것은 볼 수 있습니다.
- 큰 이메일. 32 KB를 넘는 이메일의 암호화된 사본은 수신자의 서버를 포함한 Blossom 서버에 업로드됩니다. 여러분 자신의 서버(여러분의 Blossom 목록)만 여러분의 키로 업로드 권한을 받습니다. 그 밖의 서버는 익명으로 받고, 권한을 고집하면 위와 같은 임시 키로 서명한 권한을 받습니다(2026년 10월 1일부터. 그 전에는 모든 서버가 여러분의 키를 받았습니다). 알려진 키만 받는 서버는 이를 거부하며, 사본은 다른 서버에 남습니다.
- 여러분 자신의 데이터. 사서함, 라벨, 설정, 임시보관함을 동기화할 때는 릴레이가 요구하면 계정을 전환하는 중에도 그 데이터의 주인인 계정으로 인증합니다. 여러분 자신의 릴레이에는 이미 알던 것 이상을 알려 주지 않습니다. 요청에 어차피 여러분의 키가 들어 있기 때문입니다. 여러분 자신의 릴레이 목록과 Blossom 목록은 공개되어 있으며 여러분을 식별하지 않고 요청합니다. 이메일 링크에 지정된 릴레이도 마찬가지입니다.
- 읽음 상태와 폴더는 (현재로서는) 공개 메타데이터입니다. 이메일을 읽음, 별표, 보관으로 표시하거나 옮기면 공개키에 묶인 암호화되지 않은 NIP-32 라벨 이벤트가 게시되며, 사용자 폴더 이름도 포함됩니다. 여러분에게 보낸 이메일의 id를 아는 발신자는 여러분이 언제 그 이메일에 조치했는지 알 수 있습니다. 이 라벨의 암호화는 계획되어 있으며, 그때까지는 폴더 이름을 공개된 것으로 생각하세요.
- 푸시 알림과 예약 발송은 제3자 서비스를 이용합니다. 푸시 서버(기본값
api.nmail.li)는 여러분의 공개키, 푸시 토큰, 메일을 받는 시각을 알게 됩니다. 예약 DVM은 공개키와 게시해야 할 이미 암호화된 메시지를 알게 됩니다. 둘 다 직접 켜야 하며PRIVACY.md에 문서화되어 있습니다. 푸시 알림의 문구는 푸시 서버가 정하며, Herkos는 UnifiedPush가 그것을 암호화해 전달할 때(RFC 8291)만 신뢰합니다. 암호화되지 않은 페이로드는 앱을 깨워 메일을 직접 가져오게 할 뿐입니다. - 웹 버전은 키를 브라우저에 두며, 그곳은 키를 두기에 가장 약한 곳입니다. 설치한 앱은 비밀키를 운영체제의 보안 저장소(Android 키스토어, Windows 자격 증명 관리자, libsecret, iOS/macOS 키체인)에 맡깁니다. 브라우저에는 그런 것이 없습니다. 키는 출처(origin)의 저장소에 있고 서명할 때마다 JavaScript를 거치므로, 페이지에서 실행되는 모든 코드(모든 사이트에 접근할 수 있는 브라우저 확장 프로그램, 앱이나 의존성의 XSS 버그, 변조된 배포)와 브라우저 프로필을 복사하는 정보 탈취 악성코드의 손이 닿는 곳에 있습니다. 또한 코드를 한 번 검증하는 순간도 없습니다. 서명된 바이너리는 설치할 때 확인되지만, 웹 페이지는 방문할 때마다 새 코드를 내보냅니다. 웹 버전에는 원격 서명기(NIP-46 벙커, Amber)로 로그인해 키가 브라우저에 닿지 않게 하거나, 버려도 되는 신원으로 여기고 진짜 키는 설치한 앱에 두세요.
- 브리지를 거친 메일은 브리지만큼만 믿을 수 있습니다. Herkos는 브리지를 통해
왔다고 표시된 메시지가 실제로 여러분이 설정한 브리지(또는 기본값 중 하나)의
서명을 받았는지 확인합니다. 브리지가 전달하는 기존
From:주소에 대해서는 아무것도 확인할 수 없습니다. - 첨부파일은 운영체제가 엽니다. Herkos는 실행 파일이나 스크립트 형식은 절대 실행하지 않으며, 미리 볼 수 없는 그 밖의 첨부파일은 시스템 기본 앱에 넘기기 전에 묻습니다. 하지만 파일을 여는 앱은 우리가 통제할 수 없습니다.
지원 버전
보안 수정은 가장 최근에 릴리스된 버전에 적용됩니다. 프로젝트 규모상 이전 버전은 유지 관리하지 않으니, 신고하기 전에 업데이트해 주세요.