78 lines
2.0 KiB
Plaintext

include::../description.adoc[]
include::../how-to-fix-it.adoc[]
=== Code examples
==== Noncompliant code example
[source,python,diff-id=1,diff-type=noncompliant]
----
from http.server import BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs
class ReqHandler(BaseHTTPRequestHandler):
def do_GET(self):
parsed = urlparse(self.path)
params = parse_qs(parsed.query)
self.send_response(200)
self.send_header("Content-Type", params.get('accept')[0]) # Noncompliant
self.end_headers()
self.wfile.write(bytes("Hello World!", "utf-8"))
----
==== Compliant solution
[source,python,diff-id=1,diff-type=compliant]
----
from http.server import BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs, quote
class ReqHandler(BaseHTTPRequestHandler):
def do_GET(self):
parsed = urlparse(self.path)
params = parse_qs(parsed.query)
self.send_response(200)
self.send_header("Content-Type", quote(params.get('accept')[0])) # Compliant
self.end_headers()
self.wfile.write(bytes("Hello World!", "utf-8"))
----
=== How does this work?
By applying a URL encoding to an untrusted header value, the application ensures that all special characters are properly escaped before they are added to the HTTP response. Especially `\r` (Carriage Return) and `\n` (Line Feed) characters will be encoded to `%0D` and `%OA` and won't be able to alter the HTTP response's semantics.
//=== Pitfalls
//=== Going the extra mile
//== Resources
include::../see.adoc[]
//=== Documentation
//=== Articles & blog posts
//=== Conference presentations
//=== Standards
//=== External coding guidelines
//=== Benchmarks
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
=== Message
Change this code to not set an HTTP response header based on a user-controlled
value.
=== Highlighting
Highlight the tainted argument in the sink parameters.
endif::env-github,rspecator-view[]