@cannbot-ai/install-helper 0.0.2-beta.32 → 0.0.2-beta.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1027,8 +1027,12 @@ function parseFrontmatter(filePath) {
1027
1027
  const parsed = parseYaml2(yamlBlock);
1028
1028
  if (!parsed || typeof parsed !== "object") return null;
1029
1029
  if (!parsed.name || typeof parsed.name !== "string") return null;
1030
+ const trimmedName = parsed.name.trim();
1031
+ if (!trimmedName || /[\/\\]|\.\./.test(trimmedName) || !/^[a-zA-Z0-9._-]+$/.test(trimmedName)) {
1032
+ return null;
1033
+ }
1030
1034
  return {
1031
- name: parsed.name.trim(),
1035
+ name: trimmedName,
1032
1036
  description: (parsed.description || "").trim()
1033
1037
  };
1034
1038
  } catch {
@@ -1887,9 +1891,18 @@ async function installPlugin(opts) {
1887
1891
  currentPlugin.pluginId,
1888
1892
  currentPlugin.pluginName
1889
1893
  );
1890
- if (backupInfo) {
1891
- logger.success(`${t("backup_created")}: ${backupInfo.filePath}`);
1894
+ if (!backupInfo) {
1895
+ logger.error(t("backup_failed"));
1896
+ return {
1897
+ success: false,
1898
+ pluginId: opts.pluginId,
1899
+ skillsCount: 0,
1900
+ agentsCount: 0,
1901
+ errors: [t("backup_failed")],
1902
+ warnings: []
1903
+ };
1892
1904
  }
1905
+ logger.success(`${t("backup_created")}: ${backupInfo.filePath}`);
1893
1906
  }
1894
1907
  }
1895
1908
  try {
@@ -1980,10 +1993,11 @@ async function installSkills(skillIds, tool, level, repoPath) {
1980
1993
  continue;
1981
1994
  }
1982
1995
  try {
1996
+ const resolvedSource = realpathSync(sourcePath);
1983
1997
  if (existsSync11(targetPath) || isSymlink2(targetPath)) {
1984
1998
  unlinkSync3(targetPath);
1985
1999
  }
1986
- symlinkSync(realpathSync(sourcePath), targetPath);
2000
+ symlinkSync(resolvedSource, targetPath);
1987
2001
  results.push({ skillId, success: true });
1988
2002
  installedIds.push(skillId);
1989
2003
  } catch (error) {
@@ -3016,6 +3030,7 @@ async function installPlugins(pluginIds, tool, level, repoPath, installPath, yes
3016
3030
 
3017
3031
  // src/commands/uninstall.ts
3018
3032
  import { existsSync as existsSync14, unlinkSync as unlinkSync5, rmdirSync as rmdirSync2, readdirSync as readdirSync6, lstatSync as lstatSync4 } from "fs";
3033
+ import { resolve } from "path";
3019
3034
  import chalk11 from "chalk";
3020
3035
  async function uninstallCommand(names, options) {
3021
3036
  const tool = options.tool ? validateTool(options.tool) : "opencode";
@@ -3045,9 +3060,16 @@ async function uninstallCommand(names, options) {
3045
3060
  continue;
3046
3061
  }
3047
3062
  logger.info(`${t("uninstall_in_progress")} ${plugin.displayName}...`);
3063
+ const configRoot = getConfigRoot(record.tool, record.level);
3064
+ const allowedBases = [resolve(configRoot), resolve(record.installPath)];
3065
+ const isSafePath = (p) => {
3066
+ const resolved = resolve(p);
3067
+ return allowedBases.some((base) => resolved === base || resolved.startsWith(base + "/"));
3068
+ };
3048
3069
  let removedFiles = 0;
3049
3070
  let removedDirs = 0;
3050
3071
  for (const filePath of record.files) {
3072
+ if (!isSafePath(filePath)) continue;
3051
3073
  try {
3052
3074
  if (existsSync14(filePath) || isSymlink3(filePath)) {
3053
3075
  unlinkSync5(filePath);
@@ -3058,11 +3080,10 @@ async function uninstallCommand(names, options) {
3058
3080
  } catch {
3059
3081
  }
3060
3082
  }
3061
- const configRoot = getConfigRoot(record.tool, record.level);
3062
- const sortedDirs = [...record.directories].sort((a, b) => b.length - a.length);
3083
+ const sortedDirs = [...record.directories].filter(isSafePath).sort((a, b) => b.length - a.length);
3063
3084
  for (const dirPath of sortedDirs) {
3064
3085
  try {
3065
- if (dirPath === configRoot) {
3086
+ if (resolve(dirPath) === resolve(configRoot)) {
3066
3087
  continue;
3067
3088
  }
3068
3089
  if (existsSync14(dirPath)) {
@@ -3298,7 +3319,7 @@ function createCLI() {
3298
3319
  setLanguage(config.language);
3299
3320
  }
3300
3321
  const program2 = new Command();
3301
- program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.32");
3322
+ program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.33");
3302
3323
  program2.command("init", { isDefault: false }).description("Run interactive installation wizard").action(async () => {
3303
3324
  await initCommand();
3304
3325
  });