Security · · 5 min read

CVE-2026-102999 | pypdf: 첨부 파일 매핑의 반복 탐색으로 인한 처리 지연

pypdf의 사전 기반 첨부 파일 API가 내용 조회마다 전체 목록을 다시 탐색하던 문제입니다. 반복 탐색의 원인과 6.19.0의 객체 매핑 개선, 공식 회귀 테스트를 정리합니다.

#Security #CVE-2026-102999 #pypdf #Python #PDF #DoS #Responsible Disclosure

요약

직접 제보한 pypdf 첨부 파일 처리 문제에 CVE-2026-102999가 배정되었습니다. 공식 보안 권고에는 GitHub 계정 jungmingi-lab이 제보자(Reporter)로 기록되어 있습니다.

이 문제는 PDF에 포함된 다수의 첨부 파일을 사전 기반 API로 접근할 때 처리 시간이 길어질 수 있는 가용성 취약점입니다. pypdf 6.19.0에서 첨부 파일 목록의 반복 탐색을 줄이는 수정이 반영되었습니다.

| 항목 | 내용 | | --- | --- | | CVE | [CVE-2026-102999](https://www.cve.org/CVERecord?id=CVE-2026-102999) | | 공개 권고 | [GHSA-v247-6f48-mgcj](https://github.com/py-pdf/pypdf/security/advisories/GHSA-v247-6f48-mgcj) | | 영향 구성요소 | 사전 기반 첨부 파일 매핑 API | | 심각도 | Medium | | 분류 | CWE-400: Uncontrolled Resource Consumption · CWE-407: Inefficient Algorithmic Complexity | | 영향 버전 | pypdf < 6.19.0 | | 수정 버전 | pypdf 6.19.0 이상 | | 수정 PR | [py-pdf/pypdf #4081](https://github.com/py-pdf/pypdf/pull/4081) | | 제보자 | jungmingi-lab |

영향 범위

공식 권고는 사전 기반 API를 통한 첨부 파일 접근을 영향 조건으로 명시합니다. 따라서 pypdf 설치 여부만으로 실제 서비스의 영향을 판단하기보다는, PDF 처리 과정에서 첨부 파일의 내용을 조회하는지 확인해야 합니다.

첨부 파일 추출, 문서 보관, 첨부 자료 검사처럼 외부 PDF의 내장 파일을 처리하는 작업이 검토 대상입니다. 이러한 처리를 요청 응답 안에서 동기적으로 수행하면 응답 지연으로 이어질 수 있고, 작업 큐에서는 처리 지연이 누적될 수 있습니다. 서비스 차원의 영향은 작업 시간 제한, 동시 실행 수, 프로세스 격리 방식에 따라 달라집니다.

위 서비스 사례는 공식 권고의 조건을 운영 환경에 적용한 설명입니다. 모든 PDF 읽기 작업이나 텍스트 추출 경로가 이 취약점의 영향을 받는다는 의미는 아닙니다.

기술적 원인

사전처럼 보이는 인터페이스라도 내부에서 값을 찾는 비용까지 일반적인 사전 조회와 같다고 보장되지는 않습니다. 기존 구현은 첨부 파일 이름을 먼저 수집하고, 실제 내용이 필요해지면 해당 이름에 맞는 파일을 다시 찾는 지연 조회 방식을 사용했습니다.

[수정 PR 설명](https://github.com/py-pdf/pypdf/pull/4081)에 따르면, 매핑을 순회하는 동안 각각의 내용 조회가 전체 첨부 파일 목록을 다시 파싱했습니다. 이름과 실제 첨부 객체의 연결을 보관하지 않아, 앞서 읽었던 구조를 여러 번 탐색하게 된 것입니다.

이 구조에서는 개별 조회 비용과 조회 횟수가 함께 누적됩니다. 목록을 한 번 다루는 것으로 보이는 상위 작업이 내부에서는 반복적인 전체 탐색을 수행하므로, 첨부 파일 수가 늘 때 처리 비용이 더 빠르게 증가할 수 있습니다.

이 설명은 공개된 수정 전후 코드의 구조에 근거한 분석입니다. 이 글에서는 별도의 실행 시간이나 메모리 사용량을 측정하지 않았습니다.

수정 내용

pypdf 6.19.0에 포함된 PR #4081은 첨부 파일 이름과 EmbeddedFile 객체 목록의 연결을 먼저 구성하도록 변경했습니다. 이후 내용을 가져올 때는 이미 연결된 객체를 사용합니다.

| 구분 | 수정 전 | 수정 후 | | --- | --- | --- | | 매핑 구성 | 이름에 내용 조회 작업을 연결 | 이름에 해당 첨부 객체 목록을 연결 | | 내용 조회 | 전체 목록에서 이름을 다시 탐색 | 연결된 객체의 내용에 접근 | | 반복 처리 | 전체 목록 탐색이 중복됨 | 동일 매핑 내 중복 탐색을 줄임 | | 동일 이름의 첨부 파일 | 조회 과정에서 일치 항목 수집 | 이름별 객체 목록에 함께 보관 |

공개 패치에서는 pypdf/_doc_common.py의 매핑 구성을 정리하고, pypdf/generic/_files.py에 첨부 파일의 기본 이름과 대체 이름을 다루는 로직을 모았습니다. 내용은 필요한 시점에 읽는 구조를 유지하면서, 이름으로 파일을 다시 찾는 비용을 줄였습니다.

이 수정은 첨부 파일 개수에 새로운 상한을 두는 방식이 아닙니다. 따라서 반복 탐색이 제거되더라도 파일 내용 읽기와 압축 해제 등에 필요한 비용은 남으며, 서비스의 자원 제한은 별도로 적용해야 합니다.

공식 회귀 테스트에서 확인하는 동작

PR #4081에는 하나의 첨부 파일 매핑을 순회할 때 전체 목록 로더가 한 번만 호출되는지 확인하는 테스트가 추가되었습니다. 반환된 이름과 내용도 함께 검사해, 조회 비용 개선과 기능 보존을 동시에 확인합니다.

관련 테스트 변경에서는 다음 동작도 다룹니다.

  • 첨부 파일이 없는 문서는 빈 매핑 반환
  • 일반 첨부 파일의 이름과 내용 유지
  • 기본 이름과 대체 이름을 통한 접근 유지
  • 같은 이름을 가진 여러 첨부 파일의 내용을 목록으로 반환

이는 공식 PR에 포함된 테스트의 내용을 검토한 기록입니다. 이 글 작성 과정에서 pypdf의 회귀 테스트를 별도로 실행한 것은 아닙니다.

운영 환경의 대응

이 취약점의 수정이 포함된 최소 버전은 pypdf 6.19.0입니다. 공식 권고는 업그레이드가 어려운 경우 [PR #4081](https://github.com/py-pdf/pypdf/pull/4081)의 변경 사항 적용을 대안으로 안내합니다.

운영 환경에서는 실제 배포된 의존성 버전을 확인하고, 업데이트 후 정상 문서의 첨부 파일 이름·내용·중복 이름 처리가 유지되는지 점검하는 것이 좋습니다. 외부 PDF를 처리하는 작업에는 실행 시간과 메모리 제한을 적용하고, 장시간 실행되는 작업을 중단할 수 있도록 구성해야 합니다.

공개 타임라인

| 시점 | 확인된 내용 | | --- | --- | | 2026-09-14 | 수정 PR #4081 병합 | | 2026-09-16 | 수정이 포함된 pypdf 6.19.0 릴리스 및 GHSA 공개 | | 2026-10-01 | 공식 권고의 CVE 배정 정보를 확인하고 기술 기록 작성 |

마지막 날짜는 사이트 반영일이며, CVE의 정확한 배정일을 뜻하지 않습니다.

참고 자료

  • [GHSA-v247-6f48-mgcj: Possible long runtimes with large amount of embedded files](https://github.com/py-pdf/pypdf/security/advisories/GHSA-v247-6f48-mgcj)
  • [pypdf PR #4081: Reduce number of full data lookups for attachment mapping API](https://github.com/py-pdf/pypdf/pull/4081)
  • [pypdf 6.19.0 릴리스](https://github.com/py-pdf/pypdf/releases/tag/6.19.0)
  • [pypdf CVE 3건 배정 내역](/writeups/pypdf-cve-assignments/)
정민기 연구 및 기술 기록으로 돌아가기