fix: keep the 404 GitHub link in the repository

The hint decoded the address before building the link, so an encoded /blob/..%2F..%2Fother/x resolved to another account's page. The path is now split before it is decoded, each segment is checked and encoded, and the link is kept only under /Abdess/retrobios/.
This commit is contained in:
Abdessamad Derraz committed 2026-11-10 00:53:35 +01:00
1 parent baa89556d9
commit e858e695d3
2 files changed
+64 -4

No files matched your search

+34
View File
@@ -700,6 +700,40 @@ def _short_unmarked(html: str) -> list[str]:
return found
class AGithubPathStaysInTheRepository(unittest.TestCase):
"""The 404 hint linked a GitHub path typed under this site: an encoded
/blob/..%2F..%2Fother/x resolved to another account's page."""
def _hrefs(self, paths: list[str]) -> list:
source = _read(SITE_TS)
rule = source[source.index("function githubPathHref"):source.index("// End of the GitHub path rule.")]
out = _node_typescript(rule + f"console.log(JSON.stringify({json.dumps(paths)}.map(githubPathHref)));")
return json.loads(out)
def test_a_path_of_the_repository_is_linked(self):
self.assertEqual(self._hrefs([
"blob/main/bios/Sony/PlayStation/scph5501.bin",
"tree/main/bios/",
"raw/main/bios/3D%20Realms/x.zip",
]), [
"https://github.com/Abdess/retrobios/blob/main/bios/Sony/PlayStation/scph5501.bin",
"https://github.com/Abdess/retrobios/tree/main/bios",
"https://github.com/Abdess/retrobios/blob/main/bios/3D%20Realms/x.zip",
])
def test_a_path_leaving_the_repository_gets_no_link(self):
self.assertEqual(self._hrefs([
"blob/..%2F..%2F..%2Fother/x",
"blob/../../../other/x",
"blob/main/%2E%2E/%2E%2E/%2E%2E/other",
"blob/main/a%2Fb",
"blob/main/a%5Cb",
"blob/main//x",
"blob/main/%E0%A4%A",
"issues/1",
]), [None] * 8)
class OneVerdictWhateverHash(unittest.TestCase):
"""2.1: the SHA1 of scph5501.bin found 4 setups, its MD5 12, its SHA256
none (V1, J4). A setup's list writes one hash of a file."""
+30 -4
View File
@@ -1306,6 +1306,31 @@ const startDownloads = () => {
}
};
// The GitHub page of a repository path typed under this site, or null.
// The address is split before it is decoded, so an encoded slash stays in
// its segment, and a segment that decodes to nothing, '.', '..' or a slash
// gives no link: /blob/..%2F..%2Fother/x led to another account's page.
function githubPathHref(raw: string): string | null {
const match = raw.replace(/\/$/, '').match(/^(blob|tree|raw)\/(.+)$/);
if (!match) return null;
const kind = match[1] === 'raw' ? 'blob' : match[1];
const segments: string[] = [];
for (const piece of match[2].split('/')) {
let segment: string;
try {
segment = decodeURIComponent(piece);
} catch {
return null;
}
if (!segment || segment === '.' || segment === '..' || /[\\/]/.test(segment)) return null;
segments.push(encodeURIComponent(segment));
}
const prefix = `/Abdess/retrobios/${kind}/`;
const url = new URL(`https://github.com${prefix}${segments.join('/')}`);
return url.origin === 'https://github.com' && url.pathname.startsWith(prefix) ? url.href : null;
}
// End of the GitHub path rule.
// The 404 page: a search button, and what the address it was asked for
// looks like. The addresses readers reached (counted, wiki/privacy.md): a
// command pasted as a link (/i.ps1%20%7C%20iex), a file name under files/,
@@ -1343,7 +1368,8 @@ const notFound = () => {
const hint = document.getElementById('rb-notfound-hint');
if (!hint) return;
const base = siteRoot().pathname;
let rest = location.pathname.startsWith(base) ? location.pathname.slice(base.length) : location.pathname;
const raw = location.pathname.startsWith(base) ? location.pathname.slice(base.length) : location.pathname;
let rest = raw;
try {
rest = decodeURIComponent(rest);
} catch {
@@ -1368,10 +1394,10 @@ const notFound = () => {
return;
}
// A GitHub path: the files are browsed on the repository.
const github = rest.match(/^(blob|tree|raw)\/(.+)$/);
if (github) {
const href = githubPathHref(raw);
if (href) {
const link = document.createElement('a');
link.href = `https://github.com/Abdess/retrobios/${github[1] === 'raw' ? 'blob' : github[1]}/${github[2]}`;
link.href = href;
link.textContent = 'the same path on GitHub';
show(hintLine('This is a path of the GitHub repository. Open ', link, '.'));
return;