fix(mcp-server): URL scheme regex no longer matches Windows drive letters
Change /^[a-z]+:/i to /^[a-z]{2,}:/i in getWriteGateModuleCandidates()
and getWorkflowExecutorModuleCandidates() so single-letter drive prefixes
(C:, D:) are not rejected as URL schemes. All IANA-registered schemes are
2+ characters, so this is a safe narrowing.
Adds regression tests for the regex fix.
Fixes #3942
This commit is contained in:
parent
9b7f151964
commit
9b853ce960
2 changed files with 30 additions and 2 deletions
|
|
@ -974,3 +974,31 @@ describe("workflow MCP tools", () => {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("URL scheme regex — Windows drive letter safety", () => {
|
||||
// This is the regex used in getWriteGateModuleCandidates() and
|
||||
// getWorkflowExecutorModuleCandidates() to reject non-file URL schemes.
|
||||
// It must NOT match single-letter Windows drive prefixes (C:, D:, etc.).
|
||||
const urlSchemeRegex = /^[a-z]{2,}:/i;
|
||||
|
||||
it("rejects multi-letter URL schemes", () => {
|
||||
assert.ok(urlSchemeRegex.test("http://example.com"), "http: should match");
|
||||
assert.ok(urlSchemeRegex.test("https://example.com"), "https: should match");
|
||||
assert.ok(urlSchemeRegex.test("ftp://files.example.com"), "ftp: should match");
|
||||
assert.ok(urlSchemeRegex.test("file:///C:/Users"), "file: should match");
|
||||
assert.ok(urlSchemeRegex.test("node:fs"), "node: should match");
|
||||
});
|
||||
|
||||
it("allows single-letter Windows drive prefixes", () => {
|
||||
assert.ok(!urlSchemeRegex.test("C:\\Users\\user\\project"), "C:\\ should not match");
|
||||
assert.ok(!urlSchemeRegex.test("D:\\other\\path"), "D:\\ should not match");
|
||||
assert.ok(!urlSchemeRegex.test("c:\\lowercase\\drive"), "c:\\ should not match");
|
||||
assert.ok(!urlSchemeRegex.test("E:/forward/slash/path"), "E:/ should not match");
|
||||
});
|
||||
|
||||
it("allows bare filesystem paths", () => {
|
||||
assert.ok(!urlSchemeRegex.test("/usr/local/lib/module.js"), "unix absolute path should not match");
|
||||
assert.ok(!urlSchemeRegex.test("./relative/path.js"), "relative path should not match");
|
||||
assert.ok(!urlSchemeRegex.test("../parent/path.js"), "parent relative path should not match");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ function getWriteGateModuleCandidates(): string[] {
|
|||
const candidates: string[] = [];
|
||||
const explicitModule = process.env.GSD_WORKFLOW_WRITE_GATE_MODULE?.trim();
|
||||
if (explicitModule) {
|
||||
if (/^[a-z]+:/i.test(explicitModule) && !explicitModule.startsWith("file:")) {
|
||||
if (/^[a-z]{2,}:/i.test(explicitModule) && !explicitModule.startsWith("file:")) {
|
||||
throw new Error("GSD_WORKFLOW_WRITE_GATE_MODULE only supports file: URLs or filesystem paths.");
|
||||
}
|
||||
candidates.push(explicitModule.startsWith("file:") ? explicitModule : toFileUrl(explicitModule));
|
||||
|
|
@ -340,7 +340,7 @@ function getWorkflowExecutorModuleCandidates(env: NodeJS.ProcessEnv = process.en
|
|||
const candidates: string[] = [];
|
||||
const explicitModule = env.GSD_WORKFLOW_EXECUTORS_MODULE?.trim();
|
||||
if (explicitModule) {
|
||||
if (/^[a-z]+:/i.test(explicitModule) && !explicitModule.startsWith("file:")) {
|
||||
if (/^[a-z]{2,}:/i.test(explicitModule) && !explicitModule.startsWith("file:")) {
|
||||
throw new Error("GSD_WORKFLOW_EXECUTORS_MODULE only supports file: URLs or filesystem paths.");
|
||||
}
|
||||
candidates.push(explicitModule.startsWith("file:") ? explicitModule : toFileUrl(explicitModule));
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue