---
id: b34ceec4-fcb1-4990-ac52-eaff51b04907
title: file paths in hrefs are not percent-encoded (# ? % break navigation)
state: closed
labels:
- ui
assignees: []
milestone: null
created: 2026-10-27T17:24:52.487219788Z
updated: 2026-10-27T17:45:41.755216504Z
---
## What

`href_esc` (`src/build.rs:407`) is only HTML escaping; file path segments are never percent-encoded. Git allows `#`, `?`, `%`, spaces and quotes in filenames.

- `a#b.txt` → `/files/a#b.txt.html` requests `/files/a` → 404
- `q?x.txt` → `/files/q?x.txt.html` requests `/files/q` → 404
- spaces happen to work because browsers encode them; `%` can be rejected as a bad escape by `serve`
- raw links, breadcrumb links and directory rows share the helper

## Reproduced

A fixture repo with `a#b.txt`, `a b.txt`, `q?x.txt`; navigation 404s for `#`/`?` while `/files/a%23b.txt.html` returns 200.

## Impact

A repo-controlled filename can make a file unreachable from the UI (or hide it from review); not XSS because `esc` still runs.

## Fix

Add a path-segment percent-encoder (`[A-Za-z0-9-._~]` plus `/`; everything else `%XX` UTF-8) and use it for hrefs only. Keep displayed text escaped. Test `#`, `?`, `%`, space, non-ASCII, quote.
