id: c815bb87-3bbd-44eb-9fb1-cb818ec10a8c title: release artifact filenames inject HTML into release pages state: closed labels:
- kind:security assignees: [] milestone: null created: 2026-10-27T18:08:32.834116005Z updated: 2026-10-27T18:20:51.747619077Z
What
artifact_href() interpolates the artifact path without HTML escaping or URL encoding:
src/releases.rs:329-330:
fn artifact_href(version: &str, path: &str) -> String {
format!("/releases/{}/{path}", esc(version))
}
src/releases.rs:363-365 puts this directly into href="...".
Reproduced
Create an artifact file whose name is:
evil" onmouseover="alert(1).txt
Build. The release page contains:
<a href="/releases/v1.0/evil" onmouseover="alert(1).txt">…</a>
A quote and arbitrary markup/event handlers are injected into the page. Filenames are repo-controlled (collect_artifacts accepts any name), so this is stored XSS on the release page.
Also unencoded #/? in paths break the download link.
Impact
Stored XSS / broken artifact links from .forge data.
Fix
- Percent-encode the path for the URL, then HTML-escape the entire href (reuse the path encoder added for #89, or expose it from
build). - Add tests with
",<,#,?, and spaces in artifact names.