a73x

9699882b

docs(server): clarify readme sanitizer comments and tests

alex emery   2026-04-12 19:29


diff --git a/src/server/http/repo/readme.rs b/src/server/http/repo/readme.rs
index 729345e..89289d4 100644
--- a/src/server/http/repo/readme.rs
+++ b/src/server/http/repo/readme.rs
@@ -119,9 +119,10 @@ fn html_escape(s: &str) -> String {
fn sanitize(html: &str) -> String {
    use std::collections::HashSet;

    // Restrict <img src> URL schemes to http/https only — no data:, no javascript:.
    // ammonia::Builder::url_schemes() applies the allowlist to ALL URL-bearing
    // attributes, which is what we want.
    // Restrict the URL scheme allowlist used by ammonia for href/src and the
    // other URL-bearing attributes it tracks. This drops data: image URIs as
    // well as javascript: in any href, including <a href>, which are the
    // attack vectors that matter for a README.
    let mut schemes: HashSet<&str> = HashSet::new();
    schemes.insert("http");
    schemes.insert("https");
@@ -278,6 +279,8 @@ mod tests {

    #[test]
    fn markdown_strips_script_tag() {
        // Passes because pulldown-cmark does not emit raw HTML without
        // ENABLE_UNSAFE_HTML — defense-in-depth canary, not an ammonia test.
        let (repo, _tmp) = repo_with_files(&[
            ("README.md", b"# t\n\n<script>alert(1)</script>\n"),
        ]);
@@ -287,6 +290,8 @@ mod tests {

    #[test]
    fn markdown_strips_javascript_href() {
        // Passes because pulldown-cmark does not emit raw HTML without
        // ENABLE_UNSAFE_HTML — defense-in-depth canary, not an ammonia test.
        let (repo, _tmp) = repo_with_files(&[
            ("README.md", b"[click](javascript:alert(1))\n"),
        ]);
@@ -296,6 +301,8 @@ mod tests {

    #[test]
    fn markdown_strips_onerror_attribute() {
        // Passes because pulldown-cmark does not emit raw HTML without
        // ENABLE_UNSAFE_HTML — defense-in-depth canary, not an ammonia test.
        let (repo, _tmp) = repo_with_files(&[
            ("README.md", b"<img src=\"https://x/y.png\" onerror=\"alert(1)\">\n"),
        ]);
@@ -305,6 +312,8 @@ mod tests {

    #[test]
    fn markdown_strips_iframe() {
        // Passes because pulldown-cmark does not emit raw HTML without
        // ENABLE_UNSAFE_HTML — defense-in-depth canary, not an ammonia test.
        let (repo, _tmp) = repo_with_files(&[
            ("README.md", b"<iframe src=\"https://evil.example/\"></iframe>\n"),
        ]);