Harden ATA package name filtering (#63368)

This commit is contained in:
Jake Bailey
2026-04-07 09:51:51 -07:00
committed by GitHub
parent 5f435057a5
commit c7a0ae102d
5 changed files with 21 additions and 19 deletions

View File

@@ -327,7 +327,8 @@ export const enum NameValidationResult {
NameTooLong,
NameStartsWithDot,
NameStartsWithUnderscore,
NameContainsNonURISafeCharacters,
NameContainsInvalidCharacters,
NameContainsNonURISafeCharacters = NameContainsInvalidCharacters, // for backward compatibility
}
const maxPackageNameLength = 214;
@@ -381,8 +382,8 @@ function validatePackageNameWorker(packageName: string, supportScopedPackage: bo
return NameValidationResult.Ok;
}
}
if (encodeURIComponent(packageName) !== packageName) {
return NameValidationResult.NameContainsNonURISafeCharacters;
if (!/^[\w.-]+$/.test(packageName)) {
return NameValidationResult.NameContainsInvalidCharacters;
}
return NameValidationResult.Ok;
}
@@ -405,8 +406,8 @@ function renderPackageNameValidationFailureWorker(typing: string, result: NameVa
return `'${typing}':: ${kind} name '${name}' cannot start with '.'`;
case NameValidationResult.NameStartsWithUnderscore:
return `'${typing}':: ${kind} name '${name}' cannot start with '_'`;
case NameValidationResult.NameContainsNonURISafeCharacters:
return `'${typing}':: ${kind} name '${name}' contains non URI safe characters`;
case NameValidationResult.NameContainsInvalidCharacters:
return `'${typing}':: ${kind} name '${name}' contains invalid characters`;
case NameValidationResult.Ok:
return Debug.fail(); // Shouldn't have called this.
default:

View File

@@ -1524,10 +1524,11 @@ describe("unittests:: tsserver:: typingsInstaller:: Validate package name:", ()
it("package name cannot start with underscore", () => {
assert.equal(validatePackageName("_foo"), NameValidationResult.NameStartsWithUnderscore);
});
it("package non URI safe characters are not supported", () => {
assert.equal(validatePackageName(" scope "), NameValidationResult.NameContainsNonURISafeCharacters);
assert.equal(validatePackageName("; say Hello from TypeScript! #"), NameValidationResult.NameContainsNonURISafeCharacters);
assert.equal(validatePackageName("a/b/c"), NameValidationResult.NameContainsNonURISafeCharacters);
it("package invalid characters are not supported", () => {
assert.equal(validatePackageName(" scope "), NameValidationResult.NameContainsInvalidCharacters);
assert.equal(validatePackageName("; say Hello from TypeScript! #"), NameValidationResult.NameContainsInvalidCharacters);
assert.equal(validatePackageName("a/b/c"), NameValidationResult.NameContainsInvalidCharacters);
assert.equal(validatePackageName("react'test"), NameValidationResult.NameContainsInvalidCharacters);
});
it("scoped package name is supported", () => {
assert.equal(validatePackageName("@scope/bar"), NameValidationResult.Ok);
@@ -1540,10 +1541,10 @@ describe("unittests:: tsserver:: typingsInstaller:: Validate package name:", ()
assert.deepEqual(validatePackageName("@_scope/bar"), { name: "_scope", isScopeName: true, result: NameValidationResult.NameStartsWithUnderscore });
assert.deepEqual(validatePackageName("@_scope/_bar"), { name: "_scope", isScopeName: true, result: NameValidationResult.NameStartsWithUnderscore });
});
it("scope name in scoped package name with non URI safe characters are not supported", () => {
assert.deepEqual(validatePackageName("@ scope /bar"), { name: " scope ", isScopeName: true, result: NameValidationResult.NameContainsNonURISafeCharacters });
assert.deepEqual(validatePackageName("@; say Hello from TypeScript! #/bar"), { name: "; say Hello from TypeScript! #", isScopeName: true, result: NameValidationResult.NameContainsNonURISafeCharacters });
assert.deepEqual(validatePackageName("@ scope / bar "), { name: " scope ", isScopeName: true, result: NameValidationResult.NameContainsNonURISafeCharacters });
it("scope name in scoped package name with invalid characters are not supported", () => {
assert.deepEqual(validatePackageName("@ scope /bar"), { name: " scope ", isScopeName: true, result: NameValidationResult.NameContainsInvalidCharacters });
assert.deepEqual(validatePackageName("@; say Hello from TypeScript! #/bar"), { name: "; say Hello from TypeScript! #", isScopeName: true, result: NameValidationResult.NameContainsInvalidCharacters });
assert.deepEqual(validatePackageName("@ scope / bar "), { name: " scope ", isScopeName: true, result: NameValidationResult.NameContainsInvalidCharacters });
});
it("package name in scoped package name cannot start with dot", () => {
assert.deepEqual(validatePackageName("@scope/.bar"), { name: ".bar", isScopeName: false, result: NameValidationResult.NameStartsWithDot });
@@ -1551,9 +1552,9 @@ describe("unittests:: tsserver:: typingsInstaller:: Validate package name:", ()
it("package name in scoped package name cannot start with underscore", () => {
assert.deepEqual(validatePackageName("@scope/_bar"), { name: "_bar", isScopeName: false, result: NameValidationResult.NameStartsWithUnderscore });
});
it("package name in scoped package name with non URI safe characters are not supported", () => {
assert.deepEqual(validatePackageName("@scope/ bar "), { name: " bar ", isScopeName: false, result: NameValidationResult.NameContainsNonURISafeCharacters });
assert.deepEqual(validatePackageName("@scope/; say Hello from TypeScript! #"), { name: "; say Hello from TypeScript! #", isScopeName: false, result: NameValidationResult.NameContainsNonURISafeCharacters });
it("package name in scoped package name with invalid characters are not supported", () => {
assert.deepEqual(validatePackageName("@scope/ bar "), { name: " bar ", isScopeName: false, result: NameValidationResult.NameContainsInvalidCharacters });
assert.deepEqual(validatePackageName("@scope/; say Hello from TypeScript! #"), { name: "; say Hello from TypeScript! #", isScopeName: false, result: NameValidationResult.NameContainsInvalidCharacters });
});
});

View File

@@ -200,7 +200,7 @@ Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/projects/pro
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Directory location for typing installer
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Directory location for typing installer
TI:: [hh:mm:ss:mss] Installing typings ["co } }"]
TI:: [hh:mm:ss:mss] 'co } }':: Package name 'co } }' contains non URI safe characters
TI:: [hh:mm:ss:mss] 'co } }':: Package name 'co } }' contains invalid characters
TI:: [hh:mm:ss:mss] All typings are known to be missing or invalid - no need to install more typings
TI:: [hh:mm:ss:mss] Sending response:
{

View File

@@ -654,7 +654,7 @@ TI:: [hh:mm:ss:mss] Sending response:
"projectName": "/dev/null/inferredProject1*"
}
TI:: [hh:mm:ss:mss] Installing typings ["s tream"]
TI:: [hh:mm:ss:mss] 's tream':: Package name 's tream' contains non URI safe characters
TI:: [hh:mm:ss:mss] 's tream':: Package name 's tream' contains invalid characters
TI:: [hh:mm:ss:mss] All typings are known to be missing or invalid - no need to install more typings
TI:: [hh:mm:ss:mss] Sending response:
{

View File

@@ -160,7 +160,7 @@ Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/projects/pro
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Directory location for typing installer
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Directory location for typing installer
TI:: [hh:mm:ss:mss] Installing typings ["; say Hello from TypeScript! #"]
TI:: [hh:mm:ss:mss] '; say Hello from TypeScript! #':: Package name '; say Hello from TypeScript! #' contains non URI safe characters
TI:: [hh:mm:ss:mss] '; say Hello from TypeScript! #':: Package name '; say Hello from TypeScript! #' contains invalid characters
TI:: [hh:mm:ss:mss] All typings are known to be missing or invalid - no need to install more typings
TI:: [hh:mm:ss:mss] Sending response:
{