Decorate views and functions that handle secrets with sensitive_variables and sensitive_post_parameters. When DEBUG is False, Django replaces the named local variables and POST parameters with asterisks in error reports. Without them, an emailed traceback can carry a password or card number straight into an inbox.
Why error reports leak
Django's error reporting guide says that on a public site you should always turn DEBUG off, then configure reports so you still learn about errors. When DEBUG is False, Django emails the people in ADMINS for any response with status 500 or above, and the report includes a description of the error, a complete Python traceback, and details about the HTTP request that caused it.
A traceback includes local variables for each frame. If a function holds a password, token or card number in a local variable, it can appear in that report. The request details can include POST data. Those reports go through email, and often into ticketing tools and chat, which keep them far longer than you expect.
The two decorators
The documentation names two decorators that filter reports in production, meaning when DEBUG is False:
| Decorator | Hides |
|---|---|
| sensitive_variables | Named local variables of a function |
| sensitive_post_parameters | Named POST parameters of a request |
Usage for local variables:
from django.views.decorators.debug import sensitive_variables
@sensitive_variables("user", "pw", "cc")
def process_info(user):
pw = user.pass_word
cc = user.credit_card_number
name = user.name
The docs say user, pw and cc are shown as stars while name is still disclosed. Calling the decorator with no arguments hides all local variables of that function.
For form data, apply sensitive_post_parameters to the view, naming fields such as password or card number, or none to hide all POST parameters.
Decorator order
One trap from the docs: if the variable you want to hide is also a function argument, and the function has several decorators, put sensitive_variables at the top of the chain. That way the argument is hidden as it passes through the other decorators. Put it lower and the value can slip into the report.
What this does not cover
These decorators filter Django's error reports. They do not stop you from logging secrets yourself, writing request bodies to logs, or sending exceptions to a third party tool that captures its own context. Check what your error tracking client collects and configure its scrubbing too. Also remember DEBUG True bypasses filtering, which is another reason it must be off in production.
Where to apply them
- Login, registration, password change and reset views.
- Payment and billing views.
- Functions that fetch API keys or tokens into locals.
- Any view receiving personal data in forms.
Add a code review rule: when a new view reads a secret, it gets a decorator.
Check that it works
- Set DEBUG False in a test environment with ADMINS or your error tracker configured.
- Raise a deliberate exception inside a decorated view that handles a fake password.
- Read the resulting report and confirm stars appear in place of the value.
- Repeat for your third party error tool.
Try it yourself
Click through it at your own pace, or open it full screen. Look for findings about sensitive data exposure in code.
Quick check
Do these decorators work when DEBUG is True?
No. The documentation describes them as filtering reports in a production environment, where DEBUG is False.
Does sensitive_variables stop my logging from printing secrets?
No. It only affects Django's error reports. Keep secrets out of your own log statements.
Safeguard's SAST can help find places where secrets are handled, and compliance evidence automation can record the review. A free scan is available.
Sources
Last reviewed: 19 October 2026.