Skip to content

Commit 363fcf3

Browse files
Copilothotlong
andcommitted
fix: implement path/URL pattern matching in plugin-permission-enforcer
Resolve 3 TODOs by adding glob-based pattern matching: - checkFileRead: match paths against metadata.paths patterns - checkFileWrite: match paths against metadata.paths patterns - checkNetworkAccess: match URLs against metadata.hosts patterns Add matchGlob helper supporting * and ** wildcards. When no restrictions exist in metadata, all paths/URLs are allowed. Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent cbd0cd6 commit 363fcf3

1 file changed

Lines changed: 29 additions & 9 deletions

File tree

packages/core/src/security/plugin-permission-enforcer.ts

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -306,45 +306,65 @@ export class PluginPermissionEnforcer {
306306
});
307307
}
308308

309-
private checkFileRead(capabilities: PluginCapability[], _path: string): boolean {
309+
private matchGlob(pattern: string, str: string): boolean {
310+
const regexStr = pattern
311+
.split('**')
312+
.map(segment => {
313+
const escaped = segment.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
314+
return escaped.replace(/\*/g, '[^/]*');
315+
})
316+
.join('.*');
317+
return new RegExp(`^${regexStr}$`).test(str);
318+
}
319+
320+
private checkFileRead(capabilities: PluginCapability[], path: string): boolean {
310321
// Check if plugin has capability to read this file
311322
return capabilities.some(cap => {
312323
const protocolId = cap.protocol.id;
313324

314325
// Check for file read capability
315326
if (protocolId.includes('protocol.filesystem.read')) {
316-
// TODO: Add path pattern matching
317-
return true;
327+
const paths = cap.metadata?.paths;
328+
if (!Array.isArray(paths) || paths.length === 0) {
329+
return true;
330+
}
331+
return paths.some(p => typeof p === 'string' && this.matchGlob(p, path));
318332
}
319333

320334
return false;
321335
});
322336
}
323337

324-
private checkFileWrite(capabilities: PluginCapability[], _path: string): boolean {
338+
private checkFileWrite(capabilities: PluginCapability[], path: string): boolean {
325339
// Check if plugin has capability to write this file
326340
return capabilities.some(cap => {
327341
const protocolId = cap.protocol.id;
328342

329343
// Check for file write capability
330344
if (protocolId.includes('protocol.filesystem.write')) {
331-
// TODO: Add path pattern matching
332-
return true;
345+
const paths = cap.metadata?.paths;
346+
if (!Array.isArray(paths) || paths.length === 0) {
347+
return true;
348+
}
349+
return paths.some(p => typeof p === 'string' && this.matchGlob(p, path));
333350
}
334351

335352
return false;
336353
});
337354
}
338355

339-
private checkNetworkAccess(capabilities: PluginCapability[], _url: string): boolean {
356+
private checkNetworkAccess(capabilities: PluginCapability[], url: string): boolean {
340357
// Check if plugin has capability to access this URL
341358
return capabilities.some(cap => {
342359
const protocolId = cap.protocol.id;
343360

344361
// Check for network capability
345362
if (protocolId.includes('protocol.network')) {
346-
// TODO: Add URL pattern matching
347-
return true;
363+
const hosts = cap.metadata?.hosts;
364+
if (!Array.isArray(hosts) || hosts.length === 0) {
365+
return true;
366+
}
367+
return hosts.some(h => typeof h === 'string' && this.matchGlob(h, url));
348368
}
349369

350370
return false;

0 commit comments

Comments
 (0)