Skip to content

Commit 5480dcf

Browse files
JSLEEKRclaude
andcommitted
fix: import alias handling, extensionless files, and Windows path validation
- TypeScript/Python import parsing now correctly handles aliased imports (e.g., `import { foo as bar }`) by extracting the original symbol name - TypeScript import regex now matches `import type { ... }` syntax - PluginRegistry.getForFile returns undefined for extensionless files instead of constructing invalid extension ".undefined" - MCP server path validation now blocks Windows absolute paths (C:\) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 4350133 commit 5480dcf

4 files changed

Lines changed: 17 additions & 5 deletions

File tree

src/mcp/server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ export async function startMCPServer(): Promise<void> {
102102
if (value.includes('\0')) {
103103
throw new Error(`Invalid parameter "${key}": null bytes not allowed`);
104104
}
105-
if (key === 'path' && (value.includes('..') || value.startsWith('/'))) {
105+
if (key === 'path' && (value.includes('..') || value.startsWith('/') || /^[a-zA-Z]:[/\\]/.test(value))) {
106106
throw new Error(`Invalid path parameter: path traversal not allowed. Use relative paths within the project.`);
107107
}
108108
}

src/plugins/plugin-registry.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ export class PluginRegistry {
1010
}
1111

1212
getForFile(filePath: string): LanguagePlugin | undefined {
13-
const ext = '.' + filePath.split('.').pop();
13+
const parts = filePath.split('.');
14+
if (parts.length < 2) return undefined; // no extension (e.g. Makefile)
15+
const ext = '.' + parts.pop();
1416
return this.plugins.get(ext);
1517
}
1618

src/plugins/python.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,12 @@ export class PythonPlugin implements LanguagePlugin {
125125
const toModule = match[1];
126126
const symbolNames = match[2]
127127
.split(',')
128-
.map(s => s.trim())
128+
.map(s => {
129+
const trimmed = s.trim();
130+
// Handle aliased imports: "foo as bar" → take original name "foo"
131+
const asIndex = trimmed.indexOf(' as ');
132+
return asIndex !== -1 ? trimmed.slice(0, asIndex).trim() : trimmed;
133+
})
129134
.filter(Boolean);
130135
imports.push({ fromFile: filePath, toModule, symbols: symbolNames });
131136
}

src/plugins/typescript.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,15 @@ export class TypeScriptPlugin implements LanguagePlugin {
182182

183183
private extractImports(filePath: string, source: string): ImportInfo[] {
184184
const imports: ImportInfo[] = [];
185-
const importRegex = /import\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]/g;
185+
const importRegex = /import\s+(?:type\s+)?\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]/g;
186186
let match;
187187
while ((match = importRegex.exec(source)) !== null) {
188-
const symbolNames = match[1].split(',').map(s => s.trim()).filter(Boolean);
188+
const symbolNames = match[1].split(',').map(s => {
189+
const trimmed = s.trim();
190+
// Handle aliased imports: "foo as bar" → take original name "foo"
191+
const asIndex = trimmed.indexOf(' as ');
192+
return asIndex !== -1 ? trimmed.slice(0, asIndex).trim() : trimmed;
193+
}).filter(Boolean);
189194
imports.push({
190195
fromFile: filePath,
191196
toModule: match[2],

0 commit comments

Comments
 (0)