Fix XSS in API Responses in Tornado
Tornado's `self.write()` is a common source of XSS when building APIs. If you pass a string containing raw user input to `self.write()`, Tornado defaults the Content-Type to `text/html`. An attacker can then inject `
import tornado.web
class UserHandler(tornado.web.RequestHandler): def get(self): # VULNERABLE: Echoes raw input directly into a default text/html response user_id = self.get_argument(‘id’) self.write(‘User ID: ’ + user_id)
The Secure Implementation
The vulnerability stems from the browser's tendency to interpret responses as HTML if the Content-Type is missing or generic. By explicitly setting `application/json` and the `X-Content-Type-Options: nosniff` header, you prevent the browser from 'sniffing' the payload for executable scripts. Furthermore, using `tornado.escape.json_encode()` ensures that any special characters in the user input are properly escaped within the JSON string, neutralizing the injection vector.
import tornado.web
import tornado.escape
class UserHandler(tornado.web.RequestHandler):
def get(self):
user_id = self.get_argument(‘id’)
# SECURE: Explicitly set Content-Type and X-Content-Type-Options
self.set_header(‘Content-Type’, ‘application/json; charset=UTF-8’)
self.set_header(‘X-Content-Type-Options’, ‘nosniff’)
# SECURE: Encode data as a JSON object
response = {'user_id': user_id}
self.write(tornado.escape.json_encode(response))</code></pre>
Your API Responses API
might be exposed to XSS
74% of API Responses apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.
Free Tier • No Credit Card • Instant Report
Verified by Ghost Labs Security Team
This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.