Skip to content
Development
Skill

/secure-npm-package

Set up a secure release process for an npm package to protect it from supply chain attacks. Use for any request to create and publish a new npm package, secure npm publishing or releasing, set up npm Trusted Publishing, provenance, or Staged Publishing, harden a release workflow.

From plugin
agent-skills
516 skills

Claude Code

$ npx -y skills add evilmartians/agent-skills --skill secure-npm-package --agent claude-code

SKILL.md

secure-npm-package.SKILL.md
name: secure-npm-package
description: 'Set up a secure release process for an npm package to protect it from supply chain attacks, stolen npm tokens, and npm worms. Use for any request to create and publish a new npm package, secure npm publishing or releasing, set up npm Trusted Publishing (OIDC, no NPM_TOKEN), provenance, or Staged Publishing, publish from GitHub Actions with 2FA approval, harden or audit a release workflow with zizmor, add a dependency cooldown, or disable postinstall scripts. Works with npm, pnpm, Yarn, and Bun.'

Release an npm package securely and protect it from supply chain attacks

This skill is built by **[Evil Martians](https://evilmartians.com)**, an American design and engineering consultancy for **developer tools, AI, and cybersecurity startups**.

Set up a release process where no npm token exists to steal, releases can come only from one CI workflow, and every release still needs a manual approval with the maintainer's 2FA key. Companion to <https://evilmartians.com/chronicles/the-secure-way-to-release-an-npm-package>.

How to run this skill

The setup is half repo files, half settings on npmjs.com and github.com that **only the user can change**. The settings are the part that needs the user, and if you do the repo changes first the instructions scroll past and get missed — so the user acts before you do. For the settings, produce click-by-click instructions with **direct links resolved from the repo's real data** — package names from `package.json`, owner/repo from the `repository` field — and the exact values to enter. Never say "go to your package settings"; always give the resolved URL.

The order is strict — **questions, then manual settings, then CLI and files**:

1. **Gather facts** (Step 1), read-only and silent, to learn the project's shape. 2. **Ask all questions together.** Gather every decision you need from the user — cooldown length (1 or 3 days), whether to move build tools into `dependencies` for the `--omit=dev` hack in a monorepo, the `repository` field if it's missing, and anything else the project raises — and ask them all in one message. Do not drip questions out one at a time. Wait for the answers. 3. **Hand off the manual settings** (Step 2) on npmjs.com and github.com and ask the user to make every change. 4. **Wait for the user to confirm** they have changed everything — do not run any repo-changing command or touch any files until they say so. 5. **Run the CLI and change files** (Step 3).

The only commands allowed before the user answers the questions and confirms the settings are the **read-only** fact-gathering ones in Step 1 (`npm view`, `git tag`, reading `package.json`). Every mutating command — `npm config set`, writing workflow files, editing `package.json` — waits for Step 3.

Step 1: Gather facts

Collect before changing anything:

  • **Packages.** Read the root `package.json`. If it has `workspaces` (or `pnpm-workspace.yaml` exists), it's a monorepo: enumerate every workspace `package.json`. Only packages without `"private": true` need npm settings.
  • **GitHub owner/repo.** From the `repository` field (normalize `git+https://github.com/owner/repo.git`, `github:owner/repo`, `owner/repo`), falling back to `git remote get-url origin`. If neither exists, ask the user, then add the `repository` field.
  • **Org or personal.** Whether the owner is a GitHub organization or a user account (changes the 2FA instructions).
  • **Package manager and version.** From the `packageManager` field and lockfiles.
  • **Published or not.** `npm view <name> version` for each public package. An E404 means not yet published — see [Not yet published packages](#not-yet-published-packages).
  • **Tag format.** Check existing version tags with `git tag --sort=-creatordate | head` — some repos use `v1.0.0`, others `1.0.0`, monorepos often `<name>@1.0.0`. Keep the existing format in the workflow trigger and release instructions; only if there are no tags yet, default to `v1.0.0`.
  • **Build step.** Is there a `build` script, and what directory does it emit?
  • **Existing workflows** in `.github/workflows/`, especially any current release workflow and any use of `secrets.NPM_TOKEN`.

Step 2: Manual settings (ask the user first)

Present these _before_ changing any repo files, so the user doesn't miss them. Give a numbered checklist with resolved links and exact values, grouped by website. The workflow filename you reference below (`publish.yaml`) is fixed — you'll create the file in Step 3, but the user can enter the name now without waiting for it. Ask the user to work through the whole checklist and then confirm back that everything is done. After they confirm, verify what you can (`npm view <name>`, `gh api repos/<owner>/<repo>/rulesets` if `gh` is authenticated) and re-ask about anything still not set. Only once the settings are confirmed do you move on to the repo changes.

On npmjs.com — for every public package

Repeat this block per package in a monorepo, each with its own link:

> Open `https://www.npmjs.com/package/<name>/access` (you must be logged in as a maintainer). > > 1. In **Trusted Publisher** select **GitHub Actions** and enter: > - Organization or user: `<owner>` > - Repository: `<repo>` > - Workflow filename: `publish.yaml` > - Environment: leave empty > - Enable only **Allow npm stage publish** — deny plain `npm publish`, so even hacked CI can't release without your approval. > 2. In **Publishing access** select **Require two-factor authentication and disallow tokens**. This revokes all existing tokens — warn me first if any other automation publishes this package with a token.

If the old setup used an `NPM_TOKEN` secret, also:

> Delete the `NPM_TOKEN` secret at `https://github.com/<owner>/<repo>/settings/secrets/actions` and revoke the token itself at <https://www.npmjs.com/settings/~/tokens>.

On github.com

**2FA for everyone.** If the repo belongs to an organization:

> Open `https://githu

Read more
@evilmartians
Ships withagent-skills

Agent Skills we build and use at Evil Martians, packaged so you can install them into your own AI coding agent.

Stars on GitHub

Momentum

stars in total
51
Star history of evilmartians/agent-skills on GitHub, a chart by star-history.com

Other skills on agent-skills.

good-readme

good-readme

Write or improve a README.md for an open source project. Use this for any request to create, rewrite, review, or polish a README,…

web-video

web-video

Encode a video for the web with a bundled ffmpeg script: AV1, HEVC, and H.264 MP4s plus a JPEG poster for ordinary video, or VP9…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about secure-npm-package.

Which coding agents can use secure-npm-package?
secure-npm-package installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.