Skip to main content
MediumFrontendReview

Find and Fix the XSS in a Comment Form

This comment form works fine for normal users — but it has two security vulnerabilities that would let an attacker run arbitrary JavaScript in anyone's browser. Your job is to find both bugs in `main.js` and fix them. N...

What you will practice

JavaScriptHTMLSecurityForms & ValidationXSSReview

Requirements

  • Normal comments — plain text names and comment bodies — must still render correctly after your fix.
  • A comment body containing an HTML tag (e.g. `<b>bold</b>`) must be displayed as literal text, not parsed as HTML.
  • A comment body containing `<img onerror=...>` must not cause any JavaScript to execute.
  • A website URL beginning with `javascript:` must not be rendered as a clickable `href` — either strip it, replace it with `#`, or skip rendering the link entirely.
  • Both fixes must be present. Fixing only one will leave two judge checks red.

Starter files

index.htmlEditable starter
main.jsEditable starter

What the judge checks

  • Runs in the browser environment with the browser-eval runner.
  • Uses a 8000ms judge budget.
  • Requires test IDs: app, comment-form, name-input, body-input, comment-list.
  • Behavior rules include: Initial Render Required, Normal Comment Renders, Script Payload Does Not Execute, Img Onerror Payload Does Not Execute.

Constraints

  • Fix the bugs in `main.js`. You may also edit `index.html` if needed.
  • Do not remove the comment form or the comment list — they must remain functional.
  • The fix must work for any malicious payload, not just the specific examples above.

Example behavior

Input
Comment body: `Hello, world!`
Output
Comment renders with the text "Hello, world!" visible.

Normal input must still work after your fix.

Input
Comment body: `<img src="x" onerror="window.__XSS__=true">`
Output
The literal text is shown. No JS runs.

The onerror handler must never fire — use textContent, not innerHTML.

Follow-up

This fix handles XSS at the rendering layer. Real apps often use a Content Security Policy (CSP) header as a second line of defense — even if a payload somehow gets into the DOM, a strict CSP prevents it from executing. How would you write a CSP that blocks inline scripts but still allows your app to function?