diff --git a/etc/nginx.conf b/etc/nginx.conf index 95a109aaf4..f946635b7c 100644 --- a/etc/nginx.conf +++ b/etc/nginx.conf @@ -83,6 +83,9 @@ http { server_name _; location /uploads/ { + # prevent browser from possibly interpreting untrusted files + add_header Content-Type "text/plain"; + alias /Kiwi/uploads/; } diff --git a/tcms/core/middleware.py b/tcms/core/middleware.py index 1f0e608dc1..e54a7ddc67 100644 --- a/tcms/core/middleware.py +++ b/tcms/core/middleware.py @@ -34,4 +34,7 @@ def process_response(self, request, response): "Content-Security-Policy" ] = "script-src 'self' cdn.crowdin.com;" + if request.path.find("/uploads/") > -1: + response.headers["Content-Type"] = "text/plain" + return response diff --git a/tests/test_http.sh b/tests/test_http.sh index 4f2ce85ef6..df624643a0 100755 --- a/tests/test_http.sh +++ b/tests/test_http.sh @@ -97,8 +97,13 @@ _EOF_ # copy test file externally b/c Kiwi TCMS v12.2 will prevent its upload rlRun -t -c "docker exec -i kiwi_web /bin/bash -c 'mkdir -p /Kiwi/uploads/attachments/auth_user/2/'" rlRun -t -c "docker cp tests/ui/data/inline_javascript.svg kiwi_web:/Kiwi/uploads/attachments/auth_user/2/" + rlRun -t -c "curl -k -D- https://localhost/uploads/attachments/auth_user/2/inline_javascript.svg 2>/dev/null | grep 'Content-Type: text/plain'" + + rlRun -t -c "docker cp tests/ui/data/redirect.js kiwi_web:/Kiwi/uploads/attachments/auth_user/2/" + rlRun -t -c "docker cp tests/ui/data/html_with_external_script.html kiwi_web:/Kiwi/uploads/attachments/auth_user/2/" + rlRun -t -c "curl -k -D- https://localhost/uploads/attachments/auth_user/2/redirect.js 2>/dev/null | grep 'Content-Type: text/plain'" + rlRun -t -c "curl -k -D- https://localhost/uploads/attachments/auth_user/2/html_with_external_script.html 2>/dev/null | grep 'Content-Type: text/plain'" - rlRun -t -c "curl -k --fail https://localhost/uploads/attachments/auth_user/2/inline_javascript.svg" rlRun -t -c "robot tests/ui/test_inline_javascript.robot" fi rlPhaseEnd diff --git a/tests/ui/data/html_with_external_script.html b/tests/ui/data/html_with_external_script.html new file mode 100644 index 0000000000..ea5c320df4 --- /dev/null +++ b/tests/ui/data/html_with_external_script.html @@ -0,0 +1 @@ + diff --git a/tests/ui/data/redirect.js b/tests/ui/data/redirect.js new file mode 100644 index 0000000000..0a55d88ff6 --- /dev/null +++ b/tests/ui/data/redirect.js @@ -0,0 +1 @@ +location.replace('https://kiwitcms.org'); diff --git a/tests/ui/test_inline_javascript.robot b/tests/ui/test_inline_javascript.robot index 15372b6e43..3f5b52f40e 100644 --- a/tests/ui/test_inline_javascript.robot +++ b/tests/ui/test_inline_javascript.robot @@ -6,6 +6,7 @@ ${SERVER} https://localhost ${BROWSER} Headless Firefox ${DELAY} 0 ${SVG_URL} ${SERVER}/uploads/attachments/auth_user/2/inline_javascript.svg +${HTML_URL} ${SERVER}/uploads/attachments/auth_user/2/html_with_external_script.html *** Test Cases *** @@ -17,3 +18,13 @@ Directly accessing an SVG image should not execute inline JavaScript Location Should Be ${SVG_URL} [Teardown] Close Browser + + +Directly accessing an HTML file should not execute JavaScript + Open Browser ${HTML_URL} ${BROWSER} + Maximize Browser Window + Set Selenium Speed ${DELAY} + + Location Should Be ${HTML_URL} + + [Teardown] Close Browser