
PostgreSQL의 전문 검색(tsvector/tsquery)에서 발견된 범위 밖 쓰기 취약점 CVE-2026-14662를, 수정 전(18.4)과 수정 후(18.6)를 Docker로 나란히 실행하여 검증한 기록과 발표 자료
PostgreSQL의 전문 검색 데이터 타입(tsvector / tsquery)에서 발견된
CVE-2026-14662에 대해,
수정 전(18.4)과 수정 후(18.6)를 Docker로 동시에 실행하여 동작 차이를 실제로 관측한 기록입니다.
보안 학습용으로 정리한 것으로, 발표 자료도 포함되어 있습니다.
| 항목 | 내용 |
|---|
| CVE | CVE-2026-14662 |
| 대상 | PostgreSQL의 tsvector / tsquery |
| 종류 | 정수 랩어라운드로 인한 할당 크기 부족 및 범위 밖 쓰기 |
| CVSS | 8.8 / 10.0 (High) |
| 공개일 | 2026-08-13 |
| 수정 버전 | 18.5, 17.11, 16.15, 15.19, 14.24 |
약점의 연쇄는 다음과 같은 형태입니다.
CWE-190(정수 오버플로) → CWE-131(버퍼 크기의 잘못된 계산) → CWE-787(범위 밖 쓰기)
=근본 원인 =최종적 영향
.
├── docs/
│ └── presentation.md 발표 자료(취약점 해설 + CWE 해설)
└── docker/
├── README.md 재현 환경 사용법
├── docker-compose.yml
├── init/ 양쪽 버전에 적용하는 공통 초기화 SQL
├── test/ PoC 및 데모용 SQL
└── run.sh 시작 → PoC 실행 → 결과 표시
Docker와 Docker Compose가 있으면 아래 명령만으로 재현할 수 있습니다.
cd docker
./run.sh
18.4와 18.6의 컨테이너가 시작되고, 동일한 초기화 SQL을 적용한 뒤 같은 PoC를 양쪽에 실행하여 결과를 나란히 표시합니다. 자세한 내용은 docker/README.md를 참조하세요.
| 테스트 | PostgreSQL 18.4(수정 전) | PostgreSQL 18.6(수정 후) |
|---|---|---|
| tsquery의 자기 OR 결합 반복 | 18회까지 오류 없이 성공(최종 8,650,748 바이트) | 17회째에 ERROR: tsquery is too large |
| 총 길이 1,200,000 바이트의 단어 배열 | 성공해 버림 | ERROR: string is too long for tsvector (1200000 bytes, max 1048575 bytes) |
| 3,000 바이트 단어 1개 | 성공해 버림 | ERROR: word is too long (3000 bytes, max 2046 bytes) |
수정 전에는 내부 표현의 상한(20비트 비트필드에서 유래하는 MAXSTRPOS = 1,048,575)을
초과하는 데이터를 오류 하나 없이 수용해 버립니다.
또한 18.6이 "정확히 17회째"에서 멈추는 이유는 계산으로 설명할 수 있으며, 이론값과 실측값이 바이트 단위로 일치함을 확인했습니다(자세한 내용은 발표 자료).
차이 확인에는 PostgreSQL 공식 리포지토리의 클론을 사용했지만, 용량이 크므로(각 185MB) 본 리포지토리에는 포함하지 않았습니다. 필요한 경우 다음과 같이 취득하세요.
git clone --branch REL_18_4 --depth 1 https://github.com/postgres/postgres.git postgres-18.4
git clone --branch REL_18_6 --depth 1 https://github.com/postgres/postgres.git postgres-18.6
수정이 들어간 파일은 다음 3개입니다.
src/backend/utils/adt/tsquery_util.csrc/backend/utils/adt/tsvector.csrc/backend/utils/adt/tsvector_op.c