# H5SC: the archived HTML5 XSS vector collection behind modern sanitizer thinking

> Cure53's HTML5 Security Cheatsheet holds 149 verified XSS vectors in plain JavaScript modules, a set of odd test files for filter probing, and an honest statement that nothing will ever be re-verified.

**cure53/H5SC** — HTML5 Security Cheatsheet - A collection of HTML5 related XSS attack vectors

- Repository: https://github.com/cure53/H5SC
- Website: https://html5sec.org/
- Stars: 2,936 · Forks: 415
- Language: JavaScript
- License: MPL-2.0
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/cure53-h5sc

## An archive on purpose, with the verification window stated up front

The README opens with a project status section that few security repositories bother to write. The 149 vectors were collected and verified between 2010 and 2016, with the last additions in 2022, and the archive is kept online and readable on purpose. The stated reason is historical: a large share of what sanitizers, filters and browsers do today exists because of the behaviours catalogued here.

Then it spells out the consequences, which is the part that makes this repository trustworthy. The `browsers` field on each vector describes the engines of its day, so "latest" means latest as of when the vector was verified, not current. Vectors are not re-verified against current browsers, there are no plans to do so, and entries are not removed even when they stop working, because a vector that stopped working is still a record of a parser behaviour that once existed and may exist again somewhere else.

That framing matters when you read individual entries. An Internet Explorer vector or an E4X vector is not dead weight; it describes a class of parsing divergence that keeps turning up outside browsers. New vectors are still accepted, but only when they match the collection's shape: a single markup snippet that executes script in a named engine, with a reporter credit.

## Four JavaScript files that hold the whole collection

The site at html5sec.org is the shop window, but the data is four plain files in the repository and needs no build step. `items.js` carries the 149 vectors with name, payload, description, fix advice, a browser matrix, tags and reporter, and it is multilingual: en, ja, ru, cs, de, tr and zh, though not every entry has every translation. `payloads.js` holds the `%js_alert%`-style placeholders the vectors are written against, so one vector can be rendered with an `alert`, a `confirm` or your own probe.

`categories.js` holds the category labels and `vectors.txt` is the entire collection flattened into one file for copy and paste. `lib/index.js` exposes all three as a CommonJS module, and `package.json` points `main` at that file.

```json
"name": "H5SC",
"version": "0.0.0",
"description": "HTML5 Security Cheatsheet",
"main": "lib/index.js",
"license": "Mozilla Public License, version 2.0"
```

Those five lines say a lot about the project's shape. Version 0.0.0 means there is no versioning contract to speak of, and the license string is a human-readable form of the Mozilla Public License 2.0 rather than an SPDX identifier. There is no dependency list at all, which is exactly why the data is pleasant to consume: importing the vectors into your own tooling costs nothing and pulls in no supply chain. The project has around 2,900 stars and 415 forks, is written in JavaScript, and was last pushed on 2026-09-09.

## A folder of deliberately odd files for probing filters

The second of the three things H5SC holds is a set of files published for testing filters in the awkward cases where content types, extensions and sniffed formats disagree. Every entry lives in `attachments/` and is served from html5sec.org under a `test.` prefix:

```text
https://html5sec.org/test.asf
https://html5sec.org/test.css
https://html5sec.org/test.eml
https://html5sec.org/test.hta
https://html5sec.org/test.jar
https://html5sec.org/test.svg
https://html5sec.org/test.xsl
https://html5sec.org/test.zip
https://html5sec.org/Test.class
```

The list is longer than this: `test.avi`, `test.dtd`, `test.evt`, `test.gif`, `test.hlp`, `test.htc`, `test.json`, `test.mpeg`, `test.pdf`, `test.sct`, `test.swf`, `test.vbs`, `test.vml`, `test.wbxml`, `test.xbl`, `test.xdr`, `test.xml`, `test.xxe` and `test.class` sit alongside them. `test.class` is worth a second look because of the capital T in its name, which is the kind of detail that trips extension and MIME matching on case-sensitive filesystems.

This is the part of the collection with the longest shelf life. A polyglot file that is simultaneously valid in several parsers is still a live problem in upload pipelines, previewers and email clients, and having a canonical URL for each case saves an afternoon of file crafting. A Java virtual class file, a Windows HTML application, an XSL stylesheet and a SWF are not exotic examples; they are everyday formats that a sanitizer never sees as markup.

## The search, redirect and RSS endpoints that turn the archive into a tool

The third component is described in the README as hidden features, which is how a lot of long-lived reference sites describe anything genuinely useful. The search interface is a GET request against the site itself, so all vectors mentioning `innerHTML` are at https://html5sec.org/?innerHTML, and a specific vector can be linked directly with its numeric id after a hash, for example https://html5sec.org/#123.

The redirect API is the cleverest of the three. Given a scheme and an optional status code it will redirect to a URL that carries an XSS payload, which makes it useful for testing open redirect handling and link rewriting without constructing a long data URI by hand:

```text
https://html5sec.org/r/data/
https://html5sec.org/r/data/307
https://html5sec.org/r/javascript/301
```

Supported status codes are `301`, `302`, `303`, `307`, `308` and `999`, and supported schemes are `data`, `javascript`, `jar` and `script`. The last of those redirects to a URL containing a script tag payload, which is a quick way to check whether a scanner follows redirects before deciding a page is clean.

The RSS mode exists for feed readers, which have their own parsing paths and their own history of markup handling bugs. The time-shifting behaviour is what makes it testable: `/rss/+/` serves a unix timestamp 300 seconds in the future, `/rss/+123/` uses 123 seconds ahead, and `/rss/1234/` serves a minimal feed until unix time reaches 1234. The site also exposes a JavaScript function, runnable from the page console, that returns all vectors as one isolated and numbered string.

## Contributing, translating and what the README recommends instead

The contributing section is short and specific. New vectors go into `items.js` as a pull request: copy the shape of an existing entry, use the next free `id`, fill in at least the `en` strings, list the engines and versions the vector was verified in, and credit the reporter. Translations of existing entries are welcome, and the README notes that the `de` strings in particular are mostly empty.

That requirement to list engines and versions is what makes the data usable later. A payload without a verification record is folklore; a payload with one is evidence, and the whole value of this collection depends on that distinction being maintained.

The README also points elsewhere, which is a good sign. For a living, engine-verified list of XSS payloads it recommends PortSwigger's Cross-Site Scripting cheat sheet. For the reasoning behind attack classes rather than individual payloads, it points at the DOMPurify wiki page Attack Classes and Bypass History, written by the same author. For markup that causes requests rather than script execution it points at HTTPLeaks.

So the intended division of labour is clear: use PortSwigger for what is exploitable in a browser today, use the DOMPurify wiki for why sanitizers get bypassed, and use H5SC for the historical record. There are no releases published for this repository, so there is no version history to track, and the last push on 2026-09-09 appears to be maintenance rather than new content, consistent with an archive that only accepts additions of a specific kind.

## Conclusion

H5SC is most useful read as a record of parser behaviour rather than as a payload to paste into a scanner. The 149 vectors were collected and verified between 2010 and 2016 with the last additions in 2022, so the `browsers` field on any entry tells you about engines of that period, including Internet Explorer, Presto-era Opera, E4X, XBL, `behavior:` and VML that no longer ship in a browser but still turn up inside mail clients, embedded webviews and legacy sanitizer code. The data is plain JavaScript with no build step, so it is cheap to load and diff. The README points at PortSwigger's cheat sheet for engine-verified current payloads and at the DOMPurify wiki for the reasoning behind attack classes, and that division of labour is the honest way to use this project.

## FAQ

### Is H5SC still updated with new XSS vectors?

Selectively. The README states the 149 vectors were collected and verified between 2010 and 2016 with the last additions in 2022, that nothing is re-verified against current browsers, and that entries are never removed. New vectors are still accepted when they match the collection's shape: one markup snippet that executes script in a named engine, with a reporter credit.

### How do I use the H5SC vectors outside the website?

They live in the repository as plain JavaScript. `items.js` holds the 149 vectors with payloads, descriptions, browser matrices and tags, `payloads.js` holds the `%js_alert%`-style placeholders, `categories.js` holds the labels, and `lib/index.js` exposes all three as a CommonJS module. `vectors.txt` has everything flattened into one file. There are no dependencies to install.

### What are the test.asf, test.hta and similar files in H5SC for?

They are deliberately awkward files for testing filters and parsers, published under `attachments/` and served from html5sec.org. The list includes `test.class`, `test.jar`, `test.svg`, `test.xsl`, `test.eml`, `test.vbs`, `test.swf` and about thirty more, covering formats where extension, MIME type and actual content disagree. `test.class` also has a capital T, which matters on case-sensitive filesystems.

## Sources

- [cure53/H5SC on GitHub](https://github.com/cure53/H5SC)
- [Issues](https://github.com/cure53/H5SC/issues)
- [License: MPL-2.0](https://github.com/cure53/H5SC/blob/main/LICENSE)
- [Project website](https://html5sec.org/)
- [README](https://github.com/cure53/H5SC/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/cure53-h5sc
