Python Brotli 취약점, import 안 해도 requests를 점검해야 하는 이유
코드 어디에도 import brotli가 없으니 Brotli 취약점 CVE-2026-111497과는 상관없다고 넘기기 쉽다. URL 미리보기처럼 requests로 외부 페이지를 읽는 서비스는 정말 괜찮을까?

- requests는 brotli 또는 brotlicffi가 설치돼 있으면 Brotli 응답을 자동으로 압축 해제한다.
- CVE-2026-111497의 PyPI 수정판은 Brotli 1.2.1과 brotlicffi 1.2.1.0이다.
- 서비스가 쓰는 Python 환경을 점검하고, 수정된 의존성으로 프로세스나 컨테이너를 교체해야 한다.
외부 URL을 읽는 requests도 확인 대상이다
소스 코드에서 import brotli를 찾지 못해도 Brotli 디코더를 사용하고 있을 수 있다. Requests 공식 문서는 brotli나 brotlicffi가 설치된 경우 br 응답을 자동으로 압축 해제한다고 설명한다. 개발자가 직접 압축 해제 함수를 호출하지 않아도 응답을 읽는 과정에서 해당 라이브러리가 쓰인다.
이 때문에 URL 미리보기나 크롤러처럼 외부 서버의 응답을 가져오는 기능도 점검해야 한다. GitHub 보안 권고에 따르면 조작된 Brotli 스트림을 취약한 디코더로 처리하면 메모리 손상, 정보 유출, 서비스 거부, 임의 코드 실행 가능성이 생긴다. Python 웹 프레임워크의 이름만으로 판단할 문제가 아니라, 외부 데이터가 어떤 디코더를 거치는지가 핵심이다.
requests 버전보다 디코더 패키지 버전을 본다
이번 결함의 수정 대상은 Google Brotli 디코더다. PyPI에서는 이를 포함하는 두 패키지의 영향 범위와 수정판이 다음처럼 구분된다.
| PyPI 패키지 | 권고에 명시된 영향 범위 | 수정판 |
|---|---|---|
| Brotli | 1.0.3 이상, 1.2.1 미만 | 1.2.1 |
| brotlicffi | 1.0.3 이상, 1.2.1.0 미만 | 1.2.1.0 |
requests만 업데이트했다는 사실로 디코더 교체까지 끝났다고 볼 수 없다. 의존성에 예전 버전이 고정돼 있으면 그 조건도 갱신해야 한다. Linux 배포판의 python3-brotli처럼 운영체제 패키지로 설치한 경우에는 해당 배포판의 수정 공지를 기준으로 판단한다. 위 표는 PyPI 패키지 기준이다.
pip show는 서비스를 실행하는 Python으로 호출한다
pip show로 설치 버전과 위치를 볼 수 있다. 아래의 python은 서비스가 사용하는 가상환경의 인터프리터로 바꿔 실행한다.
python -m pip show Brotli brotlicffi Version은 수정판과 비교하고, Location은 점검한 환경이 맞는지 확인하는 데 쓴다. 노트북이나 기본 셸에 패키지가 없다는 결과로 서버·작업 워커·컨테이너까지 없다고 판단할 수는 없다.
pip로 관리하는 환경에서 이미 사용하는 패키지를 갱신하는 명령 예시는 다음과 같다. 둘 다 새로 설치할 필요는 없으며, 설치된 패키지에 해당하는 줄을 사용한다.
python -m pip install --upgrade 'Brotli>=1.2.1'
python -m pip install --upgrade 'brotlicffi>=1.2.1.0' 파일 교체와 실행 프로세스 교체를 함께 끝낸다
Broccoli2Shell 조사자 안내는 설치 후에도 실행 중인 프로세스를 재시작해야 하며 컨테이너는 수정본을 포함한 이미지로 다시 빌드·배포해야 한다고 설명한다. 배포 파일의 의존성 고정값도 함께 갱신해야 다음 배포에서 옛 버전이 돌아오지 않는다.
brotlicffi 1.2.1.0 변경 내역에는 보안 수정 외에 완성된 Brotli 스트림 뒤의 남은 바이트를 오류로 처리하는 변경도 있다. 기존에 받아들이던 입력이 거절될 수 있으므로 압축 응답 처리 경로도 배포 검증에 포함한다.
점검의 끝은 개발 PC의 설치 성공 메시지가 아니다. 서비스가 실행될 환경의 패키지 버전, 새 이미지나 프로세스로의 교체, 정상 응답 처리까지 확인해야 한다.