refactor: harden remaining plugin manifest reads

This commit is contained in:
Peter Steinberger
2026-02-26 13:12:44 +01:00
parent 892a9c24b0
commit a97cec0018
5 changed files with 144 additions and 7 deletions

View File

@@ -1,6 +1,7 @@
import fs from "node:fs";
import path from "node:path";
import { MANIFEST_KEY } from "../compat/legacy-names.js";
import { openBoundaryFileSync } from "../infra/boundary-file-read.js";
import { isRecord } from "../utils.js";
import type { PluginConfigUiHint, PluginKind } from "./types.js";
@@ -43,18 +44,32 @@ export function resolvePluginManifestPath(rootDir: string): string {
export function loadPluginManifest(rootDir: string): PluginManifestLoadResult {
const manifestPath = resolvePluginManifestPath(rootDir);
if (!fs.existsSync(manifestPath)) {
return { ok: false, error: `plugin manifest not found: ${manifestPath}`, manifestPath };
const opened = openBoundaryFileSync({
absolutePath: manifestPath,
rootPath: rootDir,
boundaryLabel: "plugin root",
});
if (!opened.ok) {
if (opened.reason === "path") {
return { ok: false, error: `plugin manifest not found: ${manifestPath}`, manifestPath };
}
return {
ok: false,
error: `unsafe plugin manifest path: ${manifestPath} (${opened.reason})`,
manifestPath,
};
}
let raw: unknown;
try {
raw = JSON.parse(fs.readFileSync(manifestPath, "utf-8")) as unknown;
raw = JSON.parse(fs.readFileSync(opened.fd, "utf-8")) as unknown;
} catch (err) {
return {
ok: false,
error: `failed to parse plugin manifest: ${String(err)}`,
manifestPath,
};
} finally {
fs.closeSync(opened.fd);
}
if (!isRecord(raw)) {
return { ok: false, error: "plugin manifest must be an object", manifestPath };