TL;DR
pgvector 0.8.7은 0.8.6 이하의 IVFFlat 인덱스 빌드에서 차원 불일치 벡터가 백엔드 메모리 범위를 벗어나 쓰게 해 임의 코드 실행으로 이어질 수 있는 CVE-2026-103484를 수정함.- 취약점은 테이블 소유자에게 필요한
CREATE INDEX권한뿐 아니라REINDEX와 PostgreSQL 17 이후의MAINTAIN권한 또는pg_maintain역할을 통해서도 도달할 수 있음. - pgvector에서는 2026년에 인덱스 빌드 코드의 메모리 안전성 취약점이 세 번째로 발견됐으며, 서로 다른 원인의 취약점이 크기 메타데이터를 다루는 빌드 코드에 집중됨.
- 새 패키지 설치만으로는 충분하지 않으며, 이전 공유 라이브러리를 불러온 기존 백엔드와 연결 풀 서버 연결을 재순환해야 수정된 코드가 적용됨.
- 소스 빌드와 PGDG 패키지 사용자는 릴리스 페이지가 아닌
v0.8.7태그를 확인해야 하며, 관리형 서비스 사용자는 제공자에게 버전과 배포 일정을 확인해야 함.
무엇이 잘못됐나
- IVFFlat 인덱스 빌드는 테이블에서 표본을 추출하고, 표본에 k-means를 적용해 리스트 중심을 정한 뒤, 각 행을 가장 가까운 중심에 배정함.
- 인덱스의 차원 수는 열의 형식 수정자(type modifier)에 지정된 값에서 가져옴. 예를 들어
vector(1536)의 차원 수는 1536이며, 빌드 과정은 이에 맞춰 작업 배열 크기를 정함. - 수정 전에는 k-means 단계에서 표본 벡터를 배열에 더할 때 반복 범위를 각 벡터의 자체 헤더에서 가져옴. 벡터의 차원 수가 형식 수정자와 다르면 배열 끝을 넘어 계속 기록함.
- 수정 사항은 인덱스의 차원 수를 k-means 단계에 전달하고 모든 벡터가 그 차원 수와 일치하는지 확인함. 또한 IVFFlat과 HNSW가 벡터를 받는 빌드, 삽입, 스캔 경로 모두에 같은 검사를 추가함.
- 보안 권고문은 공격자가 형식 수정자와 일치하지 않는 벡터를 어떻게 전달하는지 설명하지 않음.
- 확장(extension)을 작성한다면 형식 수정자는 열에 대한 선언이지, 접근 방식(access method)이 전달받는 바이트의 속성이 아님을 유의해야 함. C 코드에서 한 값을 기준으로 버퍼 크기를 정하고 다른 값을 기준으로 반복문을 실행하면 취약점이 발생할 수 있음.
올해 세 번째 취약점
- CVE-2026-3172는 2월
0.8.2에서 수정됐으며, 병렬 작업자를 사용하는 HNSW 인덱스 생성 또는 재인덱싱 권한이 있는 사용자가 도달할 수 있는 병렬 HNSW 빌드의 정수 래핑(integer wraparound) 문제임. 데이터 유출이나 충돌을 일으킬 수 있음. - CVE-2026-18022는 7월
0.8.6에서 수정됐으며, 32비트 시스템의 IVFFlat 빌드에서 발생하는 정수 래핑 문제로 범위를 벗어난 쓰기로 이어짐. - CVE-2026-103484는
0.8.7에서 수정된 이번 취약점이며, 32비트 시스템으로 한정되지 않음. - 세 취약점은 발생 원인이 다르지만 모두 인덱스 빌드 코드 영역에 속함. 빌드 코드는 쿼리마다 실행되는 대신 인덱스마다 한 번 실행돼 스캔 경로보다 훨씬 적게 실행되며, 메타데이터에서 파생된 크기를 바탕으로 많은 산술 연산을 수행함.
- 벡터 확장에 퍼저(fuzzer)를 적용한다면 빌드 코드가 우선 대상임. 이번 취약점은 Compass Security 소속 연구자 네 명이 발견함.
권한으로 여겨지지 않는 권한
- IVFFlat 인덱스 생성 권한이 있는 데이터베이스 사용자는 적어 보일 수 있지만,
CREATE INDEX에는 테이블 소유권이 필요하고 많은 애플리케이션은 마이그레이션 프레임워크가 사용하는 역할로 데이터베이스에 연결함. 따라서 해당 역할은 애플리케이션 자체와 애플리케이션을 통해 SQL을 실행할 수 있는 주체를 포함할 수 있음. REINDEX도 같은 빌드 코드를 통해 인덱스를 다시 생성하므로 대상 권한에 포함됨. PostgreSQL 17부터는MAINTAIN권한 또는 미리 정의된pg_maintain역할을 통해 소유 객체가 없는 역할에도 이 권한을 부여할 수 있음.- 2월 보안 권고문은 재인덱싱을 명시적으로 언급함. 어떤 역할에 관련 권한이 있는지 확인해야 함.
- 지속적인 해결책은 스키마 소유권을 가진 마이그레이션 역할과
SELECT,INSERT,UPDATE,DELETE만 가진 애플리케이션 역할을 분리하는 것임. 기존 시스템에 적용하기는 번거롭지만, 애플리케이션 역할 자체가 이 취약점에 노출되는지 여부를 가르는 차이임.
제대로 업그레이드하기
- 수정 사항은 벡터 공유 라이브러리에 있으므로, 이전 라이브러리를 불러온 백엔드는 종료될 때까지 이전 코드를 계속 실행함. 연결 풀의 연결은 며칠 동안 유지될 수 있음.
- 새 패키지를 설치한 뒤에는 패키지가 설치되기 전에 시작한 모든 백엔드를 재순환해야 함.
pg_stat_activity에서backend_type = 'client backend'인 항목 중backend_start가 패키지 설치 시각보다 이른 프로세스를 확인하면 됨. 예시 기준 시각은2026-10-05 09:00:00-07임. - 필요하면
pg_terminate_backend()로 백엔드를 종료할 수 있음. PgBouncer를 사용한다면 관리 콘솔에서RECONNECT를 실행해 각 서버 연결이 반환될 때 닫을 수 있으며, 그렇지 않으면 기본값이 3600초인server_lifetime에 따라 연결이 순차적으로 종료됨. vector를shared_preload_libraries에 넣었다면 서버를 재시작해야 함. 이 설정은 필수 사항이 아님.pg_extension.extversion은 실행된 SQL 스크립트 버전을 나타낼 뿐, 각 백엔드가 어떤 라이브러리를 매핑했는지는 증명하지 않음.
소스 빌드 또는 PGDG 패키지를 사용하는 경우
- 실제 설치 버전이
0.8.7인지 확인해야 함.v0.8.7태그의 변경 기록에는 릴리스 날짜가 10월 1일로 기재돼 있지만,master브랜치의 변경 기록은0.8.7을 아직 미출시 상태로 표시하며 오버플로 문제도 언급하지 않음. - pgvector는 GitHub 릴리스가 아니라 Git 태그를 게시하므로, GitHub의 Releases 페이지를 감시하는 알림에는 릴리스가 표시되지 않음. 태그를 확인해야 함.
관리형 서비스를 사용하는 경우
- 실제 실행 버전과 배포 시점은 서비스 제공자가 제공하는 내용과 일정에 따름. 제공자에게 현재 버전과
0.8.7배포 시점을 문의하고, 업데이트 전까지 인덱스를 생성할 수 있는 역할을 면밀히 확인해야 함.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요