-
Notifications
You must be signed in to change notification settings - Fork 1k
Closed
Description
Describe the bug
The file input component uses an onerror
inline Javascript event handler which is incompatible with a typical Content Security Policy (CSP). This page explains in more detail that inline javascript is not allowed with a nonce- or hash-based approach to strict CSP.
Steps to reproduce the bug
- Create a page with a file input component
- Set a content security policy on the page, e.g. "script-src 'nonce-st+WdPSI/W6r3q3iFeG/hQ==' 'strict-dynamic' https:" (in production the nonce value changes on each request). You can do this by setting the
Content-Security-Policy
HTTP header, or adding an HTML meta element<meta http-equiv="Content-Security-Policy" content="script-src 'nonce-st+WdPSI/W6r3q3iFeG/hQ==' 'strict-dynamic' https:" />
- On your local machine, create an empty text file and rename it to *.jpg
- Open the page and upload the file to the file input component
- Observe that the file preview is a broken image and the browser console shows this error: `Refused to execute inline event handler because it violates the following Content Security Policy directive: "script-src 'nonce-st+WdPSI/W6r3q3iFeG/hQ==' 'strict-dynamic' https:".
Expected Behavior
The file preview image is a generic document icon rather than a broken image, and there are no browser security errors.
Related code
The onerror
inline event handler is used several times in this section:
uswds/packages/usa-file-input/src/index.js
Lines 394 to 427 in 369cf3f
reader.onloadend = function createFilePreview() { | |
const previewImage = document.getElementById(imageId); | |
if (fileName.indexOf(".pdf") > 0) { | |
previewImage.setAttribute( | |
"onerror", | |
`this.onerror=null;this.src="${SPACER_GIF}"; this.classList.add("${PDF_PREVIEW_CLASS}")`, | |
); | |
} else if ( | |
fileName.indexOf(".doc") > 0 || | |
fileName.indexOf(".pages") > 0 | |
) { | |
previewImage.setAttribute( | |
"onerror", | |
`this.onerror=null;this.src="${SPACER_GIF}"; this.classList.add("${WORD_PREVIEW_CLASS}")`, | |
); | |
} else if ( | |
fileName.indexOf(".xls") > 0 || | |
fileName.indexOf(".numbers") > 0 | |
) { | |
previewImage.setAttribute( | |
"onerror", | |
`this.onerror=null;this.src="${SPACER_GIF}"; this.classList.add("${EXCEL_PREVIEW_CLASS}")`, | |
); | |
} else if (fileName.indexOf(".mov") > 0 || fileName.indexOf(".mp4") > 0) { | |
previewImage.setAttribute( | |
"onerror", | |
`this.onerror=null;this.src="${SPACER_GIF}"; this.classList.add("${VIDEO_PREVIEW_CLASS}")`, | |
); | |
} else { | |
previewImage.setAttribute( | |
"onerror", | |
`this.onerror=null;this.src="${SPACER_GIF}"; this.classList.add("${GENERIC_PREVIEW_CLASS}")`, | |
); | |
} |
To meet CSP requirements, these event handlers should be added via addEventListener on the image element rather than the onerror
attribute.
Screenshots
System setup
- USWDS version: 3.6.0
- Device: Macbook
- Operating system: Mac OS 14.5
- Browser and version: Chrome 126.0.6478.184 (arm64)
Additional context
No response
Code of Conduct
- I agree to follow this project's Code of Conduct.
- I checked the current issues for duplicate bug reports.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Done