Without a permission system, every plugin receives the same access to storage, hooks, and configuration regardless of what it actually needs. Users cannot review what a plugin will do before installing it, operators cannot audit which plugins have access to sensitive data, and the host cannot prevent a plugin from exceeding its intended scope. OWASP A01 (Broken Access Control) and CWE-284 cover exactly this pattern. The absence of declared and enforced permissions also eliminates the ability to revoke capabilities selectively — any restriction requires removing the entire plugin.
High because undeclared and unenforced permissions give every plugin identical unrestricted access, preventing users from making informed installation decisions or operators from applying least-privilege controls.
Add a permissions array to the plugin manifest schema and validate it at load time. Capabilities not listed in the manifest must produce an error when accessed, not silently succeed.
// Plugin manifest:
{
"name": "my-plugin",
"permissions": ["hooks:read", "storage:write", "config:read"]
}
// Host enforces permissions:
function createPluginContext(plugin: PluginManifest): PluginContext {
return {
hooks: plugin.permissions.includes('hooks:read')
? hookRegistry : throwPermissionError('hooks:read'),
storage: plugin.permissions.includes('storage:write')
? scopedStorage(plugin.name) : readOnlyStorage(plugin.name),
};
}
ID: plugin-extension-architecture.isolation-security.sandboxing
Severity: high
What to look for: Check whether plugins declare their required capabilities or permissions, and whether the host enforces these declarations. Look for:
"permissions": ["storage", "network", "file-read"])"permissions": ["tabs", "storage", "https://api.example.com/*"] in manifest.json — enforced by the browser"contributes" capabilities in package.jsonPass criteria: Count all isolation mechanisms for plugin code. Plugins declare required permissions or capabilities. The host verifies these declarations and restricts plugin access to only granted capabilities. Either the host enforces at runtime (capability checks) or at install time (manifest validation). Users can see what permissions a plugin requires.
Fail criteria: No permission system — all plugins have the same unrestricted access. OR permissions are declared but never enforced (purely decorative).
Skip (N/A) when: The plugin system only supports trusted first-party plugins with identical access requirements, AND there are fewer than 5 total plugins. Also skip if the plugin system is a simple middleware chain with no meaningful access differentiation (e.g., Express middleware all gets req/res/next).
Detail on fail: "No permission system exists. All plugins receive the same PluginContext with full access to storage, hooks, and config. There is no way for a plugin to declare what it needs, no way for the host to restrict access, and no way for users to review what a plugin can do before installing it."
Remediation: A permission system doesn't need to be Chrome-extension-level complex. Even a simple capability declaration in the plugin manifest, validated at load time, provides meaningful security.
// Plugin manifest:
{
"name": "my-plugin",
"permissions": ["hooks:read", "storage:write", "config:read"]
}
// Host enforces permissions:
function createPluginContext(plugin: PluginManifest): PluginContext {
return {
hooks: plugin.permissions.includes('hooks:read')
? hookRegistry : throwPermissionError('hooks:read'),
storage: plugin.permissions.includes('storage:write')
? scopedStorage(plugin.name) : readOnlyStorage(plugin.name),
};
}