Django 10월 보안 업데이트: 6.1.2·6.0.9·5.2.18 적용 체크리스트

Django를 운영 중이라면 현재 사용 중인 릴리스 계열의 보안 패치를 먼저 확인하자. Django 프로젝트는 2026년 10월 6일 6.1.2, 6.0.9, 5.2.18을 공개하고 빠른 업데이트를 권고했다. 새로 공개된 보안 문제 네 건과 기존 보안 완화 조치의 보완이 포함됐다. Django 공식 보안 공지

이 글은 10월 7일 확인한 공식 문서와 배포 기록을 바탕으로, 작은 팀이 패치 버전을 고르고 회귀 테스트를 준비하는 순서를 정리한다. 특히 모델 폼셋을 쓴다면 폼의 검증 결과와 저장 후 데이터 상태를 함께 확인하는 것이 중요하다.

1. 지금 쓰는 계열에서 적용할 버전 고르기

  • Django 6.1 계열: 6.1.2
  • Django 6.0 계열: 6.0.9
  • Django 5.2 LTS 계열: 5.2.18

위 숫자는 2026년 10월 7일 기준 각 지원 계열의 최신 정식 패치다. 세 버전 모두 PyPI에 배포되어 있다. 5.2 사용자가 이번 보안 수정을 받기 위해 곧바로 6.1로 옮길 필요는 없다. 우선 현재 계열의 패치를 적용하고, 기능 버전 전환은 의존성과 호환성을 살펴 별도로 계획하는 편이 변경 범위를 줄이기 좋다. 지원 버전 목록 · 6.1.2 배포 기록 · 6.0.9 배포 기록 · 5.2.18 배포 기록

4.2 LTS 등 지원이 끝난 계열은 별도 마이그레이션이 필요하다. 또한 Django 6.0·6.1의 공식 Python 호환 범위는 3.12~3.14이므로, 계열을 올릴 때 런타임 조건도 확인해야 한다. 이 글의 패치 선택 목록을 모든 과거 버전의 업그레이드 경로로 적용해서는 안 된다. Python 호환성 안내

2. 서비스에서 먼저 확인할 네 가지 경로

공식 분류는 low 한 건, moderate 세 건이다. 심각도 이름과 함께 실제 기능 사용 여부를 확인하자. 다음 목록은 점검 순서를 정하기 위한 요약이며, 특정 기능을 사용하지 않는다는 이유로 전체 업데이트를 미룰 근거는 아니다.

  • CVE-2026-87975, 모델 폼셋 권한 문제: 폼을 통해 기본 키를 설정할 수 있는 모델에서 제한된 queryset 밖의 객체가 삭제되거나, 편집 전용 폼셋에서 객체가 생성될 수 있었다. OneToOneField나 부모 링크가 기본 키인 경우, 폼 필드에 포함된 자연 키·UUID 기본 키 등이 해당 조건이다. 기본 BigAutoField를 쓰는 모델은 이 문제의 영향 대상이 아니다.
  • CVE-2026-84429, HTTP 헤더 처리: 특정 헤더 매개변수 파싱의 계산량 때문에 서비스 거부 가능성이 있었다. Accept·Content-Type 처리와 HttpRequest.accepts() 같은 경로가 관련된다. 파서 변경으로 일부 비정상적이거나 특이한 헤더의 해석 결과가 달라질 수 있다.
  • CVE-2026-87890, 공간 조회의 bytes 입력: 외부에서 받은 bytes를 공간 조회에 직접 전달하는 애플리케이션에서는 래스터 해석 중 의도하지 않은 네트워크 요청이 발생할 수 있었다. 패치 뒤 래스터 bytes는 GDALRaster로 명시적으로 감싸야 한다. 입력의 출처와 내용 검증도 유지해야 한다.
  • CVE-2026-77050, 언어 코드 처리: 서로 다른 매우 긴 언어 코드가 메모리 캐시에 쌓일 수 있었다. 수정 후에는 캐시 조회 전에 500자를 넘는 코드를 거부하거나 줄인다.

네 항목의 조건과 심각도는 6.1.2 릴리스 노트에서 확인할 수 있다. 공간 조회의 bytes 변경은 공식적으로 하위 호환성이 깨지는 변경으로 명시돼 있다. GeoDjango를 사용한다면 기존 래스터 입력 처리부터 살펴보자.

이번 패치에는 깊게 중첩된 geometry collection의 제한을 우회할 수 있던 기존 완화 조치의 보완도 들어갔다. 5.2.17·6.0.8·6.1에 앞선 조치가 들어 있었더라도 이번 패치를 검토해야 한다. 5.2.18 릴리스 노트 · 6.0.9 릴리스 노트

3. 폼셋 테스트는 저장 후 데이터까지 확인하기

이번 폼셋 수정에서 눈여겨볼 부분은 테스트의 성공 기준이다. Django의 공식 수정과 회귀 테스트에는 formset.is_valid()가 참인 상태에서도 save() 이후 queryset 밖의 객체가 그대로 존재하는지 확인하는 사례가 있다. 따라서 “반드시 폼 오류가 나야 한다”는 기대만으로 수정 여부를 판단하면 실제 방어 동작을 잘못 읽을 수 있다.

자신의 프로젝트에는 다음 결과를 확인하는 테스트를 추가하는 것을 권한다. 아래는 공식 수정에서 도출한 점검 제안이며, 이 글에서 실행한 테스트 결과는 아니다. 운영 데이터 대신 격리된 테스트 데이터베이스와 가짜 객체를 사용한다.

  1. 현재 사용자가 편집할 수 있는 객체의 정상 수정·삭제가 기존대로 동작하는지 확인한다.
  2. 편집 범위 밖의 객체는 요청 처리 후에도 삭제되거나 변경되지 않는지 데이터베이스를 다시 조회한다.
  3. 편집 전용 화면에서는 새 객체가 생기지 않는지 확인한다.
  4. GET으로 폼을 보여 줄 때와 POST를 처리할 때 같은 권한 기준의 queryset이 전달되는지 점검한다.

일반 모델 폼셋은 기본적으로 모델의 전체 객체를 대상으로 하며, 필요한 범위는 애플리케이션이 지정해야 한다. 공식 문서도 GET과 POST 양쪽에 queryset을 넘기는 예를 제공한다. 또한 extra=0은 빈 폼 표시를 줄이는 설정이고, 새 객체 생성을 막으려는 목적에는 edit_only=True를 사용한다. 보안 패치를 적용하면서 이 설정과 애플리케이션의 권한 검사를 함께 점검하자. 사용자 지정 queryset · 새 객체 생성 제한

4. 의존성 변경부터 실행 환경 확인까지

다음은 소규모 서비스에 권하는 배포 순서다. 전체 테스트 실행과 하위 호환성 검토는 Django 업그레이드 안내를 따르고, 구체적인 빌드·배포 절차는 프로젝트 방식에 맞춘다.

  1. 현재 상태 기록: 운영 이미지나 가상환경의 Django 버전, 사용 중인 계열, 의존성 파일을 확인한다.
  2. 변경 범위 고정: 기존 패키지 관리 절차로 해당 계열의 패치 버전을 반영한다. 잠금 파일을 쓴다면 함께 갱신하고, 예상 밖의 다른 의존성 변경도 검토한다.
  3. 테스트 환경 검증: 전체 테스트와 위 폼셋 점검을 수행한다. 사용하는 경우에 한해 언어 선택, 콘텐츠 협상, 파일 업로드의 정상 헤더, GeoDjango 입력 처리도 확인한다.
  4. 배포와 재기동: 새 빌드로 웹 프로세스와 Django를 사용하는 워커를 갱신한다. 저장소의 버전 선언과 실제 실행 환경이 일치하는지 확인한다.
  5. 배포 후 확인: 정상 요청의 오류율과 로그, 폼 저장·삭제 결과를 살펴본다. 패치 버전, 빌드 식별자, 테스트 결과를 배포 기록에 남긴다.

다음 명령은 기존 Django 프로젝트의 가상환경을 활성화한 뒤 사용할 수 있다. 테스트 명령은 테스트용 설정과 데이터베이스가 준비된 개발·CI 환경에서 실행한다.

python -m django version
python -Wa manage.py test

명령은 공식 버전 확인 문서와 업그레이드 안내에 대조했으며, 이 글 작성 과정에서 실제 프로젝트로 실행하지 않았다. 첫 명령은 해당 Python 환경에 설치된 버전을 출력한다. 둘째 명령의 통과 여부는 프로젝트 테스트에 달려 있다.

패치 완료 기준을 짧게 남기자

“최신 버전으로 바꿨다”보다 현재 계열의 패치 버전이 배포됐고, 변경된 입력 처리와 객체 권한 경계가 테스트됐으며, 실행 프로세스에도 반영됐다는 기록이 유용하다. 특히 UUID 기본 키를 쓴다는 사실만으로 영향을 단정하지 말고, 그 키가 폼을 통해 설정되는지까지 확인하자.

이번 릴리스는 프레임워크의 명시된 문제를 수정한다. 애플리케이션이 잘못 구성한 권한 범위나 검증 로직은 별도로 고쳐야 한다. 소규모 팀이라면 같은 계열 패치를 우선 반영하고, 자신의 서비스가 사용하는 경로에 집중해 회귀 검증을 진행하는 접근이 현실적이다.

자료 확인: 2026년 10월 7일. Django 공식 보안 공지·문서·소스 변경과 PyPI 배포 기록을 확인하고 AI의 도움을 받아 정리했다. 독립적인 취약점 재현이나 런타임 테스트는 수행하지 않았다.

댓글