fix: require an authority for the path-less root form (#2295)
`skill:`, `mailto:` and `skill://` also parse to an empty pathname, with an empty host, so an empty path alone accepted authority-less URIs the guard exists to reject. Accept the empty path only when a host is present (Copilot review round 1). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQ2eszDCUqTmhtTMaznw3W Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
528a37be38
commit
195f209359
2 changed files with 11 additions and 4 deletions
|
|
@ -176,6 +176,11 @@ describe("normalizeSkillUri", () => {
|
|||
expect(normalizeSkillUri("skill:demo/SKILL.md")).toBeUndefined();
|
||||
// Path-less but still opaque: no authority, so it stays rejected.
|
||||
expect(normalizeSkillUri("skill:demo")).toBeUndefined();
|
||||
// Empty path AND no authority — the parser reports `pathname === ""` for
|
||||
// these too, so an empty path alone must not be read as the root form.
|
||||
expect(normalizeSkillUri("skill:")).toBeUndefined();
|
||||
expect(normalizeSkillUri("mailto:")).toBeUndefined();
|
||||
expect(normalizeSkillUri("skill://")).toBeUndefined();
|
||||
});
|
||||
|
||||
it("accepts a path-less authority URI — a skill's root directory (#2295)", () => {
|
||||
|
|
|
|||
|
|
@ -173,7 +173,8 @@ export function isSkillsExtensionSupported(
|
|||
*
|
||||
* A **path-less authority** URI (`skill://data-analysis`) is accepted, and is
|
||||
* not the opaque case above: RFC 3986 gives a URI with an authority an empty
|
||||
* path, and the parser reports that as `pathname === ""`. It has no segments,
|
||||
* path, and the parser reports that as `pathname === ""`. The authority has to
|
||||
* be non-empty — `skill:` parses to an empty path too, with no host. It has no segments,
|
||||
* so nothing survives unnormalized. It is what a skill's root directory looks
|
||||
* like once `/SKILL.md` is removed, so rejecting it made a server echoing that
|
||||
* root back in a directory read read as "outside this skill" when it is the
|
||||
|
|
@ -196,9 +197,10 @@ export function normalizeSkillUri(uri: string): string | undefined {
|
|||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
if (parsed.pathname !== "" && !parsed.pathname.startsWith("/")) {
|
||||
return undefined;
|
||||
}
|
||||
// An empty path is only the root form when an authority carries the identity:
|
||||
// `skill:` and `mailto:` also parse to `pathname === ""`, with no host.
|
||||
const pathlessRoot = parsed.pathname === "" && parsed.host !== "";
|
||||
if (!pathlessRoot && !parsed.pathname.startsWith("/")) return undefined;
|
||||
return canonicalizePercentEncoding(parsed.href);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue