Upload a file and verify security headers on the served response. For non-PDF files, Content-Disposition: attachment must be set to force a download. For PDF files, Content-Disposition must NOT be set so the browser can render them inline, but Content-Type: application/pdf is always pr
(
tmp_path,
upload_file: AppHarness,
driver: WebDriver,
exp_name: str,
exp_contents: str,
expect_attachment: bool,
expected_mime_type: str,
)
| 999 | ids=["html", "pdf", "txt"], |
| 1000 | ) |
| 1001 | def test_uploaded_file_security_headers( |
| 1002 | tmp_path, |
| 1003 | upload_file: AppHarness, |
| 1004 | driver: WebDriver, |
| 1005 | exp_name: str, |
| 1006 | exp_contents: str, |
| 1007 | expect_attachment: bool, |
| 1008 | expected_mime_type: str, |
| 1009 | ): |
| 1010 | """Upload a file and verify security headers on the served response. |
| 1011 | |
| 1012 | For non-PDF files, Content-Disposition: attachment must be set to force a |
| 1013 | download. For PDF files, Content-Disposition must NOT be set so the browser |
| 1014 | can render them inline, but Content-Type: application/pdf is always present. |
| 1015 | X-Content-Type-Options: nosniff is always required. |
| 1016 | |
| 1017 | Args: |
| 1018 | tmp_path: pytest tmp_path fixture |
| 1019 | upload_file: harness for UploadFile app. |
| 1020 | driver: WebDriver instance. |
| 1021 | exp_name: filename to upload. |
| 1022 | exp_contents: file contents to upload. |
| 1023 | expect_attachment: whether the response should force a download. |
| 1024 | expected_mime_type: expected Content-Type mime type. |
| 1025 | """ |
| 1026 | import httpx |
| 1027 | |
| 1028 | assert upload_file.app_instance is not None |
| 1029 | poll_for_token(driver, upload_file) |
| 1030 | clear_btn = driver.find_element(By.ID, "clear_uploads") |
| 1031 | clear_btn.click() |
| 1032 | |
| 1033 | upload_box = get_upload_box(driver, upload_root_id="tertiary") |
| 1034 | upload_button = driver.find_element(By.ID, "upload_button_tertiary") |
| 1035 | |
| 1036 | target_file = tmp_path / exp_name |
| 1037 | target_file.write_text(exp_contents) |
| 1038 | |
| 1039 | upload_box.send_keys(str(target_file)) |
| 1040 | upload_button.click() |
| 1041 | |
| 1042 | upload_done = driver.find_element(By.ID, "upload_done") |
| 1043 | assert upload_file.poll_for_value(upload_done, exp_not_equal="false") == "true" |
| 1044 | |
| 1045 | # Fetch the uploaded file directly via httpx and check security headers. |
| 1046 | upload_url = f"{Endpoint.UPLOAD.get_url()}/{exp_name}" |
| 1047 | resp = httpx.get(upload_url) |
| 1048 | assert resp.status_code == 200 |
| 1049 | assert resp.text == exp_contents |
| 1050 | assert resp.headers["x-content-type-options"] == "nosniff" |
| 1051 | assert resp.headers["content-type"] == expected_mime_type |
| 1052 | |
| 1053 | if expect_attachment: |
| 1054 | assert resp.headers["content-disposition"] == "attachment" |
| 1055 | else: |
| 1056 | assert "content-disposition" not in resp.headers |
| 1057 | |
| 1058 | if not expect_attachment: |
nothing calls this directly
no test coverage detected