UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

39 lines (38 loc) • 1.77 kB
import { c as normalizeOptionalLowercaseString } from "./string-coerce-1VuiLaaR.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); return !normalized || IGNORED_INSTALLED_PLUGIN_DIR_NAMES.has(normalized) || normalized.startsWith(".") || normalized.endsWith(".bak") || normalized.includes(".backup-") || normalized.includes(".disabled"); } /** * 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 };