Skill catalog: a GitHub sourceUrl pointing at any .md file installs that file, and blob links with ?plain=1 build an unfetchable URL
Summary
Two defects in the GitHub sourceUrl → raw download URL rewrite for catalog skills. Both predate #6307 (which only moved this code from skills/catalog/ops.rs into skills/catalog/download.rs); tinysweeper surfaced them while reviewing that move.
Class of task broken: installing any registry skill whose catalog entry carries a GitHub sourceUrl — the GitHub, Anthropic, OpenAI, HuggingFace, NVIDIA, gstack and browse.sh sources, roughly 1,500 entries.
1. Any .md blob is accepted as the skill file
download_url_from_source_url appends /SKILL.md only when the rewritten URL does not already end in .md:
"blob" => {
if raw.ends_with("/SKILL.md") || raw.ends_with(".md") {
Some(raw)
} else {
Some(format!("{raw}/SKILL.md"))
}
}crates/openhuman-core/src/skills/catalog/download.rs:103 after #6307, skills/catalog/ops.rs:706 on main @ 700281685 — identical line.
So an entry whose sourceUrl is https://github.com/o/r/blob/main/README.md yields a download URL for README.md, and install fetches that file and tries to parse it as a skill. The installer requires frontmatter with name and description, so the usual outcome is a confusing parse error rather than a wrong skill, but a Markdown file that happens to carry frontmatter would install as one.
Expected: only a blob that is a SKILL.md is taken directly; any other blob path should resolve to the SKILL.md beside it, or be rejected.
2. A blob link with a query or fragment produces a broken URL
The same function splits the source URL as plain text, so ?plain=1 or #L10 stays inside path:
https://github.com/o/r/blob/main/SKILL.md?plain=1
-> https://raw.githubusercontent.com/o/r/main/SKILL.md?plain=1/SKILL.mdbecause SKILL.md?plain=1 does not end in .md, so /SKILL.md is appended after the query. ?plain=1 is what GitHub's own "copy permalink to plain view" produces, and such a URL cannot be fetched.
Expected: strip the query and fragment before rewriting, then decide whether to append /SKILL.md.
Notes
- Both are pure
sourceUrlhandling; the ClawHub file API, the skills.sh repo resolution anddocsPathare unaffected. - Not introduced by #6307: that PR moved the function verbatim to bring
ops.rsunder the 750-line layout limit. Worth fixing separately with a unit test per case indownload_tests.rs, next todownload_url_from_source_url_rejects_non_github_and_malformed.
Source: tinyhumansai/openhuman