Merge lp:~ack/txaws/xss-hardening into lp:txaws

Proposed by Alberto Donato on 2013-08-22
Status: Merged
Merged at revision: 156
Proposed branch: lp:~ack/txaws/xss-hardening
Merge into: lp:txaws
Diff against target: 88 lines (+34/-8)
2 files modified
txaws/server/resource.py (+7/-6)
txaws/server/tests/test_resource.py (+27/-2)
To merge this branch: bzr merge lp:~ack/txaws/xss-hardening
Reviewer Review Type Date Requested Status
Fernando Correa Neto (community) 2013-08-22 Approve on 2013-08-22
txAWS Committers 2013-08-22 Pending
Review via email: mp+181562@code.launchpad.net

Description of the change

Based on Chris' branch lp:~tribaal/txaws/xss-hardening, drops the cgi.escape as json content shoudn't be escaped.

It also adds the "X-Content-Type-Options: nosniff" header, to prevent browsers from guessing the content type, and use the one declared in the response (application/json).

To post a comment you must log in.
Fernando Correa Neto (fcorrea) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'txaws/server/resource.py'
2--- txaws/server/resource.py 2012-05-09 14:21:39 +0000
3+++ txaws/server/resource.py 2013-08-22 14:02:04 +0000
4@@ -94,6 +94,8 @@
5 def write_response(response):
6 request.setHeader("Content-Length", str(len(response)))
7 request.setHeader("Content-Type", self.content_type)
8+ # Prevent browsers from trying to guess a different content type.
9+ request.setHeader("X-Content-Type-Options", "nosniff")
10 request.write(response)
11 request.finish()
12 return response
13@@ -109,16 +111,15 @@
14 log.msg("status: %s message: %s" % (
15 status, safe_str(failure.value)))
16
17- bytes = failure.value.response
18- if bytes is None:
19- bytes = self.dump_error(failure.value, request)
20+ body = failure.value.response
21+ if body is None:
22+ body = self.dump_error(failure.value, request)
23 else:
24 log.err(failure)
25- bytes = safe_str(failure.value)
26+ body = safe_str(failure.value)
27 status = 500
28 request.setResponseCode(status)
29- request.write(bytes)
30- request.finish()
31+ write_response(body)
32
33 deferred.addCallback(write_response)
34 deferred.addErrback(write_error)
35
36=== modified file 'txaws/server/tests/test_resource.py'
37--- txaws/server/tests/test_resource.py 2012-05-09 14:21:39 +0000
38+++ txaws/server/tests/test_resource.py 2013-08-22 14:02:04 +0000
39@@ -120,8 +120,7 @@
40 "access_key_id": request.args["access_key"][0],
41 "signature_method": "Hmacsha256",
42 "signature_version": 2,
43- "signature": request.args["signature"][0],
44- }
45+ "signature": request.args["signature"][0]}
46 params = dict((k, v[-1]) for k, v in request.args.iteritems())
47 raw = params.copy()
48 raw.pop("signature")
49@@ -153,6 +152,8 @@
50 self.assertEqual("data", request.response)
51 self.assertEqual("4", request.headers["Content-Length"])
52 self.assertEqual("text/plain", request.headers["Content-Type"])
53+ self.assertEqual(
54+ "nosniff", request.headers["X-Content-Type-Options"])
55 self.assertEqual(200, request.code)
56
57 self.api.principal = TestPrincipal(creds)
58@@ -428,6 +429,30 @@
59
60 return self.api.handle(request).addCallback(check)
61
62+ def test_handle_error_is_api_content_type(self):
63+ """
64+ If an error occurs while parsing the parameters, L{QueryAPI.handle}
65+ responds with HTTP status 400, and the resulting response has a
66+ Content-Type header matching the content type defined in the QueryAPI.
67+ """
68+ creds = AWSCredentials("access", "secret")
69+ endpoint = AWSServiceEndpoint("http://uri")
70+ query = Query(action="SomeAction", creds=creds, endpoint=endpoint)
71+ query.sign()
72+ query.params.pop("Action")
73+ request = FakeRequest(query.params, endpoint)
74+
75+ def check(ignored):
76+ errors = self.flushLoggedErrors()
77+ self.assertEquals(0, len(errors))
78+ self.assertEqual(400, request.code)
79+ self.assertEqual(
80+ self.api.content_type, request.headers['Content-Type'])
81+ self.assertEqual(
82+ "nosniff", request.headers["X-Content-Type-Options"])
83+
84+ return self.api.handle(request).addCallback(check)
85+
86 def test_handle_unicode_api_error(self):
87 """
88 If an L{APIError} contains a unicode message, L{QueryAPI} is able to

Subscribers

People subscribed via source and target branches