Skip to content

fix(security)!: disable node scripts by default - #717

Open
xnyo wants to merge 4 commits into
mainfrom
giuseppe/node-pm-ignore-scripts
Open

fix(security)!: disable node scripts by default#717
xnyo wants to merge 4 commits into
mainfrom
giuseppe/node-pm-ignore-scripts

Conversation

@xnyo

@xnyo xnyo commented May 12, 2026

Copy link
Copy Markdown
Member

Disables scripts before running npm/yarn/pnpm install in the frontend action and playwright action. This improves security and protects against npm supply chain attacks that use pre-install, install or post-install scripts to inject malicious payloads.

If those scripts are required, the new node-package-manager-allow-scripts input can be used to restore the old behavior.

For repositories using pnpm, a better approach than using node-package-manager-allow-scripts is to allowlist only the specific packages that genuinely need build scripts, reducing the blast radius. The setting to use depends on the pnpm version:

pnpm ≤9 and pnpm 10 (before 10.26) — add to package.json:

{
  "pnpm": {
    "onlyBuiltDependencies": ["esbuild", "sharp"]
  }
}

pnpm 10.26+ — add to pnpm-workspace.yaml:

allowBuilds:
  esbuild: true
  sharp: true

pnpm 11+ — same as above (onlyBuiltDependencies is removed in pnpm 11, allowBuilds is the only supported option):

allowBuilds:
  esbuild: true
  sharp: true

Note: pnpm 10+ already disables lifecycle scripts by default for all dependencies, so --ignore-scripts has no additional effect for projects on pnpm 10 or later. The CI change is most impactful for npm and yarn projects.

@xnyo xnyo self-assigned this May 12, 2026
@xnyo xnyo added the security The issue is related to a security vulnerability label May 12, 2026
Comment thread .github/workflows/ci.yml
run: |
if [ -f "./cspell.config.json" ]; then
npx --yes cspell@6.13.3 -c cspell.config.json "**/*.{ts,tsx,js,go,md,mdx,yml,yaml,json,scss,css}"
npx --yes --ignore-scripts cspell@6.13.3 -c cspell.config.json "**/*.{ts,tsx,js,go,md,mdx,yml,yaml,json,scss,css}"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cspell doesn't have any lifecycle scripts for install, so it's safe to always skip the, regardless of the value of node-package-manager-allow-scripts

@xnyo xnyo moved this from 📬 Triage to 🔬 In review in Grafana Catalog Team May 12, 2026
@xnyo xnyo moved this from 🔬 In review to 🧑‍💻 In development in Grafana Catalog Team May 12, 2026
@xnyo
xnyo marked this pull request as ready for review May 12, 2026 10:57
@xnyo
xnyo requested a review from a team as a code owner May 12, 2026 10:57
@xnyo
xnyo requested review from leventebalogh, sunker and wbrowne May 12, 2026 10:57
@xnyo xnyo moved this from 🧑‍💻 In development to 🔬 In review in Grafana Catalog Team May 12, 2026
@tolzhabayev

Copy link
Copy Markdown
Contributor

@xnyo stale?

@mckn mckn left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Some things to consider:

  1. Duplicated logic (playwright.yml and actions/internal/plugins/frontend/action.yml) — the entire "Configure package manager script policy" step (~25 lines, including all the comments) is copy-pasted verbatim between the two files. Since it's already the same repo, this could be extracted into a small shared composite action (e.g. actions/internal/plugins/node-install-cmd) that both call, so future fixes/tweaks don't need to be applied twice. Given it's GH Actions and duplication across workflow/action boundaries is common, this is a nice-to-have rather than a blocker.

  2. Inconsistent coverage of other npx invocations — npx google-artifactregistry-auth --credential-config ./.npmrc (present in both playwright.yml and frontend/action.yml) still runs without --ignore-scripts, while the cspell npx call in ci.yml was updated. If the goal is blanket protection against malicious install/lifecycle scripts from any npx-fetched package, this call is an inconsistency worth a deliberate decision (even if the answer is "it's a trusted Google package, out of scope").

  3. Debug annotation naming is a bit off — the printf '::act-debug::...' lines use ::act-debug:: as if it were a GitHub Actions workflow command, but act-debug isn't a real GH Actions command; it appears to be a convention specific to the act-based test harness (act.AnnotationLevelDebug in the new test) for asserting internal state. Worth a one-line comment noting this is test-harness-only tooling and not a real GHA annotation, so future readers don't mistake it for standard Actions output.

  4. Env vars persist for the rest of the job — setting NPM_CONFIG_IGNORE_SCRIPTS/YARN_ENABLE_SCRIPTS via $GITHUB_ENV affects every subsequent step in the job (lint, build, etc.), not just the install step. This is almost certainly intentional ("belt-and-suspenders") and is safe for npm run <script> (explicit run-scripts still execute; only implicit pre/post hooks are suppressed), but it's worth confirming no downstream step in real plugin repos relies on install-time hooks running again mid-job (e.g., a postinstall-triggered codegen step invoked a second time by a later npm install).

  5. TODO acknowledged, not blocking: the test file has an explicit TODO noting Yarn Berry's --ignore-scripts-rejection path isn't covered by a real fixture yet — reasonable to leave as follow-up given no simple-frontend-yarn-berry fixture currently exists, but worth a tracking issue so it doesn't get forgotten given it's the one CLI-flag branch with no test coverage today.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

security The issue is related to a security vulnerability

Projects

Status: 🔬 In review

Development

Successfully merging this pull request may close these issues.

4 participants