Ajv allErrors:true로 인한 리소스 고갈(DoS)

Uncontrolled Resource Consumption (Resource Exhaustion)

설명

Ajv에서 allErrors:true 옵션을 사용하면 검증 실패 시 가능한 모든 에러를 수집합니다. 이 과정에서 매우 많은 에러 객체와 문자열이 생성되고, 스키마의 제약 조건을 끝까지 평가하느라 CPU 사용량이 증가합니다. 공격자는 많은 규칙을 동시에 위반하도록 입력을 조작하거나 거대한/중첩된 JSON을 보내 메모리와 CPU를 과도하게 소모시켜 서비스 거부(DoS)를 유발할 수 있습니다.

잠재적 영향

  • 서비스 거부(DoS): 과도한 에러 수집과 연산으로 CPU/메모리가 고갈되어 응답 지연 또는 프로세스 다운 발생

  • 메모리 고갈: 수천 개의 에러 객체/메시지 생성으로 힙 메모리 급증, OOM 및 재시작 유발

  • 성능 저하: 검증이 끝까지 진행되어 요청 처리 시간이 크게 늘어나 전체 서비스 처리량 감소

  • 로그/모니터링 비용 증가: 대량의 에러 메시지 출력으로 로그가 폭증하고 운영 비용과 가시성 저하

해결 방법

  • 운영(Production)에서는 Ajv 인스턴스 생성 시 allErrors:true를 사용하지 말고 기본값(false, fail-fast)을 유지하세요

  • 디버깅이 필요한 경우에만 개발 환경에서 환경 변수로 제어하세요 (예: DEBUG_VALIDATE=1 일 때만 allErrors:true)

  • 요청 본문 크기 제한(body size limit)과 요청 시간 제한(timeout)을 설정하세요

  • Rate limiting과 Circuit breaker를 적용해 폭주 트래픽을 완화하세요

  • 스키마는 신뢰 가능한 소스만 사용하고, 불필요하게 많은 규칙(oneOf/anyOf 등 과도한 조합)을 피하세요

  • 입력 구조를 상한선으로 제한(maxItems, maxProperties 등)을 정의해 검증 복잡도를 낮추세요

취약한 코드 및 안전한 코드 예시

취약한 코드

안전한 코드

설명:

  • 취약한 코드: allErrors:true는 검증이 실패하더라도 모든 규칙을 끝까지 검사하고 모든 에러를 수집합니다. 공격자가 많은 제약을 위반하도록 입력을 만들면 에러 객체가 대량 생성되어 CPU/메모리를 고갈시키고, DoS로 이어질 수 있습니다.

  • 안전한 코드: 기본값(fail-fast)으로 설정해 첫 오류에서 즉시 중단하여 에러 수와 연산량을 최소화했습니다. 또한 allErrors는 개발 환경에서만 환경 변수로 제한적으로 활성화하고, 입력 크기/시간 제한 및 스키마의 상한(maxItems/maxLength)을 통해 검증 복잡도를 제어하여 리소스 고갈 가능성을 줄였습니다.

참조

Last updated