{"record":{"id":"97c4303bf334aec7","repo":"Mintplex-Labs/anything-llm","slug":"importedplugin-importcommunityitemfromurl-entry","errorCode":null,"errorMessage":"[ImportedPlugin.importCommunityItemFromUrl]: Entry \"${entry.entryName}\" would extract outside plugin folder - not allowed.","messagePattern":"\\[ImportedPlugin\\.importCommunityItemFromUrl\\]: Entry \"(.+?)\" would extract outside plugin folder - not allowed\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"server/utils/agents/imported.js","lineNumber":333,"sourceCode":"          );\n          resolve(false);\n        }\n      });\n\n      const success = await downloadZipFile;\n      if (!success)\n        return { success: false, error: \"Failed to download zip file.\" };\n\n      // Unzip the file to the plugin folder\n      // Note: https://github.com/cthackers/adm-zip?tab=readme-ov-file#electron-original-fs\n      const AdmZip = require(\"adm-zip\");\n      const zip = new AdmZip(zipFilePath);\n\n      // Validate all zip entries to prevent Zip Slip path traversal attacks (CWE-22)\n      for (const entry of zip.getEntries()) {\n        const entryPath = path.resolve(pluginFolder, entry.entryName);\n        if (!isWithin(pluginFolder, entryPath) && pluginFolder !== entryPath) {\n          throw new Error(\n            `[ImportedPlugin.importCommunityItemFromUrl]: Entry \"${entry.entryName}\" would extract outside plugin folder - not allowed.`\n          );\n        }\n      }\n\n      zip.extractAllTo(pluginFolder);\n\n      // We want to make sure specific keys are set to the proper values for\n      // plugin.json so we read and overwrite the file with the proper values.\n      const pluginJsonPath = path.resolve(pluginFolder, \"plugin.json\");\n      const pluginJson = safeJsonParse(fs.readFileSync(pluginJsonPath, \"utf8\"));\n      pluginJson.active = false;\n      pluginJson.hubId = hubId;\n      fs.writeFileSync(pluginJsonPath, JSON.stringify(pluginJson, null, 2));\n\n      console.log(\n        `ImportedPlugin.importCommunityItemFromUrl - successfully imported plugin to agent-skills/${hubId}`\n      );","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/server/utils/agents/imported.js#L315-L351","documentation":"Thrown in ImportedPlugin.importCommunityItemFromUrl while iterating zip entries before extractAllTo. If any entry's resolved path is not within pluginFolder, extraction is aborted. This is a deliberate Zip Slip (CWE-22) mitigation - a hostile community plugin zip could otherwise write files outside the plugins directory.","triggerScenarios":"importCommunityItemFromUrl downloads a .zip and at least one entry has a name like '../../etc/passwd' or an absolute path, so path.resolve(pluginFolder, entry.entryName) escapes pluginFolder.","commonSituations":"Installing a crafted/hostile community agent-skill plugin; a zip produced by a tool that stores absolute entry names; a corrupted zip with malformed entry names.","solutions":["Reject the plugin and report it to the hub maintainer - the zip is unsafe.","If you control the zip, repackage it so all entries are relative and contained (no leading '/' or '..').","Keep this guard; do not bypass it."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// defense already lives in the code; at the call site treat a defensive failure as terminal:\nconst res = await ImportedPlugin.importCommunityItemFromUrl(url);\nif (!res.success && /not allowed/.test(res.error)) throw new Error(`Unsafe plugin zip from ${url}`);","typeGuard":null,"tryCatchPattern":"const res = await ImportedPlugin.importCommunityItemFromUrl(url); if (!res.success && /not allowed/.test(res.error)) return reportUnsafePlugin(url);","preventionTips":["Only install community plugins from trusted sources.","Always validate zip entries before extractAllTo (the code does).","Prefer strictly relative entry paths in zips you produce."],"tags":["security","path-traversal","zip-slip","cwe-22","plugins","agents"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}