Skip to content

cross site scripting via Unsanitized Error Messages #368

@krewdev

Description

@krewdev
  1. Cross-Site Scripting (XSS) via Unsanitized Error Messages

a. Vulnerability Type

Improper Neutralization of Input During Web Page Generation (XSS) / Unsanitized Error Handling.

b. Explanation

In the catch block, the code constructs an error message by concatenating a static string with the content of e.message. If the error originates from a malicious server response (e.g., a custom error body containing HTML or script tags), or if the underlying fetch implementation allows injection into the error message, this unsanitized content is stored in the error state.

If a consuming React component later renders this error state using a dangerously set inner HTML property (or if the framework fails to escape it properly), an XSS attack could be executed. While React generally escapes string content, it is best practice to sanitize or strictly control the content of error messages derived from external, untrusted sources before storing them in state.

c. Problematic Line(s) of Code

// Inside the catch block:
if (e instanceof Error) {
msg += " Error: " + e.message + "."; // e.message is untrusted input
setError(msg);
}

d. Corrected, Secure Code Snippet

We should ensure that any external input used in the error message is strictly treated as plain text. If a dedicated sanitization utility is not available, we should limit the information exposed to the user and ensure the message is stringified safely.

// ... inside fetchData
} catch (e) {
if (response.controller.signal.aborted) return;

  let msg = "An error occurred while loading model.";
  
  if (e instanceof Error) {
    // Sanitize or strictly limit the external message content
    // We use JSON.stringify to ensure the message is treated as a safe string literal
    const safeErrorMessage = JSON.stringify(e.message).slice(0, 256); // Limit length for safety
    msg +=  Details: ${safeErrorMessage};
  }

  setError(msg);

  if (window.APP_SETTINGS.debug) {
    console.error(e);
  }
} finally {

// ...

e. Why the Corrected Code is More Secure

By using JSON.stringify on the external error message (e.message), we ensure that any potentially malicious characters (like <, >, or quotes) are properly escaped into a safe string literal before being stored in the state. Additionally, limiting the length (.slice(0, 256)) prevents potential denial-of-service attacks via excessively long error messages. This minimizes the risk of XSS if the consuming component were to render the error message improperly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions