Skip to content

USWDS - Bug: file upload component is incompatible with a typical content security policy (CSP) #5990

@jeffpw-goog

Description

@jeffpw-goog

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

  1. Create a page with a file input component
  2. 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:" />
  3. On your local machine, create an empty text file and rename it to *.jpg
  4. Open the page and upload the file to the file input component
  5. 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:

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

Actual:
image

Browser console error:
image

Expected:
image

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

Metadata

Metadata

Assignees

Type

No type

Projects

Status

Done

Relationships

None yet

Development

No branches or pull requests

Issue actions