Skip to content

Commit 4217436

Browse files
committed
refactor(editor): stricter path validation for oxc.path.server
1 parent aa0689f commit 4217436

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

editors/vscode/client/PathValidator.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,37 @@
1111
* Even though we are not using `shell: true`, it's a good practice to validate the input.
1212
*/
1313
export function validateSafeBinaryPath(binary: string): boolean {
14-
// Check for path traversal
15-
if (binary.includes('..')) {
14+
// Check for path traversal (including Windows variants)
15+
if (binary.includes('..') || binary.includes('.\\')) {
1616
return false;
1717
}
1818

1919
// Check for malicious characters or patterns
2020
// These characters are never expected in a binary path.
2121
// If any of these characters are present, we consider the path unsafe.
22-
const maliciousPatterns = ['$', '&', ';', '|', '`', '>', '<', '!'];
22+
const maliciousPatterns = [
23+
// linux/macOS
24+
'$',
25+
'&',
26+
';',
27+
'|',
28+
'`',
29+
'>',
30+
'<',
31+
'!',
32+
// windows
33+
'%',
34+
'^',
35+
];
2336
for (const pattern of maliciousPatterns) {
2437
if (binary.includes(pattern)) {
2538
return false;
2639
}
2740
}
41+
2842
// Check if the filename contains `oxc_language_server`
2943
// Malicious projects might try to point to a different binary.
30-
if (!binary.includes('oxc_language_server')) {
44+
if (!binary.replaceAll('\\', '/').toLocaleLowerCase().split('/').pop()?.includes('oxc_language_server')) {
3145
return false;
3246
}
3347

editors/vscode/tests/PathValidator.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,19 @@ suite('validateSafeBinaryPath', () => {
99
strictEqual(validateSafeBinaryPath('/opt/oxc_language_server'), true);
1010
});
1111

12+
test('should accept case variations of oxc_language_server', () => {
13+
strictEqual(validateSafeBinaryPath('OXC_LANGUAGE_SERVER'), true);
14+
strictEqual(validateSafeBinaryPath('OXC_LANGUAGE_SERVER.exe'), true);
15+
strictEqual(validateSafeBinaryPath('/usr/local/bin/OXC_LANGUAGE_SERVER'), true);
16+
strictEqual(validateSafeBinaryPath('C:\\Program Files\\OXC_LANGUAGE_SERVER.exe'), true);
17+
});
18+
1219
test('should reject paths with directory traversal', () => {
1320
strictEqual(validateSafeBinaryPath('../oxc_language_server'), false);
1421
strictEqual(validateSafeBinaryPath('../../oxc_language_server'), false);
1522
strictEqual(validateSafeBinaryPath('/usr/local/../bin/oxc_language_server'), false);
1623
strictEqual(validateSafeBinaryPath('..\\oxc_language_server'), false);
24+
strictEqual(validateSafeBinaryPath('.\\oxc_language_server'), false);
1725
});
1826

1927
test('should reject paths with malicious characters', () => {
@@ -24,6 +32,10 @@ suite('validateSafeBinaryPath', () => {
2432
strictEqual(validateSafeBinaryPath('oxc_language_server<input.txt'), false);
2533
strictEqual(validateSafeBinaryPath('oxc_language_server`whoami`'), false);
2634
strictEqual(validateSafeBinaryPath('oxc_language_server!'), false);
35+
36+
// windows specific
37+
strictEqual(validateSafeBinaryPath('oxc_language_server^&pause'), false);
38+
strictEqual(validateSafeBinaryPath('oxc_language_server & del /f *'), false);
2739
});
2840

2941
test('should reject paths not containing oxc_language_server', () => {
@@ -32,5 +44,7 @@ suite('validateSafeBinaryPath', () => {
3244
strictEqual(validateSafeBinaryPath(''), false);
3345
strictEqual(validateSafeBinaryPath('oxc_language'), false);
3446
strictEqual(validateSafeBinaryPath('language_server'), false);
47+
strictEqual(validateSafeBinaryPath('/oxc_language_server/malicious'), false);
48+
strictEqual(validateSafeBinaryPath('C:\\oxc_language_server\\evil.exe'), false);
3549
});
3650
});

0 commit comments

Comments
 (0)