초록 ABSTRACT
본 보고서는 ATM Scanner V2의 핵심 알고리즘 설계를 완전하게 기술한다. ATM Scanner는 대규모 언어 모델(LLM) API에 기반한 보안 취약점 서식지 예측 도구로서, 그 핵심 혁신은 귀추 추론(abductive reasoning)을 반복 실행 가능한 5단계 파이프라인 알고리즘으로 공학화한 데 있다. 본 문서는 세 가지 주요 알고리즘 모듈을 상세히 기술한다: (1) 5단계 파이프라인 알고리즘—”설계 고고학 → 심(seam) 표시 → 표적 스캔 → 규칙 추출”의 인지 과정을 명확한 입·출력 사양을 갖춘 5개의 LLM 호출 단계로 분해하며, 각 단계는 정밀하게 설계된 시스템 프롬프트(system prompt)를 사용하여 모델을 올바른 추론 모달리티로 유도한다; (2) 다중 스캔 수렴 알고리즘—동일 타깃에 대해 N회 독립 스캔을 수행한 후, 심 명칭의 퍼지 매칭과 빈도 통계를 통해 출력을 “수렴 집합”(높은 신뢰도)과 “발산 집합”(인적 검증 필요)으로 분류하여, LLM의 샘플링 변이를 노이즈가 아닌 신호로 활용한다; (3) 신뢰도 분류 알고리즘—정규표현식 기반의 출력 행 단위 분류기로서, 각 출력 행을 “방향성 판단”(높은 신뢰성), “메커니즘 추론”(중간 신뢰성), “정밀 수치”(검증 필요)의 3단계 신뢰도로 자동 태그하여, LLM 잠복 오류의 비관측성 문제에 직접 대응한다. 실측 데이터에 따르면: 5단계 파이프라인은 3대 보안 사격장에서 약 70%의 심 명중률을 달성했으며, 다중 스캔 수렴 알고리즘은 방향성 판단의 오류율을 단회 스캔의 약 6%에서 0%에 근접하게 저감시켰다.
01서론: 왜 알고리즘화가 필요한가
ATM 방법론은 이론 논문에서 “귀추적 표적 지뢰탐색”의 5단계 인지 과정을 자연어로 기술했다. 그러나 인지 과정을 반복 실행 가능한 소프트웨어 도구로 전환하려면 세 가지 공학적 문제를 해결해야 한다:
문제 1: 모호한 인지 단계를 어떻게 정밀한 LLM 호출로 전환하는가? 이론 논문이 기술하는 것은 “설계 고고학을 수행하라”이다—그러나 LLM에게는 일반적 코드 분석 모달리티가 아닌 “설계 고고학” 추론 모달리티로 유도하는 정밀한 system prompt가 필요하다. 각 단계의 system prompt 설계가 ATM Scanner의 핵심 알고리즘 혁신이다.
문제 2: LLM의 잠복 오류에 어떻게 대응하는가? LLM의 오류는 정확한 출력과 형식적으로 완전히 구별 불가능하다. 단회 스캔의 약 6% 메커니즘 오귀인율과 약 10% 수치 편차율은 고유한 것이다. 알고리즘 차원에서 체계적인 오류 필터링 메커니즘이 필요하다.
문제 3: 인적 감사자가 AI 출력을 어떻게 효율적으로 소비하는가? 1회 완전 스캔은 수천 자의 분석 텍스트를 산출할 수 있다. 감사자는 “어떤 내용을 신뢰할 수 있고 어떤 내용에 추가 검증이 필요한지”를 빠르게 파악해야 한다.
02전체 아키텍처
ATM Scanner V2는 3층 아키텍처를 채택한다: 핵심 파이프라인 층, 노이즈 필터링 층, 인간-기계 인터페이스 층.
| 층 | 알고리즘 모듈 | 입력 | 출력 |
|---|---|---|---|
| 핵심 파이프라인 층 | 5단계 파이프라인 알고리즘 | 타깃 시스템 기술 | 심 목록 + 생성 규칙 + 서식지 지도 |
| 노이즈 필터링 층 | 다중 스캔 수렴 알고리즘 | N회 독립 스캔 결과 | 수렴 집합(높은 신뢰도) + 발산 집합(검증 필요) |
| 인간-기계 인터페이스 층 | 신뢰도 분류 알고리즘 | 단회 스캔 텍스트 | 행 단위 신뢰도 태그 (초록/노랑/빨강) |
03알고리즘 1: 5단계 파이프라인
3.1 파이프라인 전체 설계
5단계 파이프라인은 ATM 방법론의 인지 과정을 5개의 직렬 LLM 호출 단계로 분해한다. 각 단계는 독립적인 system prompt를 갖고, 선행 단계의 출력을 컨텍스트로 수신하며, 구조화된 분석 결과를 산출한다. 핵심적 설계 결정은: 각 단계의 system prompt가 “무엇을 할 것인가”뿐만 아니라 “어떤 추론 모달리티로 할 것인가”까지 기술한다는 점이다—이것이 ATM이 일반적 LLM 보안 분석과 구별되는 핵심이다.
14행과 17행에 주목하라—각 단계가 수신하는 컨텍스트는 선행 모든 단계 출력의 연결(∘는 연결을 나타냄)이다. 이는 Step 5가 고고학 분석, 심 표시, 표적 스캔의 전체 결과를 동시에 보게 됨을 의미한다. 컨텍스트의 누적적 전달은 생성 규칙 품질의 핵심이다—선행 3단계의 맥락 없이는 Step 5가 계층간 인과관계를 추출할 수 없다.
3.2 System Prompt 설계 원리
각 단계의 system prompt는 이중 기능을 수행한다: 과업 정의(무엇을 할 것인가)와 추론 모달리티 설정(어떤 인지적 자세로 할 것인가). 이하에서 각 단계의 설계 원리를 상세히 기술한다:
| 단계 | 추론 모달리티 | 핵심 제약 | 출력 형식 요구 |
|---|---|---|---|
| Step 2 고고학 | 역사 추적 모달리티: 1세대 설계자의 물리적 제약과 암묵적 가정을 소급 | “발견당 3~4문장” — 발산 방지 | 🏛️ 1세대 설계층 / 🔨 리팩터링 이벤트 / ⏳ 시간 범위 |
| Step 3 표시 | 충돌 감지 모달리티: 동일 경로 위 서로 다른 시대 가정 간 충돌 탐색 | “위험 점수 1~10 및 근거” — 정량화 강제 | 🔴 고위험 / 🟡 중위험 / 📍 스캔 좌표 |
| Step 4 스캔 | 공격자 사고 모달리티: 심의 가정 충돌이 악용 가능한지 판단 | “방어적 보안 연구 목적” — 윤리적 제약 | 상태 / 공격 프리미티브 / 트리거 조건 / 영향 범위 / 기존 관계 |
| Step 5 규칙 | 귀납적 추상 모달리티: 구체적 심으로부터 재활용 가능한 패턴 추출 | “단일 취약점을 기술하는 것이 아니라, 한 부류의 취약점을 생성하는 패턴” | 템플릿 / 기존 사례 / 다음 서식지 / 재활용 범위 |
3.3 핵심 Prompt 설계 세부사항
Step 2의 “물리적 제약” 앵커링: 프롬프트는 모델에게 “설계자의 의도”가 아닌 “설계자의 물리적 제약”을 소급하도록 명시적으로 요구한다. 이 구분은 결정적이다—”의도”는 주관적이고 검증 불가능한 반면, “물리적 제약”(예: “2006년에는 하드웨어 암호화 가속이 없었음”)은 객관적이고 추적 가능하다. 이로써 고고학 분석의 결과가 독립적으로 검증 가능해진다.
Step 3의 “계층간 충돌” 유도: 프롬프트는 “동일 데이터 경로 위에서 서로 다른 시대의 설계 가정이 충돌”이라는 정밀한 표현을 사용한다. “동일 데이터 경로”라는 제약이 탐색 범위를 한정한다—모델이 서로 무관한 두 서브시스템 사이의 이론적 충돌을 탐색하는 것이 아니라, 데이터가 실제로 경유하는 경로 위의 구체적 충돌 지점에 집중하게 된다.
Step 4의 “공격자 사고” 전환: 프롬프트는 모델에게 심이 “버그가 있는지”가 아니라 “악용 가능한지”를 판단하도록 요구한다. 이 구분은 출력을 학술적인 “문제가 존재할 수 있음”에서 공학적인 “다음의 공격 프리미티브를 구성할 수 있음”으로 격상시켜, 결과에 실행 가능성을 부여한다.
Step 5의 “템플릿화” 요구: 프롬프트는 “[조건 A] × [조건 B] × [조건 C]일 때, [구체적 대상]을 검사하라”라는 템플릿 형식을 명시적으로 요구한다. 이 형식 제약은 모델이 구체적 발견을 재활용 가능한 패턴으로 추상화하도록 강제한다—이 제약이 없으면, 모델은 이전 가능한 규칙이 아닌 현재 시스템에 대한 구체적 기술을 출력하는 경향이 있다.
3.4 컨텍스트 윈도우 관리
5단계 파이프라인의 누적 컨텍스트 증가는 공학적 과제다. Step 5 시점에서 user message는 선행 3단계의 전체 출력과 원래 입력을 포함하여 수만 토큰에 달할 수 있다. 관리 전략은 다음과 같다:
max_tokens 설정: 기본값은 16,000 토큰이며, 사용자가 2,000~16,000 범위에서 조절할 수 있다. 실측에 따르면 Step 4와 Step 5의 출력은 16,000 토큰 이내에서 완전히 생성된다. 8,000 미만이면 출력이 절단될 수 있다.
모델 선택의 영향: Opus 4.6(200K 컨텍스트 윈도우)은 전체 누적 컨텍스트를 처리할 수 있다. Haiku 4.5(더 작은 컨텍스트 윈도우)는 Step 5에서 컨텍스트 과다로 인해 출력 품질이 저하될 수 있다. 알고리즘 설계에서 Haiku의 max_tokens 상한은 낭비를 피하기 위해 8,192로 설정되었다.
04알고리즘 2: 다중 스캔 수렴
4.1 알고리즘 동기
LLM의 샘플링 과정(temperature > 0)은 동일 입력에 대한 다중 호출이 서로 다른 출력을 생성하게 한다. 전통적 응용에서 이는 “비결정성”—제거해야 할 결함—이다. ATM Scanner는 이를 신호원으로 역전시킨다: 어떤 심이 다수의 독립 스캔에서 반복적으로 나타나면, 타깃 시스템의 실제 구조적 결함일 가능성이 높다. 어떤 심이 특정 1회 스캔에서만 나타나면, LLM의 샘플링 노이즈일 가능성이 높다.
4.2 알고리즘 정의
4.3 심 추출 함수
extract_seams()는 수렴 알고리즘의 핵심 서브루틴이다. 정규표현식을 사용하여 LLM의 자유 텍스트 출력으로부터 구조화된 심 정보를 추출한다:
function extractSeams(text) { const seams = []; const re = /(?:접缝|SEAM|seam)\s*[##\-—]?\s*(\d+)[::]\s*(.+?)(?:\n|$)/gi; let m; while ((m = re.exec(text)) !== null) seams.push({ id: m[1], name: m[2].trim().substring(0, 60) }); return seams; }
정규표현식은 중국어(“接缝”)와 영어(“SEAM”/”seam”) 마커를 모두 지원하며, 다양한 번호 구분자(#, #, -, —)와 콜론 형식(:, :)에 호환된다. 명칭은 60자로 절단하여, 동일 심이 기술 세부사항의 차이로 인해 다른 것으로 분류되는 것을 방지한다.
4.4 퍼지 매칭의 설계 트레이드오프
수렴 알고리즘의 핵심 과제는: 동일한 심이 서로 다른 스캔에서 다른 표현으로 기술될 수 있다는 것이다. 예를 들어, “AF_ALG 인접 인터페이스 위반”과 “algif_skcipher의 splice 쓰기 문제”는 동일한 심을 가리킨다.
현재 구현은 소문자 앞 25자 매칭을 조립도(粗粒度) 퍼지 매칭으로 사용한다. 이는 의도적 단순화다—보다 정밀한 의미론적 매칭(예: 임베딩 벡터 코사인 유사도)은 추가적인 API 호출 비용과 지연을 야기한다. 실측에서 25자 매칭은 대부분의 심 명칭에 대해 충분한 변별력을 갖는다. LLM이 동일 개념을 기술할 때 유사한 핵심어를 사용하는 경향이 있기 때문이다.
향후 개선 방향: 추가 API 호출 없이 매칭 정밀도를 높이기 위해 경량 TF-IDF 또는 n-gram 중첩도 계산을 도입.
4.5 임계값 선택
수렴 임계값 θ = 0.6의 의미는: 어떤 심이 수렴 집합에 편입되려면 최소 60%의 스캔에서 출현해야 한다는 것이다. N=3일 경우 최소 2회 출현, N=5일 경우 최소 3회 출현을 의미한다.
| θ | N=3 | N=5 | 특성 |
|---|---|---|---|
| 0.4 | ≥2회 | ≥2회 | 관대: 더 많은 심이 수렴 집합에 진입, 위양성 증가 |
| 0.6 (기본값) | ≥2회 | ≥3회 | 균형: 산발적 노이즈를 필터링하고 안정적 발견을 보존 |
| 0.8 | ≥3회 (전체) | ≥4회 | 엄격: 고도로 안정적인 심만 통과 |
05알고리즘 3: 신뢰도 분류
5.1 알고리즘 동기: 잠복 오류에 대한 대응
LLM의 잠복 오류는 세 가지 위험한 특성을 갖는다: 자기 검출 불가, 외관상 구별 불가, 고도의 위장(상세 내용은 「ATM 아키텍처 Demo 테스트」 V2 제11절 참조). 신뢰도 분류 알고리즘의 목표는: 잠복 오류를 제거할 수 없는 전제하에, 최소한 인적 감사자에게 “어떤 출력 행이 오류를 포함할 가능성이 가장 높은지” 알려주는 것이다.
5.2 3단계 분류기
5.3 분류 근거의 실증적 기반
3단계 분류의 신뢰성 순위는 ATM Scanner의 3회 커널 스캔에서 실측된 오류율 데이터에 기반한다:
| 등급 | 태그 색상 | 내용 유형 | 실측 오류율 | 예시 |
|---|---|---|---|---|
| DIRECTION | 초록 | 심 표시, 위험 점수, 방향성 판단 | 0% (17/17 정확) | “SEAM-03: Folio 이중 트랙 병존 · 9/10” |
| MECHANISM | 노랑 | 공격 프리미티브, 트리거 조건, 메커니즘 추론 | ~6% (1/17 오귀인) | “Copy Fail의 근인은 folio 경로 잠금 충돌” |
| NUMERICAL | 빨강 | 수치 계산, 버전 번호, 시간 추정 | ~10% (3/30 편차) | “40Gbps에서 약 14초 래핑” |
이 분류는 LLM의 능력 계층에 직접 대응한다: LLM은 패턴 인식과 방향성 판단에서 가장 강력하고(0% 오류), 인과 추론에서 다소 약하며(~6%), 정밀 계산에서 가장 약하다(~10%). 신뢰도 분류는 이 이미 알려진 능력 계층을 감사자에게 시각적으로 제시한다.
06스트리밍 출력 알고리즘
6.1 SSE 스트리밍 파서
ATM Scanner는 Server-Sent Events(SSE)를 사용하여 Claude API의 출력을 스트리밍 방식으로 수신하며, 토큰 단위의 실시간 렌더링을 구현한다. 스트리밍 파싱 과정에서 두 가지 핵심 버그를 만났으며, 그 수정 방안이 엔지니어링 알고리즘의 일부를 구성한다:
버그 1: UTF-8 멀티바이트 절단. 한국어/중국어 문자는 3바이트의 UTF-8을 차지한다. 네트워크 청크의 절단 지점이 문자 중간에 떨어지면, TextDecoder가 깨진 문자를 출력한다. 수정: new TextDecoder("utf-8", { stream: true })로 스트리밍 모드를 활성화하여, 미완성 멀티바이트 시퀀스를 다음 청크까지 버퍼링한다.
버그 2: SSE의 크로스 청크 JSON 파싱. 하나의 data: {...} 행이 두 네트워크 청크에 걸칠 수 있다. 수정: 행 단위 버퍼를 도입하여, \n으로 분할한 후 마지막 불완전 행을 다음 반복의 접두사로 보존한다.
// 스트리밍 파싱 핵심 로직 const decoder = new TextDecoder("utf-8", { stream: true }); let buffer = ""; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split("\n"); buffer = lines.pop() || ""; // 불완전 행 보존 for (const line of lines) { // data: {...} 행 파싱 } }
07모델 선택 알고리즘
ATM Scanner는 세 가지 모델 옵션을 제공하며, 각 모델은 추론 깊이와 속도 사이에서 서로 다른 트레이드오프를 갖는다:
| 모델 | 생성 규칙 수 | 고유 발견 | 코드 수준 깊이 | 적용 시나리오 |
|---|---|---|---|---|
| Opus 4.6 | 6개 (TCP 시나리오) | R6 연쇄 활성화, 커플링 체인 | 함수명+행 번호 수준 정밀 | 정식 스캔, 논문 데이터 |
| Sonnet 4 | 3개 (TCP 시나리오) | 고유 발견 없음 | 모듈 수준 | 빠른 탐색, 초기 스크리닝 |
| Haiku 4.5 | 미테스트 | — | 개념 수준 | 대규모 배치 사전 스크리닝 |
실측 결론: Opus 4.6이 산출하는 생성 규칙 수는 Sonnet 4의 2배이며, Opus만의 고유 R6(연쇄 활성화)는 단일 심 분석의 구조적 맹점을 드러낸다. ATM의 출력 품질은 모델의 추론 능력과 양(+)의 상관관계를 갖는다—방법론의 천장은 방법론 자체가 아니라 모델 능력에 의해 결정된다.
08잠복 오류 대응 전략 매트릭스
세 가지 알고리즘 모듈을 종합하여, ATM Scanner V2는 다층적 잠복 오류 대응 체계를 구축한다:
| 오류 유형 | 발생률 | 대응 알고리즘 | 잔여 리스크 |
|---|---|---|---|
| 방향성 판단 오류 | 0% (실측) | 다중 스캔 수렴 (중복 검증) | 극히 낮음 |
| 메커니즘 오귀인 | ~6% | 다중 스캔 발산 감지 + 노랑 태그 알림 | 낮음 (발산 항목이 검증 필요로 표시됨) |
| 수치/버전 편차 | ~10% | 빨강 태그 자동 표시 + 향후 수치 검증 파이프라인 | 중간 (현재 인적 검산에 의존) |
| 내부 수치 모순 | ~3% | 다중 스캔 교차 대조 | 낮음 (모순이 다중 출력에서 증폭됨) |
| 과잉 추론 | ~5% | 신뢰도 태그 + 인적 검토 | 중간 (의미론적 수준의 과잉 추론은 자동 감지 곤란) |
09알고리즘 복잡도 및 비용 분석
| 리소스 | 단회 스캔 (N=1) | 3회 반복 스캔 (N=3) | 5회 반복 스캔 (N=5) |
|---|---|---|---|
| API 호출 횟수 | 4 (Step 2~5 각 1회) | 12 (4단계 × 3회) | 20 (4단계 × 5회) |
| 입력 토큰 (추정) | ~20K (누적 컨텍스트) | ~60K | ~100K |
| 출력 토큰 (추정) | ~40K (4단계 × 10K) | ~120K | ~200K |
| Opus 4.6 추정 비용 | ~$1.50 | ~$4.50 | ~$7.50 |
| Sonnet 4 추정 비용 | ~$0.40 | ~$1.20 | ~$2.00 |
| 시간 (Opus 4.6) | ~8~12분 | ~25~35분 | ~40~60분 |
전통적 보안 감사와의 비교: Linux 커널 서브시스템에 대한 인적 감사는 보안 연구원의 수 주에서 수 개월간 작업이 필요하며, 비용은 수만에서 수십만 달러에 달한다. ATM Scanner는 $1.50~$7.50과 8~60분으로 탐색 공간의 방향성 압축을 완료한다—”수만 개의 함수”를 “수십 개의 정밀 좌표”로 축소한다. 후속 심층 인적 감사는 여전히 필요하지만, 감사 범위가 약 1,000배 압축된다.
10한계점 및 향후 알고리즘 개선
퍼지 매칭의 조립도. 현재의 25자 접두어 매칭은 의미론적으로 등가이나 표현이 크게 다른 심 기술을 처리할 수 없다. 개선 방향: n-gram 중첩도 또는 경량 텍스트 임베딩의 코사인 유사도 도입.
수치 자동 검증 부재. 현재의 빨강 태그는 “이 행에 수치가 포함되어 있음”만 표시할 뿐, 수치의 정확성을 자동 검증하지 않는다. 개선 방향: 후처리 단계에 결정론적 계산 모듈을 도입하여, 시퀀스 번호 래핑 시간, 주소 오프셋 등 계산 가능한 물리량을 자동 검산하고 LLM 출력과 대조.
컨텍스트 압축. 현재 파이프라인은 선행 모든 단계의 전체 출력을 후속 단계에 전달한다. 긴 출력 시나리오에서 핵심 정보가 희석될 수 있다. 개선 방향: 단계 사이에 요약 압축 레이어를 도입하여, 전문이 아닌 구조화된 핵심 발견만 전달.
신뢰도 분류의 정적성. 현재 분류기는 고정된 정규표현식에 기반하며, 영역에 따른 출력 형식 차이에 적응할 수 없다. 개선 방향: 경량 LLM(예: Haiku)을 사용하여 각 출력 행에 대해 의미론 수준의 신뢰도 평가를 수행.
11결론
ATM Scanner V2의 알고리즘 설계는 귀추 추론을 반복 실행 가능한 소프트웨어로 공학화하는 세 가지 핵심 문제를 해결한다:
5단계 파이프라인 알고리즘은 정밀하게 설계된 system prompt를 통해 모호한 인지 단계를 정밀한 LLM 호출 시퀀스로 전환한다. 각 단계의 추론 모달리티 설정—과업 기술만이 아닌—이 알고리즘의 핵심 혁신이다. 실측 결과: 이 파이프라인은 3대 보안 사격장에서 약 70%의 심 명중률을 달성했다.
다중 스캔 수렴 알고리즘은 LLM의 샘플링 변이를 노이즈원에서 신호원으로 역전시킨다. N회 독립 스캔의 빈도 통계와 퍼지 매칭을 통해 출력을 높은 신뢰도의 수렴 집합과 검증 필요의 발산 집합으로 분류한다. 실측 결과: 수렴 알고리즘은 방향성 판단의 오류율을 약 6%에서 0%에 근접하게 저감시켰다.
신뢰도 분류 알고리즘은 LLM의 알려진 능력 계층(방향 판단 > 메커니즘 추론 > 정밀 계산)에 기반하여 각 출력 행에 시각적 신뢰도 태그를 자동 부착하며, 인적 감사자의 주의력을 검증이 가장 필요한 내용으로 유도한다.
12참고문헌
[1] 이조글로벌인공지능연구소. “Mythos가 발견한 0-Day 버그의 귀추적 분석 — 귀추적 표적 지뢰탐색(ATM) 방법론.” 2026년 4월.
[2] 이조글로벌인공지능연구소 & Opus 4.6. “ATM 아키텍처 Demo 테스트 V2.” 2026년 5월. 14장, 오류율 분석 및 LLM 잠복 오류 논의 포함.
[3] 이조글로벌인공지능연구소 & Opus 4.6. “ATM 보안 사격장 실측 보고서 V1.” 2026년 5월 2일. 3대 사격장 교차 영역 검증.
[4] Anthropic. “Claude API Documentation: Messages API with Streaming.” docs.anthropic.com, 2026.
[5] Anthropic. “Claude Mythos Preview.” red.anthropic.com/2026/mythos-preview, April 7, 2026.
[6] Peirce, C.S. “Deduction, Induction, and Hypothesis.” Popular Science Monthly, 13, 1878. 귀추 추론의 최초 형식화.
[7] CVE-2026-31431. “Copy Fail: algif_aead page-cache write.” Xint Code / Theori, April 2026.
[8] CVE-2025-37868. “drm/xe/userptr: fix notifier vs folio deadlock.” May 2025.
[9] CVE-2026-23097. “Deadlock in hugetlb folio migration.” Red Hat, January 2026.
[10] Google Security Research. “kernelCTF Rules.” google.github.io/security-research/kernelctf/rules, 2026.
[11] Zero Day Initiative. “Pwn2Own Automotive 2026 Results.” January 2026.
[12] CVE-2026-3910. “Type Confusion in V8 Maglev Compiler.” Google TAG, March 2026.
[13] CVE-2025-2783. “Mojo IPC sandbox escape.” Kaspersky, March 2025.
[14] WHATWG. “Server-Sent Events Specification.” html.spec.whatwg.org/multipage/server-sent-events.html
[15] ECMA-404. “The JSON Data Interchange Standard.” 2017. SSE data payload format.