flawopen.com/ReDoS/JavaScript RegExp
JavaScript RegExp는 ReDoS에 취약할까?
마지막 표시가 빠진 서류 더미를 담당자가 나눌 수 있는 모든 방식으로 다시 시도한다고 생각해 보세요. 모호한 패턴은 정규식 엔진이 같은 문자를 반복해서 살펴보게 만듭니다. V8의 일반 RegExp 경로는 이렇게 역추적할 수 있습니다. 입력 길이를 제한하고 작업량을 예측할 수 있는 패턴을 쓰면 비용을 제한합니다. Node에서는 동기식 매칭이 event loop 스레드에서 실행되어 같은 프로세스의 다른 callback을 지연시킵니다. V8 문서는 플래그로 활성화하는 실험적 non-backtracking 엔진을 설명하며 패턴 제한도 있습니다. 운영 Node에서 활성화되어 있다고 가정하지 마세요.
// 요청 데이터에 모호한 중첩 반복 사용
const re = /^(\w+\s?)*$/;
app.post('/search', (req, res) => {
const q = req.body.q;
if (!re.test(q)) return res.sendStatus(400);
res.sendStatus(200);
});
// 입력을 제한하고 필드 문법만 허용
app.post('/search', (req, res) => {
const q = req.body.q;
if (typeof q !== 'string' || q.length > 128)
return res.sendStatus(400);
// 예시 문법: ASCII 단어 문자와 공백만
if (!/^[\w ]{1,128}$/.test(q))
return res.sendStatus(400);
res.sendStatus(200);
});
Node.js에서 ReDoS 영향이 커지는 이유
동기식 정규식 매칭은 Node.js 프로세스의 callback을 처리하는 JavaScript 스레드에서 실행됩니다. 패턴이 거의 일치하거나 실패하는 입력에서 오래 걸리면 매칭이 끝날 때까지 event loop는 다른 callback을 실행하거나 요청을 진행할 수 없습니다. Worker, 여러 프로세스 또는 복제본이 일부 용량을 유지할 수 있지만 영향을 받은 프로세스는 여전히 멈출 수 있습니다.
영향은 도달 가능성, 패턴 복잡도, 입력 제한, 배포 구성에 달려 있습니다. 공격자는 비용이 큰 경로를 유발하는 입력으로 취약한 매칭에 도달해야 합니다. 영향을 받은 프로세스의 가용성 위험으로 취급하고 전체 서비스 영향은 worker, 복제본, 라우팅, 상태 확인을 고려하세요.
npm 실제 사례: xmldom CVE-2026-83606
@xmldom/xmldom의 검토된 advisory는 processing-instruction 파싱에서 CWE-1333을 보고합니다. 취약한 문법에서는 greedy 공백 그룹과 lazy 데이터 그룹이 같은 공백을 소비할 수 있습니다. 닫는 ?>가 없으면 파서가 여러 분할을 시도해 시간이 제곱 수준으로 늘어납니다. 0.9.0-beta.9부터 0.9.10까지 영향받으며 0.9.11은 구분자가 공백을 데이터 그룹에 돌려주지 않도록 수정했습니다. advisory는 범위를 scoped 패키지의 0.9.x 경로로 한정하며 0.8.x와 unscoped 패키지는 영향 대상으로 지정하지 않습니다.
의존성 스캔은 도움이 되지만 정규식 안전성 증명은 아니다
npm audit은 프로젝트 의존성 트리와 일치하는 알려진 advisory를 보고합니다. 소스의 모든 정규식을 분석하거나 공개되지 않은 ReDoS를 찾지는 않습니다. 직접 및 전이 의존성을 업데이트하고 영향받는 호출 경로를 확인하며 사용자 제어 텍스트를 처리하는 패턴은 별도로 검토하세요.
npm audit --omit=dev
audit은 알려진 advisory를 다루며 모든 정규식 위험을 다루지는 않습니다. 배포 상황에 맞게 보고서를 검토하고 신뢰할 수 없는 입력이 비용 큰 매칭에 도달하는지와 길이가 제한되는지 별도로 확인하세요.
자주 묻는 질문
RegExp API에는 매칭별 timeout 옵션이 없습니다. 단순한 패턴을 쓰고 매칭 전에 입력을 제한하세요. 복잡한 처리가 필요하면 강제 종료 기한이 있는 worker나 자식 프로세스에 격리하세요. 영향을 제한할 수 있지만 패턴 자체가 효율적으로 바뀌지는 않습니다.
네. 문제 있는 동기식 매칭은 끝날 때까지 페이지의 main thread를 멈춰 UI를 막을 수 있습니다. 입력을 제한하고 패턴을 단순화하며 키 입력마다 무거운 매칭을 실행하지 마세요.
사용자 제공 패턴은 비용이 큰 matcher에 전달되는 실행 입력으로 취급하세요. 엄격한 제한과 격리 없이 서버에서 임의 패턴을 받지 마세요. 문자 그대로 검색하면 입력을 regex literal로 escape하거나 문자열 검색 API를 사용하세요. escape는 길이 제한을 대신하지 않습니다.
참고 자료 및 수정
- GitHub Advisory — @xmldom/xmldom CVE-2026-83606
- xmldom — 0.9.11 릴리스 노트
- Node.js — event loop 차단 금지 (ReDoS)
- V8 — non-backtracking RegExp 엔진 및 한계
- npm — 의존성 감사
- CWE-1333 — 비효율적 정규식 복잡도