Communitygithub.com

SSBrouhard/npm-package-release-hardening

Une compétence d'agent qui durcit les paquets npm avant leur publication publique — détecte les secrets inclus, les incohérences de version d'exécution minimale et les déchets dans l'archive. Fonctionne dans tout agent compatible avec les compétences.

Qu'est-ce que npm-package-release-hardening ?

Cette compétence d'agent aide les développeurs à préparer leurs paquets npm pour une publication publique robuste et sécurisée. Elle vérifie systématiquement que le contrat du paquet (package.json) est honnête, que l'archive de publication (tarball) ne contient que les fichiers nécessaires, et que l'environnement d'exécution minimal (engines.node) est correctement testé. Elle inspecte également la configuration GitHub (CI, Dependabot, protection de branche) et applique des durcissements de sécurité sur le dépôt distant. La compétence fonctionne avec npm, pnpm et yarn, et produit un rapport détaillé des actions effectuées, des vérifications réussies et des éventuels blocages. Elle est particulièrement utile pour les développeurs souhaitant publier des paquets de manière fiable, en évitant les erreurs courantes comme l'oubli de fichiers importants, les secrets exposés ou les incohérences de version de Node.js.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add SSBrouhard/npm-package-release-hardening

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Durcissement de la publication de paquets npm

Objectif

Faire passer un paquet npm de « fonctionne en local » à « honnête, inspectable et sûr à publier ». Prioriser la vérification réelle plutôt que les impressions : contenu de l'archive, contrat d'exécution, CI, paramètres GitHub et hygiène des mises à jour de dépendances.

Commencer ici

  1. Confirmer le dépôt exact :
pwd
git status --short --branch
git remote -v
  1. Inspecter la surface du paquet :
cat package.json
ls -la
find .github -maxdepth 3 -type f -print 2>/dev/null
  1. Détecter le gestionnaire de paquets à partir des fichiers de verrouillage :
  • package-lock.json -> npm
  • pnpm-lock.yaml -> pnpm
  • yarn.lock -> yarn

Utiliser les commandes npm ci-dessous par défaut, mais les adapter au gestionnaire de paquets détecté si nécessaire.

Contrat du paquet

Faire en sorte que package.json dise la vérité :

  • name : la cible de publication est intentionnelle et disponible
  • version : la version actuelle prévue pour la publication
  • description, keywords : suffisamment utiles pour la recherche dans le registre
  • license : présent et correspond à LICENSE
  • repository, homepage, bugs : pointent vers le dépôt public. Si l'URL du dépôt public n'est pas encore définitive, signaler ces champs comme une tâche explicite avant publication plutôt que de les omettre silencieusement
  • type, exports, main, bin : correspondent à ce que les utilisateurs importeront ou exécuteront
  • files : limite l'archive aux artefacts publiable
  • engines.node : la version d'exécution minimale que le paquet prend réellement en charge
  • prepublishOnly ou équivalent : empêche la publication d'un artefact de construction obsolète

Pour les paquets CLI, confirmer que la cible bin est construite, exécutable le cas échéant, et testée via la commande que les utilisateurs exécuteront.

Règle de version d'exécution minimale

L'engin Node est une promesse, pas une décoration.

  • Si engines.node indique >=20, CI doit tester Node 20.
  • Maintenir @types/node sur la même ligne majeure que la version d'exécution minimale prise en charge.
  • Préférer le verrouillage exact de @types/node à la dernière mise à jour sur cette ligne d'exécution.
  • Ne pas fusionner les sauts majeurs de @types/node au-dessus de la version d'exécution minimale sauf si vous augmentez également engines.node.
  • engines.node est indicatif : npm émet seulement un avertissement et ne bloque pas l'installation sauf si l'utilisateur définit engine-strict, donc CI sur la version minimale est ce qui applique réellement la promesse.

Pourquoi : Les types Node sont réservés au développement, mais ils modifient ce que TypeScript autorise. @types/node@26 peut permettre la compilation de code tout en utilisant des API qui échouent pour les utilisateurs sur Node 20.

Commandes de vérification

Pour les projets npm :

npm ci
npm run build --if-present
npm test --if-present
npm audit --omit=dev
npm pack --dry-run

Pour pnpm/yarn, utiliser les commandes équivalentes d'installation/construction/test/audit/empaquetage. Si la prise en charge d'audit diffère, le mentionner plutôt que de faire semblant.

Pour les CLI, exécuter également au moins un test de fumée externe :

node dist/path/to/cli.js --help
npm pack --dry-run

Si possible, installer le fichier .tgz empaqueté dans un répertoire temporaire et exécuter le binaire exactement comme un utilisateur le ferait.

Révision de l'archive

npm pack --dry-run est la source de vérité du registre. Vérifier :

  • inclut la sortie construite
  • inclut README.md et LICENSE
  • exclut les fichiers source uniquement, fichiers temporaires, tests, documents privés, jeux de données, bases de données locales, secrets
  • la taille du paquet est raisonnable
  • le chemin bin du CLI apparaît dans l'archive

Si files est absent, l'ajouter. Ne pas se fier à .gitignore comme politique de publication.

Configuration de base pour GitHub

Ajouter ou vérifier :

  • .github/workflows/ci.yml
  • .github/dependabot.yml
  • .github/CODEOWNERS
  • .github/pull_request_template.md
  • SECURITY.md

Utiliser les versions majeures actuellement prises en charge pour les actions appartenant à GitHub. Si Actions avertit qu'un environnement d'exécution d'action est obsolète, mettre à jour la version majeure de l'action après que CI soit passé.

CI devrait généralement inclure :

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@CURRENT_MAJOR
      - uses: actions/setup-node@CURRENT_MAJOR
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npm run build --if-present
      - run: npm test --if-present

Ajuster node-version à la version d'exécution minimale prise en charge du paquet, et remplacer chaque @CURRENT_MAJOR par le tag majeur actuel de l'action (par exemple actions/checkout@v4) — épingler à une version majeure réelle, ne jamais valider le texte de remplacement.

Configuration de base pour Dependabot

Configurer les mises à jour des paquets et des actions GitHub :

version: 2
updates:
  - package-ecosystem: npm
    directory: /
    schedule:
      interval: weekly
    open-pull-requests-limit: 5
    commit-message:
      prefix: deps
      include: scope

  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: weekly
    open-pull-requests-limit: 5
    commit-message:
      prefix: deps
      include: scope

Lorsque Dependabot ouvre des PR immédiatement après le déploiement de la configuration, considérer cela comme une preuve que la configuration est active. Trier les PR ; ne pas fusionner aveuglément tous les contrôles verts.

Tri des PR Dependabot

Utiliser cette règle empirique :

  • Correctif/mineur de dépendance d'exécution : fusionner si les contrôles passent et les notes de version sont banales.
  • Majeur de dépendance d'exécution : inspecter les notes de version et tester le comportement réel du paquet.
  • Majeur d'outil de développement : fusionner si la construction/test/empaquetage passent et que le contrat d'exécution n'est pas modifié.
  • @types/node au-dessus de la version d'exécution minimale : fermer ou remplacer par un épinglage à la version d'exécution minimale.
  • Majeur d'action GitHub Actions : fusionner si CI passe et qu'il supprime les avertissements d'obsolescence.

Si deux PR sont en conflit dans un petit fichier de configuration, fusionner l'une et mettre à jour l'autre, ou appliquer la seconde directement avec un commentaire clair expliquant qu'elle a été remplacée.

Durcissement du dépôt distant GitHub

Appliquer ce que le dépôt/compte prend en charge, puis vérifier les paramètres réels avec gh ou des lectures API.

Paramètres utiles :

gh repo edit OWNER/REPO \
  --delete-branch-on-merge \
  --enable-squash-merge \
  --enable-merge-commit=false \
  --enable-rebase-merge=false \
  --allow-update-branch

gh api --method PUT repos/OWNER/REPO/vulnerability-alerts --silent
gh api --method PUT repos/OWNER/REPO/automated-security-fixes --silent
gh api --method PUT repos/OWNER/REPO/actions/permissions/workflow \
  -f default_workflow_permissions=read \
  -F can_approve_pull_request_reviews=false --silent

Pour les listes d'autorisation d'Actions, privilégier les actions appartenant à GitHub uniquement lorsque le workflow utilise uniquement ces actions. Si des actions tierces sont nécessaires, autoriser explicitement le plus petit ensemble.

Les dépôts publics débloquent généralement davantage de contrôles de sécurité. Les dépôts privés sur les formules gratuites peuvent bloquer :

  • la protection de branche ou les ensembles de règles
  • l'analyse de code
  • l'analyse de secrets
  • la protection contre les push

Signaler clairement les blocages. Ne pas signaler les contrôles indisponibles comme activés.

Protection de branche

Lorsque disponible, protéger la branche par défaut avec :

  • exiger une pull request avant la fusion
  • exiger les contrôles d'état CI
  • exiger que les branches soient à jour si cela convient au projet
  • exiger la résolution des conversations
  • bloquer les push forcés
  • bloquer les suppressions
  • exiger un historique linéaire si la fusion par squash uniquement est utilisée

Après avoir activé la protection, cesser de pousser directement vers main sauf si l'utilisateur le demande explicitement et comprend la dérogation.

Outils de révision/portail PR

Si vous utilisez un outil de révision/portail automatisé, assurez-vous que le dépôt distant a une branche par défaut/de base avant de demander au portail de créer une PR. Les nouveaux dépôts vides ont souvent besoin d'un premier push main d'abord ; sinon, le portail peut valider et pousser une branche de fonctionnalité mais échouer la création de la PR car il n'y a pas de référence de base.

Liste de contrôle avant publication

Avant npm publish :

  • npm whoami affiche le compte prévu
  • npm view NOM_DU_PAQUET name version confirme l'état du nom
  • CI est verte sur le commit en cours de publication
  • npm pack --dry-run a été révisé
  • les exemples d'installation/utilisation du README correspondent au comportement réel
  • repository, homepage et bugs pointent vers le dépôt public réel (ou sont explicitement signalés comme À FAIRE si l'URL n'est pas définitive)
  • aucune alerte de sécurité ou Dependabot bloquant la publication ne subsiste
  • le changement de version est intentionnel, tagué dans git (git tag vX.Y.Z && git push --tags) et reflété dans un CHANGELOG ou une release GitHub
  • les paquets scopés (@scope/nom) sont publiés avec --access public (les paquets scopés par défaut sont restreints/privés)

Pour les comptes utilisant l'authentification web/passkey/2FA :

npm publish --auth-type=web

Privilégier la publication depuis CI avec provenance pour un lien de chaîne d'approvisionnement vérifiable. La provenance nécessite un paquet public, un CI pris en charge tel que GitHub Actions, et l'autorisation id-token: write sur le job :

npm publish --provenance --access public

Après la publication :

npm view NOM_DU_PAQUET version
npm view NOM_DU_PAQUET bin files engines repository --json
npx -y NOM_DU_PAQUET --help

Si publié avec provenance, confirmer que le registre affiche l'attestation de provenance / « Built and signed » sur la page du paquet.

Réponse finale

Signaler uniquement ce qui a été réellement vérifié :

  • contrôles du paquet effectués
  • résultat de l'archive
  • décisions sur les PR de dépendances
  • commits/PR créés ou fusionnés
  • paramètres GitHub confirmés
  • contrôles bloqués par le plan/la visibilité
  • tag de version et statut de provenance, si publié
  • commande de publication ou vérification après publication si encore détenue par l'utilisateur

Skills associés