Opened 60 minutes ago

Last modified 24 minutes ago

#37393 assigned Cleanup/optimization

Docs security topic needs better advice on untrusted user input

Reported by: Mike Edmunds Owned by: Mike Edmunds
Component: Documentation Version: 6.1
Severity: Normal Keywords: security
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

[Not sure if this should be a forum discussion or a ticket. I'm starting with a ticket.]

The first item in the ​Security in Django documentation topic is:

Always sanitize user input

The golden rule of web application security is to never trust user-controlled data. Hence, all user input should be sanitized before being used in your application. See the forms documentation for details on validating user inputs in Django.

It's true that "never trust user-controlled data" is an incredibly important golden rule. But the accompanying advice focuses entirely on input validation, conflates validation and sanitization, and doesn't really address context-specific escaping or sanitizing at the point of use.

I bring this up because #37388, #37162, and #34753 were all (to varying degrees) examples of developers not fully comprehending ways that user-controlled data can introduce vulnerabilities, or misunderstanding how and where "user input should be sanitized before being used" applies.

In the current docs:

  • The second sentence can be misread as "sanitize on input" rather than "sanitize at use." Trying to sanitize on input is often an anti-pattern, and it's usually better to retain the original input and escape or sanitize it on output. ("Input must be sanitized" is how the web ended up with contact forms and password rules that prohibit ' and ; because those characters might be used in sql injection.)
  • The correct escaping/sanitization depends on the output context, not the input data type. html, json, sql, urls, http headers, and even csv all require different handling. This may seem obvious, but it's quite common to see code using the wrong escape function. And even experienced developers may not be aware of all the possible contexts and rules. (Like formatting email addresses. Or trying to use Django template tags to initialize js variable values in an embedded script.)
  • Validation is not the same thing as sanitization. And validating the form of the input ("looks like an email address" or "is a jpeg" or "is numeric") is not the same as validating the content ("is an email address at our company" or "is a jpeg appropriate for display in our feed" or "is a numeric distance in km"). Assuming format validation means "trusted" can be insecure, embarrassing, or potentially even life-threatening.

I realize Django's docs can't offer a full tutorial on security topics, and that some specific types of output escaping and content validation are in fact addressed later in the page. But (imho) we could expand this section just a bit and provide much better, more actionable advice on this "golden rule" to lead off the security topic.

[I'll work on some suggested wording. But I've been meaning to bring this up for a while now and wanted to report it before I forget again.]

Change History (2)

comment:1 by Jacob Walls, 42 minutes ago

Triage Stage: Unreviewed → Accepted

Yes, happy to look at tweaks here. We often caution in security patch release notes, "As a reminder, all untrusted user input should be validated before use." -- but as you point out, this discussion conflates that with sanitization. (I've probably done some conflating myself when responding to security reporters.)

comment:2 by Mike Edmunds, 24 minutes ago

Owner: set to Mike Edmunds
Status: new → assigned
Note: See TracTickets for help on using tickets.
Back to Top