In this article
Les 10 commandes npm incontournables que tout développeur JavaScript devrait connaître
Les commandes avancées simplifient les tâches complexes et offrent une meilleure visibilité sur les dépendances et les configurations de votre projet. De la détection des vulnérabilités à la génération d’une nomenclature logicielle (SBOM), ces commandes vous aideront à gagner en efficacité et à développer en gardant la sécurité à l’esprit.
Le gestionnaire de paquets npm est un outil indispensable dans l’écosystème JavaScript et Node.js. Il constitue la pierre angulaire de la gestion des dépendances, des scripts et des configurations qui facilitent les workflows de développement. Que vous développiez un petit projet ou une application à grande échelle, maîtriser les commandes npm peut considérablement améliorer votre productivité et la qualité de votre code.
Snyk pour sécuriser vos projets JavaScript
La sécurité est un aspect essentiel du développement logiciel moderne. Snyk s’intègre parfaitement à votre workflow de développement JavaScript pour détecter les vulnérabilités dans votre code source, les paquets open source, les images de conteneur et les configurations cloud.
En examinant ces commandes npm power-user, pensez à renforcer votre posture de sécurité en créant un compte Snyk gratuit.
1. Transmettre des options de ligne de commande à un script npm run avec --
Dans les projets complexes, vous devez souvent transmettre des options de ligne de commande supplémentaires aux scripts exécutés avec npm run. C’est particulièrement utile lorsque vous souhaitez modifier le comportement d’un script sans le changer lui-même. Vous pouvez, par exemple, changer l’environnement à la volée, activer le débogage ou transmettre des options de configuration.
Exemple d’utilisation dans un script npm run
Pour transmettre des options de ligne de commande au programme exécuté par un script npm run, utilisez la syntaxe du double tiret --. Tout ce qui suit -- est transmis directement au script.
Voici un exemple simple pour illustrer cela :
{
"scripts": {
"start": "node app.js"
}
}
Vous pouvez exécuter le script start et transmettre des options supplémentaires au programme app.js comme suit :
npm run start -- --port=3000 --env=productionDans ce cas, --port=3000 et --env=production sont transmis au script app.js en tant qu’arguments positionnels.
Considérations de sécurité
La transmission dynamique d’options peut être très utile, mais elle comporte aussi des risques de sécurité. Assurez-vous que les scripts et les options transmis sont sécurisés, qu’ils n’exposent aucune information sensible et qu’ils ne permettent pas de comportements indésirables. Validez et assainissez toujours les entrées lorsque vous utilisez des options dynamiques.
2. Examiner les arbres de dépendances avec npm ls
En tant que développeur JavaScript, vous devez comprendre l’arbre de dépendances de votre projet afin d’identifier les paquets concernés par des vulnérabilités. La commande npm ls fait partie de ces commandes avancées qui vous aident à examiner l’arbre de dépendances de votre projet. Elle affiche une représentation arborescente ASCII de tous les paquets dont dépend votre projet, avec leurs versions et leurs relations hiérarchiques.
Syntaxe et options de filtrage de la commande npm ls
La syntaxe de base de la commande npm ls est la suivante :
npm ls [<package-name>]Cette commande peut répertorier toutes les dépendances ou se concentrer sur un paquet particulier en indiquant son nom. Vous pouvez également filtrer les résultats pour afficher uniquement les dépendances de production ou de développement à l’aide des options --production ou --development, respectivement.
Exemple : trouver les dépendances affectées par une vulnérabilité donnée
Imaginons que vous ayez découvert une vulnérabilité par déni de service dans le paquet ms npm. Pour identifier les dépendances de votre projet affectées par cette version vulnérable, utilisez la commande npm ls :
Cette commande affiche l’arbre de dépendances et indique où ms est utilisé. Voici un exemple de résultat :
> npm ls ms
goof@1.0.1 /Users/lirantal/projects/repos/nodejs-goof
├─┬ express-session@1.17.2
│ └─┬ debug@2.6.9
│ └── ms@2.0.0
├─┬ express@4.12.4
│ ├─┬ debug@2.2.0
│ │ └── ms@0.7.1
│ ├─┬ finalhandler@0.3.6
│ │ └─┬ debug@2.2.0
│ │ └── ms@0.7.1
│ └─┬ send@0.12.3
│ ├─┬ debug@2.2.0
│ │ └── ms@0.7.1 deduped
│ └── ms@0.7.1
├─┬ humanize-ms@1.0.1
│ └── ms@0.6.2
├─┬ method-override@3.0.0
│ └─┬ debug@3.1.0
│ └── ms@2.0.0
├─┬ mongoose@4.2.4
│ ├─┬ mquery@1.6.3
│ │ └─┬ debug@2.2.0
│ │ └── ms@0.7.1
│ └── ms@0.7.1
├─┬ morgan@1.10.0
│ └─┬ debug@2.6.9
│ └── ms@2.0.0Vous pouvez aussi préciser votre recherche et chercher ms@0.7.1.
3. Comprendre les dépendances transitives avec npm why
Dans les grands projets JavaScript, la gestion des dépendances peut devenir complexe, notamment lorsqu’il s’agit de dépendances transitives : celles qui ne figurent pas directement dans votre package.json, mais dont vos dépendances directes ont besoin.
Identifier la raison de la présence d’un paquet particulier dans votre projet peut être essentiel pour déboguer et sécuriser votre application. La commande npm why répond à ce besoin en expliquant en détail pourquoi un paquet donné est installé.
La commande npm why est simple à utiliser. Voici sa syntaxe de base :
> npm why ms@0.7.1
ms@0.7.1
node_modules/send/node_modules/ms
ms@"0.7.1" from send@0.12.3
node_modules/send
send@"0.12.3" from express@4.12.4
node_modules/express
express@"4.12.4" from the root project
send@"0.12.3" from serve-static@1.9.3
node_modules/serve-static
serve-static@"~1.9.3" from express@4.12.4
node_modules/express
express@"4.12.4" from the root project
ms@"0.7.1" from debug@2.2.0
node_modules/send/node_modules/debug
debug@"~2.2.0" from send@0.12.3
node_modules/send
send@"0.12.3" from express@4.12.4
node_modules/express
express@"4.12.4" from the root project
send@"0.12.3" from serve-static@1.9.3
node_modules/serve-static
serve-static@"~1.9.3" from express@4.12.4
node_modules/express
express@"4.12.4" from the root projectComme vous pouvez le constater, cette commande npm explique en détail pourquoi ms est inclus et affiche la chaîne de dépendances qui a conduit à son installation.
Conseils supplémentaires pour la commande npm why
Précisez la version : si vous connaissez la version à l’origine du problème, ajoutez-la à la commande pour obtenir des résultats plus précis :
npm why ms@0.7.1Utilisez la sortie JSON : pour obtenir des résultats plus riches et détaillés, qui incluent les types de dépendances et d’autres métadonnées, utilisez l’option
--json:
npm why ms@0.7.1 --jsonCela peut être particulièrement utile pour les scripts automatisés ou les analyses plus approfondies.
Comprendre les dépendances transitives est essentiel pour maintenir une base de code sécurisée et efficace. Des outils comme Snyk Open Source peuvent aussi vous aider en analysant vos dépendances à la recherche de vulnérabilités connues et en vous fournissant des informations exploitables. Créez un compte Snyk gratuit ici pour sécuriser vos projets dès aujourd’hui.
Si vous débutez dans la gestion des dépendances et souhaitez comprendre le fonctionnement des fichiers lock, l’article « Qu’est-ce que package-lock.json et comment fonctionnent les fichiers lock pour les paquets yarn et npm ? » peut également vous être utile. Il explique le versionnage sémantique, les fichiers shrinkwrap, les fichiers lock qui divergent et d’autres concepts importants liés aux fichiers lock npm.
4. Répertorier les scripts de cycle de vie disponibles avec npm run
Lorsque vous travaillez sur un projet JavaScript ou Node.js, vous devez souvent exécuter divers scripts définis dans votre fichier package.json, n’est-ce pas ? Par exemple, npm run test ou npm run build.
Cependant, retenir le nom exact de tous ces scripts de cycle de vie npm lifecycle peut être difficile, surtout dans les grands projets ou si vous travaillez régulièrement sur plusieurs projets (backend et frontend, par exemple).
La commande npm run vient à la rescousse ! Elle résout ce problème en répertoriant tous les scripts de cycle de vie disponibles dans votre projet. Vous voyez ainsi facilement quels scripts sont disponibles et comment les exécuter.
Voici un exemple pratique pour afficher tous les scripts npm run d’un projet :
> npm run
Lifecycle scripts included in goof@1.0.1:
start
NODE_OPTIONS=--openssl-legacy-provider node app.js
test
snyk test
available via `npm run-script`:
dev
NODE_OPTIONS=--openssl-legacy-provider nodemon ./app.js
build
browserify -r jquery > public/js/bundle.js
cleanup
mongo express-todo --eval 'db.todos.remove({});'Le résultat répertorie tous les scripts npm run disponibles dans le projet, ainsi que les commandes qu’ils exécutent. Vous gagnez ainsi quelques secondes en évitant d’ouvrir le fichier package.json dans votre IDE ou votre terminal !
5. Rechercher des dépendances de manière avancée avec npm query
J’imagine qu’il s’agit d’une fonctionnalité peu connue du gestionnaire de paquets npm, qui vous permet de filtrer et de sélectionner des dépendances selon leurs attributs. Cela peut être utile pour comprendre l’impact d’une dépendance tierce ou effectuer des actions ciblées, mais trouver la bonne dépendance npm peut s’avérer délicat.
Introduite dans npm@8, la commande npm query permet d’effectuer des recherches avancées dans les dépendances à l’aide d’un langage de requête. Elle vous permet de filtrer et de sélectionner des dépendances selon leurs attributs, ce qui facilite la gestion et l’audit des dépendances de votre projet.
Utiliser la syntaxe de npm query
La syntaxe de la commande npm query est la suivante :
npm query "<query>"La partie requête est la plus délicate. Ce langage (DSL) prend en charge différents attributs et opérateurs pour affiner votre recherche. Vous pouvez, par exemple, filtrer les dépendances selon leurs scripts de cycle de vie, leurs versions ou d’autres métadonnées fournies par les paquets tiers.
Exemple : trouver les dépendances dotées d’un script npm postinstall
Imaginons que vous souhaitiez trouver toutes les dépendances de votre projet qui possèdent un script postinstall. Cette recherche peut vous aider à identifier les paquets qui exécutent des scripts pendant l’installation, ce qui peut présenter des risques de sécurité ou affecter votre processus de build. Vous pouvez utiliser la requête suivante :
npm query ":attr(scripts, [postinstall])"Cette commande renvoie la liste des dépendances dont le fichier package.json contient un script postinstall.
Le résultat peut ressembler à ceci :
[
{
"name": "some-package",
"version": "1.0.0",
"scripts": {
"postinstall": "node setup.js"
}
}
]Dans cet exemple, some-package possède un script postinstall qui exécute node setup.js. Ces informations peuvent vous aider à auditer vos dépendances pour détecter d’éventuels risques de sécurité ou comportements indésirables.
Conseil supplémentaire : utilisez l’outil open source de sécurisation de la chaîne d’approvisionnement logicielle npq tool pour repérer, avant l’installation, les dépendances dotées de scripts postinstall ou preinstall et agir de manière préventive.
6. Comparer des versions avec npm diff
Comprendre les différences entre les versions d’un paquet est essentiel pour maintenir une base de code sécurisée et stable. C’est utile si vous souhaitez déterminer les changements apportés entre deux versions d’un paquet.
La commande npm diff vous aide à comparer deux versions d’un paquet. Elle est particulièrement utile pour repérer d’éventuels problèmes de sécurité, des fonctionnalités obsolètes, des dépendances modifiées ou des changements importants susceptibles d’affecter votre application.
La commande npm diff est simple à utiliser et ressemble à la commande git diff :
npm diff --diff=<package@version1> --diff=<package@version2>Imaginons que vous souhaitiez comparer les changements entre les versions 2.1.2 et 2.1.3 du paquet ms. Exécutez la commande suivante :
npm diff --diff=ms@2.1.3 --diff=ms@2.1.2Le résultat affiche les différences dans le code, comme avec la commande git diff :
diff --git a/index.js b/index.js
index v2.1.3..v2.1.2 100644
--- a/index.js
+++ b/index.js
@@ -23,7 +23,7 @@
* @api public
*/
-module.exports = function (val, options) {
+module.exports = function(val, options) {
options = options || {};
var type = typeof val;
if (type === 'string' && val.length > 0) {
diff --git a/package.json b/package.json
index v2.1.3..v2.1.2 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
{
"name": "ms",
- "version": "2.1.3",
+ "version": "2.1.2",
"description": "Tiny millisecond conversion utility",
- "repository": "vercel/ms",
+ "repository": "zeit/ms",
"main": "./index",
"files": [
"index.js"
@@ -28,11 +28,10 @@
},
"license": "MIT",
"devDependencies": {
- "eslint": "4.18.2",
+ "eslint": "4.12.1",
"expect.js": "0.3.1",
"husky": "0.14.3",
"lint-staged": "5.0.0",
- "mocha": "4.0.1",
- "prettier": "2.0.5"
+ "mocha": "4.0.1"
}
}
diff --git a/license.md b/license.md
index v2.1.3..v2.1.2 100644
--- a/license.md
+++ b/license.md
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2020 Vercel, Inc.
+Copyright (c) 2016 Zeit, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/readme.md b/readme.md
index v2.1.3..v2.1.2 100644
--- a/readme.md
+++ b/readme.md
@@ -1,6 +1,7 @@
# ms
-
+[](https://travis-ci.org/zeit/ms)
+[](https://spectrum.chat/zeit)
Use this package to easily convert various time formats to milliseconds.Vous pouvez maintenant examiner les changements pour vérifier qu’ils n’introduisent aucune vulnérabilité de sécurité ni rupture de compatibilité.
7. Créer et analyser des SBOM avec npm sbom
SBOM signifie Software Bill of Materials (nomenclature logicielle) : il s’agit d’une liste détaillée de tous les composants et dépendances de votre logiciel, comparable à une recette qui répertorie tous les ingrédients.
Cette transparence aide à détecter les vulnérabilités potentielles et à garantir la conformité aux différentes normes de sécurité. Les SBOM sont particulièrement importants pour la sécurité de la chaîne d’approvisionnement, où connaître les composants de votre logiciel est essentiel pour gérer les risques et instaurer la confiance.
Les équipes de sécurité utilisent souvent les SBOM pour garantir la conformité aux normes et réglementations du secteur, comme le décret présidentiel sur la cybersécurité.
Utiliser npm sbom et l’intégrer à Snyk
La commande npm sbom génère un SBOM pour votre projet ou votre espace de travail.
Elle est particulièrement utile lorsqu’elle est associée à Snyk, un outil de sécurité pour les développeurs qui détecte les vulnérabilités dans le code source, les paquets open source, les images de conteneur et les configurations cloud.
Vous pouvez utiliser npm comme gestionnaire de paquets pour générer un SBOM de toutes les dépendances du projet, puis envoyer l’ensemble de l’arbre de dépendances à Snyk pour détecter les vulnérabilités. Et tout cela se fait directement depuis l’interface de ligne de commande.
Voici la syntaxe de base pour créer un SBOM au format CycloneDX avec npm sbom :
npm sbom --sbom-format cyclonedx > sbom.cdx.jsonVous pouvez maintenant analyser ce SBOM à la recherche de vulnérabilités avec Snyk :
snyk sbom test --experimental --file=sbom.cdx.jsonCette commande génère la liste des vulnérabilités détectées dans le SBOM, ainsi que leur niveau de gravité :
× [HIGH] Regular Expression Denial of Service (ReDoS)
Introduced through: pkg:npm/negotiator@0.2.8
URL: https://security.snyk.io/vuln/npm:negotiator:20160616
× [HIGH] Uninitialized Memory Exposure
Introduced through: pkg:npm/npmconf@0.0.24
URL: https://security.snyk.io/vuln/npm:npmconf:20180512
× [HIGH] Prototype Override Protection Bypass
Introduced through: pkg:npm/qs@2.2.4
URL: https://security.snyk.io/vuln/npm:qs:20170213
× [CRITICAL] Incomplete List of Disallowed Inputs
Introduced through: pkg:npm/babel-traverse@6.26.0
URL: https://security.snyk.io/vuln/SNYK-JS-BABELTRAVERSE-5962463
× [CRITICAL] Prototype Pollution
Introduced through: pkg:npm/handlebars@4.0.11
URL: https://security.snyk.io/vuln/SNYK-JS-HANDLEBARS-534988
× [CRITICAL] Server-side Request Forgery (SSRF)
Introduced through: pkg:npm/parse-url@5.0.1
URL: https://security.snyk.io/vuln/SNYK-JS-PARSEURL-2936249
× [CRITICAL] Arbitrary File Write via Archive Extraction (Zip Slip)
Introduced through: pkg:npm/adm-zip@0.4.7
URL: https://security.snyk.io/vuln/npm:adm-zip:20180415
╭──────────────────────────────────────────────────────────────────────╮
│ Test summary │
│ Organization: a30b7399-4e0c-4f6e-ba84-b27e131db54c │
│ Test type: Software Bill of Materials │
│ Path: sbom.cdx.json │
│ │
│ Open issues: 148 [ 4 CRITICAL 64 HIGH 72 MEDIUM 8 LOW ] │
╰──────────────────────────────────────────────────────────────────────╯8. Épingler des dépendances à l’aide des overrides dans package.json
Comme vous l’avez peut-être déjà constaté, la gestion des dépendances peut avoir ses avantages et ses inconvénients. Si npm facilite considérablement l’ajout et la gestion des dépendances, votre projet peut aussi être exposé à des problèmes de sécurité liés aux dépendances transitives.
Les développeurs sont notamment confrontés à l’apparition de vulnérabilités ou de ruptures de compatibilité dans ces dépendances transitives. Un paquet largement utilisé peut, par exemple, introduire soudainement une vulnérabilité ou une rupture de compatibilité qui affecte l’ensemble de votre projet.
npm propose une fonctionnalité puissante appelée overrides dans le fichier package.json pour atténuer ces risques. Elle vous permet d’épingler des versions spécifiques de dépendances directes et transitives, afin que votre projet n’utilise que les versions auxquelles vous faites confiance.
Un cas concret où les overrides se sont révélées précieuses remonte à mars 2022 : l’incident de sécurité lié aux protestwares des packages peacenotwar et node-ipc, qui a permis de limiter les perturbations pour les consommateurs de packages.
Comment utiliser la configuration overrides dans package.json
Pour utiliser la fonctionnalité overrides, ajoutez une section overrides à votre fichier package.json. Cette section indique les versions des dépendances à utiliser, indépendamment de celles spécifiées dans les fichiers package.json propres à ces dépendances.
Voici un exemple simple d’utilisation de overrides :
{
"name": "your-project",
"version": "1.0.0",
"dependencies": {
"some-package": "^2.0.0"
},
"overrides": {
"node-ipc@>9.2.1 <10": "9.2.1",
"node-ipc@>10.1.0": "10.1.0"
}
}Dans cet exemple :
Le package
node-ipcest verrouillé à la version 9.2.1 pour les versions supérieures à 9.2.1 et inférieures à 10.Le package
node-ipcest verrouillé à la version 10.1.0 pour les versions supérieures à 10.1.0.
Renforcer la sécurité avec Snyk
Même si le verrouillage des dépendances peut contribuer à atténuer certains risques, il ne constitue pas une solution miracle. Il est essentiel d’analyser régulièrement votre projet à la recherche de vulnérabilités. Un outil de sécurité conçu pour les développeurs comme Snyk détecte aussi rapidement que possible les malwares, les protestwares et les vulnérabilités générales dans vos dépendances, et vous aide à y remédier.
Pour commencer avec Snyk, créez gratuitement un compte ici.
9. Développer des packages localement avec npm install
Lorsque vous développez des packages npm en local, vous devez souvent les tester dans un autre projet. Si vous ne connaissez pas cette fonctionnalité intégrée à npm, vous pourriez être amené à publier le package dans le registre npm, une opération fastidieuse et chronophage, surtout si vous devez apporter fréquemment des modifications.
La commande npm install <path-to-package-in-disk-directory> résout ce problème en vous permettant d’installer et de lier des packages locaux directement depuis votre répertoire de développement. Elle crée un lien symbolique vers le répertoire où vous développez le package, ce qui permet de tester et de récupérer les mises à jour facilement, sans avoir à le republier à chaque fois (et sans même devoir le désinstaller puis le réinstaller localement, grâce au lien symbolique).
Pour utiliser cette commande, accédez au répertoire racine du projet dans lequel vous souhaitez installer le package local. Exécutez ensuite la commande suivante :
npm install /path/to/local/packageRemplacez /path/to/local/package par le chemin réel vers le répertoire de votre package local. Cette commande crée un lien symbolique entre le répertoire node_module's de votre projet et le répertoire du package local.
Les avantages pratiques de l’installation locale de packages avec npm
Mises à jour immédiates : les modifications apportées au package local sont immédiatement répercutées dans le projet, sans qu’il soit nécessaire de le republier.
Débogage simplifié : vous pouvez déboguer et tester votre package en temps réel dans le contexte du projet global.
Flux de travail plus efficace : le processus de développement est simplifié grâce à la réduction des tâches liées à la gestion des versions et à la publication des packages.
10. Sécurité et compatibilité avec une configuration .npmrc
Le fichier .npmrc est un fichier de configuration pour npm qui vous permet de personnaliser le comportement des commandes npm. Il joue un rôle essentiel dans le renforcement de la sécurité et de la compatibilité de vos projets Node.js. En configurant certains paramètres dans le fichier .npmrc, vous pouvez protéger vos projets contre les packages malveillants et vérifier la compatibilité de vos dépendances avec des versions précises de l’environnement d’exécution Node.js.
Désactiver les scripts pour renforcer la sécurité
L’un des moyens les plus efficaces de protéger votre projet contre les packages dangereux et malveillants consiste à désactiver l’exécution des scripts de cycle de vie. Ces scripts peuvent exécuter des commandes arbitraires pendant l’installation, ce qui présente un risque pour la sécurité.
En définissant ignore-scripts=true dans votre fichier .npmrc, vous pouvez empêcher l’exécution de ces scripts :
# .npmrc
ignore-scripts=trueCette configuration garantit que npm n’exécutera aucun script preinstall, postinstall ni autre script de cycle de vie, réduisant ainsi le risque d’exécution de code malveillant.
Compatibilité avec les versions de l’environnement d’exécution Node.js
Pour garantir la sécurité et la stabilité d’un projet, il est également important de vérifier sa compatibilité avec des versions précises de l’environnement d’exécution Node.js. Cette précaution est particulièrement utile si votre projet dépend de versions anciennes ou non prises en charge de Node.js. En définissant node-version dans votre fichier .npmrc, vous pouvez indiquer à npm de ne mettre à jour que les dépendances compatibles avec la version de Node.js spécifiée :
# .npmrc
node-version=14.0.0Cette configuration garantit que npm ne prendra en compte que les dépendances dont la plage de versions Node.js dans le fichier manifeste engines correspond à celle spécifiée.
Pour aller plus loin
Les commandes Power-user npm avancées permettent non seulement de gérer les dépendances, mais aussi de renforcer la sécurité et l’efficacité de votre flux de travail de développement.
Vous pourriez également apprécier ces articles sur Node.js :
Dix bonnes pratiques de sécurité npm pour sécuriser vos projets JavaScript.
Dix fonctionnalités modernes de l’environnement d’exécution Node.js à adopter en 2024
Dix bonnes pratiques pour conteneuriser des applications web Node.js avec Docker
Les bonnes pratiques de Brian Clark pour créer un package npm moderne en tenant compte de la sécurité.
Outil gratuit de vérification du code
Sécurisez votre code avant votre prochain commit.