A plugin system that loads plugins by file-system convention with no manifest requirement cannot perform compatibility checking, dependency resolution, or permission enforcement before executing plugin code. The host has no metadata about a plugin's intended capabilities until after it has already run. ISO 25010 maintainability.modularity requires that components declare their dependencies and interfaces; a missing manifest makes every plugin an opaque blob. Security review of what plugins are installed and what they require becomes impossible.
High because the absence of a required plugin manifest prevents the host from performing any metadata-driven decision — compatibility checking, dependency resolution, or permission scoping — before executing plugin code.
Require a plugin.json manifest alongside every plugin entry point. Validate the manifest schema at load time and reject plugins with missing required fields before importing any plugin code.
{
"name": "my-analytics-plugin",
"version": "1.2.0",
"description": "Adds analytics tracking to all pages",
"author": "Jane Developer",
"engines": { "host-api": "^2.0.0" },
"permissions": ["hooks:read", "storage:write"],
"dependencies": {
"base-plugin": "^1.0.0"
}
}
ID: plugin-extension-architecture.versioning-contracts.plugin-manifest
Severity: high
What to look for: Check whether each plugin is required to provide a structured manifest or metadata file that declares its identity, version, dependencies, and capabilities. Look for:
plugin.json, extension.json, manifest.json, package.json with plugin-specific fieldsname, version, description, authorpackage.json with engines.vscode, contributes, activationEventsmanifest.json with manifest_version, permissions, content_scriptsPlugin Name, Version, Requires at leastmanifest.json with name, id, api, editorTypePass criteria: Count all required manifest fields. Plugins must provide a manifest (or metadata structure) with at minimum: name, version, and host API version requirement. The host validates the manifest on load and rejects plugins with invalid or missing manifests. The manifest schema is documented. At least 3 fields must be required (name, version, entry point).
Fail criteria: No manifest concept — plugins are loaded by convention (file system location or import) with no metadata. The host doesn't know the plugin's name, version, or requirements until it executes the plugin's code.
Skip (N/A) when: The plugin system uses code-only registration where metadata is provided in the registration call (e.g., app.register(myPlugin, { name: 'my-plugin', version: '1.0.0' })) AND this is the documented, intended approach. In this case, check that the registration call requires the metadata fields.
Detail on fail: "Plugins are loaded by scanning the plugins/ directory for index.ts files. No manifest is required — the host imports the module and calls its default export. Plugin name is inferred from the directory name. No version, no dependency declaration, no permissions. The host has no metadata about any plugin until it executes that plugin's code."
Remediation: A manifest is the contract between plugin and host. It lets the host make decisions (compatibility checking, dependency resolution, permission enforcement) BEFORE executing any plugin code.
// Minimum viable plugin manifest (plugin.json):
{
"name": "my-analytics-plugin",
"version": "1.2.0",
"description": "Adds analytics tracking to all pages",
"author": "Jane Developer",
"engines": { "host-api": "^2.0.0" },
"permissions": ["hooks:read", "storage:write"],
"dependencies": {
"base-plugin": "^1.0.0"
}
}