UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

45 lines (44 loc) • 1.87 kB
import { c as normalizeOptionalLowercaseString } from "./string-coerce-6kR-86XC.mjs"; import path from "node:path"; import fs from "node:fs/promises"; //#region src/security/installed-plugin-dirs.ts const IGNORED_INSTALLED_PLUGIN_DIR_NAMES = /* @__PURE__ */ new Set(["node_modules", ".openclaw-install-backups"]); /** * Decide whether an installed-plugin directory should be skipped by security audits. * This filters generated install debris while keeping real plugin roots visible to scans. */ function shouldIgnoreInstalledPluginDirName(name) { const normalized = normalizeOptionalLowercaseString(name); if (!normalized) return true; if (IGNORED_INSTALLED_PLUGIN_DIR_NAMES.has(normalized)) return true; if (normalized.startsWith(".")) return true; if (normalized.endsWith(".bak")) return true; if (normalized.includes(".backup-")) return true; if (normalized.includes(".disabled")) return true; return false; } /** * Lists installed plugin directories under the state extensions dir. Read * failures surface through `onReadError` so audits can report scan problems, * except a missing extensions dir, which is the normal no-plugins state. */ async function listInstalledPluginDirs(params) { const extensionsDir = path.join(params.stateDir, "extensions"); if (!(await fs.stat(extensionsDir).catch((err) => { const code = err?.code; if (code !== "ENOENT" && code !== "ENOTDIR") params.onReadError?.(err); return null; }))?.isDirectory()) return { extensionsDir, pluginDirs: [] }; return { extensionsDir, pluginDirs: (await fs.readdir(extensionsDir, { withFileTypes: true }).catch((err) => { params.onReadError?.(err); return []; })).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => !shouldIgnoreInstalledPluginDirName(name)).filter(Boolean) }; } //#endregion export { listInstalledPluginDirs as t };