psf-drf-check(8)

Script: /opt/psf-security-patches/django/drf-check.sh. Tool page: Django REST framework. Source. With the package installed: man psf-drf-check.

Django REST framework October 2026: checker with mitigation  (v1)
CVE-2026-114138 (Accept header CPU exhaustion)
CVE-2026-114137 (TokenProxy.delete() revokes nothing)

If this software is helpful, consider a donation to our 501c3 nonprofit:
https://privacysafe.foundation

Django REST framework (DRF) is the standard toolkit for building web APIs on
Django. Both flaws are fixed in DRF 3.18.2.

CVE-2026-114138  DefaultContentNegotiation accepts an unbounded number and size
                 of Accept header tokens, and parses each one repeatedly for
                 every renderer. A remote, unauthenticated client can send many
                 distinct media types with large quoted parameters and burn
                 about 19 seconds of CPU per request. Every API view does
                 content negotiation, so any reachable endpoint is a target.
                 CVSS 7.5. Affected: every release before 3.18.2 (the 0.x and
                 2.x lines are not fixed upstream). The cost also involves
                 Django's own header parameter parser, which Django fixed
                 separately in 5.2.18, 6.0.9 and 6.1.2, so keep Django current
                 as well.

CVE-2026-114137  From 3.12.0 until 3.18.2, TokenProxy.delete() in
                 rest_framework.authtoken uses the wrong primary key, so the
                 delete matches no row and reports success. The token keeps
                 working. DRF tokens do not expire, so code that revokes access
                 through a TokenProxy instance leaves the access open
                 indefinitely. CVSS 7.4. Only sites with rest_framework.authtoken
                 installed are exposed, and DRF's own admin delete is not
                 affected. Revocation done with Token.objects (not TokenProxy)
                 works on every version.

"check" is read-only; "mitigate" and "rollback" are the only commands that change
anything. "check" finds installed copies (dist-info and egg-info
metadata) and declared pins (requirements, poetry.lock, uv.lock, pdm.lock,
Pipfile.lock), notes where rest_framework.authtoken and TokenProxy appear in
project source, and for installed copies compares the neighboring Django.

Usage:
  ./drf-check.sh [command] [DIR ...]

  check (default)  scan DIR (default /usr/lib /usr/local/lib /opt /srv /var/www
                   /var/lib /home /root). Exit 0 = nothing affected, 1 = an
                   affected copy or pin was found.
  mitigate [options]   (root) changes the host. PrivacySafe protection: real Accept headers are far shorter than 1 KB, so
                   nginx answers 406 to an Accept header of 1024 characters or more,
                   which bounds the cost of the attack. Only when an affected copy is
                   found (--force overrides). Adds a map block right after "http {" and
                   an include as the first line of every server block that proxies
                   (proxy_pass, uwsgi_pass or scgi_pass), then checks with nginx -t; if
                   nginx rejects the result everything is undone at once. nginx only.
                     --server-name NAME  only the server block that lists NAME (repeat)
                     --dir DIR           where to look for Django REST framework (repeat)
                     --dry-run           show the changes, change nothing
                     --reload            graceful reload afterwards (systemd)
                     --force             apply even if no affected copy is found
  rollback [--dry-run] [--reload]   remove what mitigate added and restore the files it edited.
  version          print the script version.
Containers: with no directory argument the check also reads the project files it needs from
running docker and podman containers (SCAN_CONTAINERS=1, the default; 0 skips them), through a
read-only probe, and judges them like host projects. The copies are temporary: a path shown as
.../docker_NAME/PATH is the PATH inside the container NAME.
     PSF_LOCK_WAIT    seconds a run that changes the host waits for another one that is already
                      changing it (default 30), then stops with exit 2; the lock is STATE_DIR/.lock

The Security Patches software and this documentation are dedicated to the public domain under CC0 1.0 Universal. Other pages on privacysafe.app/docs are CC BY-SA 4.0 unless the page says otherwise.

The PrivacySafe Ecosystem

Shop at Ivy Cyber

Ivy Cyber offers PrivacySafe products and services in the USA and has partnerships with 3NSoft in Canada and Kuip Limited in the European Union. Enterprise services and consulting are available at ivycyber.com

PrivacySafe Foundation is a 501(c)(3) nonprofit public charity that supports the development of the PrivacySafe applications, along with the components they rely upon: 3NWeb protocols, filesystem, documentation, and reference implementations.

PrivacySafe Foundation

Donations to PrivacySafe Foundation support education, research, documentation, and public code. Purchases from Ivy Cyber support PrivacySafe products, services, hosting, and technical support. Together, we're building a better web.