Un firewall d'artefacts est un proxy qui prend une décision de
politique (autoriser, masquer, refuser) devant chaque npm install ou
pip install, avant que le paquet n'entre dans votre usine logicielle. Un
cache comme Nexus sert tout ce qu'on lui demande ; le firewall décide ce qui a
le droit d'entrer. Cette leçon s'adresse aux équipes sécurité et
plateforme qui gèrent déjà un gestionnaire d'artefacts et veulent passer du
cache au contrôle.
L'exemple est Varnish Artifact Firewall, la brique Premium de Varnish
Orca, devant Nexus. Tout est vérifié le 1er octobre 2026 sur Orca
0.18.1 (firewall 0.6.0) : la configuration de la leçon passe le validateur,
mais l'image publique ne porte aucun addon de licence (addons=[]), si
bien que le firewall n'applique rien sans licence d'essai. La leçon le dit à
chaque endroit où cela change ce que vous pouvez observer.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Distinguer cache, firewall d'artefacts, analyse SCA et contrôle d'admission.
- Rédiger des règles
allow,hideetdeny, et régler la quarantaine des publications récentes. - Monter un lab Orca et Nexus, et savoir ce qu'il montre sans licence.
- Bloquer une version vulnérable et un nom interne usurpé.
- Fermer les contournements, sur les runners CI comme sur les postes.
- Produire la preuve de SOCLE-INT-GEN-3, une consommation OSS via un proxy interne contrôlé, sans tirage direct non filtré.
Pourquoi un cache ne suffit pas
Section intitulée « Pourquoi un cache ne suffit pas »Vos développeurs lancent chaque jour des dizaines de npm install et de
pip install. Chacune télécharge du code tiers, souvent des centaines de
paquets transitifs, et l'exécute sur les postes et les runners CI. En
septembre 2025, le ver Shai-Hulud a compromis plus de 500 paquets npm
selon l'alerte de la CISA du 23 septembre : son script postinstall
collectait les jetons et identifiants présents dans l'environnement, puis se
republiait avec les jetons npm trouvés.
Un gestionnaire d'artefacts comme Nexus ou un cache comme Varnish Orca résout deux problèmes réels : la vitesse et la résilience face à une panne du registre public. Mais il sert tout ce qu'on lui demande. Si un développeur installe une version vulnérable, un paquet au nom usurpé par dependency confusion, ou une version publiée il y a deux heures par un compte compromis, le cache la télécharge, la stocke et la rediffuse à toute l'équipe.
Qu'est-ce qu'un firewall d'artefacts ?
Section intitulée « Qu'est-ce qu'un firewall d'artefacts ? »Un firewall d'artefacts s'intercale entre vos clients (npm, pip, runners CI) et vos dépôts, et évalue chaque résolution contre un jeu de règles. Chez Varnish, une règle aboutit à l'une de trois actions, et une quarantaine globale s'y ajoute, d'après la documentation de configuration du firewall :
| Décision | Effet | Cas d'usage |
|---|---|---|
allow | Sert l'artefact | Exception explicite, paquet de confiance |
hide | Retire la version de la résolution « dernière version » | Évincer une version sans casser un lockfile existant |
deny | Refuse avec une réponse 403 | Paquet interdit, version vulnérable |
quarantaine (default_quarantine_days) | Bloque toute version publiée depuis moins de N jours, quelles que soient les règles | Fenêtre de sécurité sur les publications fraîches |
La quarantaine n'est donc pas une action de règle : c'est un réglage global, qui répond directement à l'exigence de délai avant adoption (cooldown) du référentiel, SOCLE-INT-OSS-1. Une version piégée publiée ce matin, comme celles de Shai-Hulud, est retenue le temps que la communauté la repère.
L'intérêt par rapport à un scanner est le moment de la décision : avant l'ingestion. Une dépendance refusée n'entre jamais dans le cache ni dans le build. Là où un SBOM scanné vous dit après coup « vous avez installé un composant vulnérable », le firewall empêche le composant d'arriver.
Architecture du lab d'étude
Section intitulée « Architecture du lab d'étude »Le lab enchaîne trois composants. Le firewall est transparent : les
clients visent le registre virtuel d'Orca, et enable_firewall: true fait
passer ce registre par le firewall en interne. Le schéma suit une résolution :
Le rôle de Nexus est de centraliser : un dépôt proxy vers le registre public, un dépôt hosted pour vos paquets internes, et un groupe qui expose une URL unique. L'ordre des membres du groupe (hosted avant proxy) constitue déjà une première barrière contre la dependency confusion ; le firewall ajoute la décision par règle au-dessus.
Devant Nexus, mais aussi devant Pulp
Section intitulée « Devant Nexus, mais aussi devant Pulp »Le firewall n'est pas lié à Nexus. La documentation Varnish décrit Orca comme
un gestionnaire de registres virtuels agnostique : chaque registre virtuel
a un backend remotes.url, et Orca transmet le chemin client tel quel vers
ce backend. Rien n'empêche donc de pointer ce backend vers un autre
gestionnaire, comme Pulp, le
gestionnaire d'artefacts open source.
Ce montage avec Pulp a été vérifié dans un lab antérieur à cette leçon : le registre virtuel se charge, l'index PyPI et le téléchargement des artefacts passent à travers Orca. Deux points de vigilance en sont ressortis :
- Le montage le plus direct vise le registre de conteneurs : Pulp expose
son API OCI sur
/v2/à la racine, comme le registre public qu'Orca sait déjà mettre en cache. - Pour PyPI, Pulp émet des liens de téléchargement absolus via son
paramètre
CONTENT_ORIGIN; Orca les ré-enveloppe dans son endpoint/redirectz, et il faut alignerCONTENT_ORIGINsur l'URL exposée par Orca.
Placer Orca devant Pulp est intéressant parce que Pulp n'a pas de quarantaine native : le firewall apporte la couche de décision qui manque, sur un stockage entièrement open source.
Monter le lab
Section intitulée « Monter le lab »Le lab tient dans un docker-compose.yml (Nexus et Orca) et quelques
fichiers de configuration. Les images sont figées par digest ; les
versions sont celles du 1er octobre 2026.
-
Déclarer Nexus et Orca
docker-compose.yml services:nexus:image: sonatype/nexus3:3.96.4@sha256:5f48f9085096e96f4111ec07d79d57ca5a4a1da5a2003a3028a0b60c62bea7d1ports: ["8081:8081"]volumes: ["nexus-data:/nexus-data"]orca:image: varnish/orca:0.18.1@sha256:44df08bdb5843ef1173bda327adb487c2bd101681b24559482c10bf6d8f1429dplatform: linux/amd64 # Orca est distribué pour linux/amd64depends_on: [nexus]ports:- "8080:80" # registres virtuels (endpoint client)- "9090:9090" # métriques du firewall (Premium)volumes:- ./orca/orca.yaml:/etc/varnish-supervisor/default.yaml:ro- ./orca/rulesets:/etc/orca/rulesets:rovolumes:nexus-data: -
Créer les dépôts Nexus (proxy, hosted, groupe) pour npm et PyPI via l'API REST. Le groupe
npm-allagrègenpm-private-hostedpuisnpm-public-proxy, et c'est lui que verra le firewall.Nexus Community Edition ne sert aucun artefact tant que son EULA n'est pas acceptée. Mesuré sur 3.96.4 : un téléchargement répond
403 You must accept the End User License Agreement (EULA), puis200après acceptation par l'API, qui attend le corps renvoyé parGET, avec"accepted": true.Fenêtre de terminal curl -s -u "admin:$NEXUS_PASSWORD" http://localhost:8081/service/rest/v1/system/eula \| jq '.accepted = true' \| curl -s -u "admin:$NEXUS_PASSWORD" -H 'Content-Type: application/json' \-X POST http://localhost:8081/service/rest/v1/system/eula -d @-# réponse 204, sans corps -
Configurer le firewall Orca
orca/orca.yaml virtual_registry:registries:- name: npm-nexusdefault: trueenable_firewall: trueremotes:- url: http://nexus:8081/repository/npm-all/- name: pypi-nexusenable_firewall: trueremotes:- url: http://nexus:8081/repository/pypi-all/firewall:default_action: allow # observe en POC ; deny en productiondefault_quarantine_days: 2severity_deny_threshold: 9severity_allow_threshold: 4audit_log_output: stdoutmetrics_address: ":9090"rulesets:- path: /etc/orca/rulesets/npm-rules.yaml- path: /etc/orca/rulesets/pypi-rules.yamlLe binaire embarque un validateur. Mesuré sur Orca 0.18.1, il répond
configuration is validpour ce fichier, et refuse une clé inconnue (field champ_inconnu not found in type firewall.FirewallConfig) ou une entrée derulesetsécrite en simple chaîne au lieu d'un objetpath:.Fenêtre de terminal docker run --rm --platform linux/amd64 \-v "$PWD/orca/orca.yaml":/c.yaml:ro -v "$PWD/orca/rulesets":/etc/orca/rulesets:ro \varnish/orca:0.18.1@sha256:44df08bdb5843ef1173bda327adb487c2bd101681b24559482c10bf6d8f1429d \varnish-supervisor -validate -config /c.yaml# configuration is valid -
Pointer les clients sur le firewall
Orca transmet le chemin client tel quel : incluez le chemin du groupe Nexus.
.npmrc registry=http://npm-nexus.localhost:8080/repository/npm-all/pip.conf [global]index-url = http://pypi-nexus.localhost:8080/repository/pypi-all/simpletrusted-host = pypi-nexus.localhost
Écrire des règles
Section intitulée « Écrire des règles »Une règle décrit quoi reconnaître (match) et quoi décider
(action). Les règles sont regroupées dans un fichier identifié par un id,
et triées par priority. Ce jeu de règles npm de démonstration couvre les
trois actions.
id: npm-demo-rulesrules: # Blocage dur d'un paquet précis. - id: block-left-pad priority: 100 action: deny severity: 9.5 reason: "Package bloqué pour la démonstration." match: - type: npm name: left-pad
# Anti dependency confusion : un scope interne ne vient jamais du public. - id: block-internal-scope priority: 90 action: deny reason: "Le scope @company ne doit pas être résolu depuis le registre public." match: - type: npm name: "@company/*"
# Masquer les vieilles versions sans casser un lockfile existant. - id: hide-lodash-old priority: 50 action: hide reason: "Les versions de lodash < 4.17.21 ne sont pas proposées." match: - type: npm name: lodash version: "vers:npm/<4.17.21"Côté Python, la même grammaire bloque une version vulnérable. La plage
de versions utilise la notation VERS (vers:pypi/<2.32.0), un format
normalisé de plages de versions par écosystème.
id: pypi-demo-rulesrules: - id: block-old-requests priority: 100 action: deny severity: 9.0 reason: "Les versions de requests < 2.32.0 sont interdites." match: - type: pypi name: requests version: "vers:pypi/<2.32.0"Comment la sévérité interagit avec les seuils
Section intitulée « Comment la sévérité interagit avec les seuils »Une règle peut porter un score severity, qui prend le pas sur son
action. D'après la documentation de Varnish, une règle dont la sévérité est
supérieure ou égale à severity_deny_threshold (9 par défaut) aboutit à
deny, une règle inférieure ou égale à severity_allow_threshold (4 par
défaut) aboutit à allow, et entre les deux, c'est l'action de la règle
qui s'applique. Dans l'exemple npm, block-left-pad (9.5) serait refusé même
si son action valait hide.
Ce mécanisme permet de brancher des règles communautaires, par exemple les
jeux de règles dérivés des données OSV, et de piloter leur effet par deux
seuils, sans réécrire chaque règle. Il porte aussi un piège : une règle deny
de sévérité 3 est autorisée.
Des règles dynamiques avec un dépôt git
Section intitulée « Des règles dynamiques avec un dépôt git »Charger les règles depuis des fichiers locaux (path:) impose de
redémarrer Orca pour les prendre en compte. Le mode dynamique passe par
une source git, que le firewall rafraîchit à intervalle régulier, sans
redémarrage. L'extrait suivant passe le validateur de la 0.18.1.
firewall: mode: report # décisions journalisées, rien n'est bloqué rulesets: - git: name: npm-osv-rules url: https://github.com/varnish/osv-rules.git sub_path: rulesets/npm/all.yaml ref: main # branche suivie : les règles changent sans revue locale interval: 30m # fréquence de rafraîchissement webhook: url: http://collector.interne/reloaded # notifié après chaque rechargementLe dépôt varnish/osv-rules existe et publie rulesets/npm/all.yaml. Suivre
sa branche main est un choix assumé : les règles se mettent à jour seules,
au prix d'une confiance dans l'éditeur. Pour vos propres règles, un dépôt
interne versionné et relu par revue de code donne une vraie démarche
GitOps. Le mode report est le bon point de départ : toutes les
décisions sont ramenées à allow, mais restent écrites dans le journal
d'audit, ce qui permet de mesurer l'effet d'une politique avant de l'activer.
Étudier le firewall en pratique
Section intitulée « Étudier le firewall en pratique »Avec une licence d'essai montée, le firewall applique les décisions. Le scénario d'étude le plus parlant compare deux installations. Les étapes suivantes n'ont pas été rejouées pour cette leçon, faute de licence : elles décrivent le comportement documenté.
-
Installer une dépendance autorisée
Fenêtre de terminal npm install is-number # aucune règle ne correspond : allow -
Tenter une dépendance bloquée
Fenêtre de terminal npm install left-pad # règle block-left-pad : deny, réponse 403 -
Lire le journal d'audit
Fenêtre de terminal docker compose logs orca | grep -i denyLe journal porte la décision, le paquet et la raison (
reason) de la règle. C'est lui que vous routerez vers un SIEM en production. -
Modifier une règle et rejouer
Retirez
block-left-pad, redémarrez Orca, relancez l'installation : elle passe. La politique pilote la décision.
Ce que le firewall ne protège pas
Section intitulée « Ce que le firewall ne protège pas »Un firewall d'artefacts ferme une porte : l'entrée non gouvernée des dépendances. Le présenter comme une protection globale serait une erreur, et trois limites le montrent.
- Il ne lit pas le code d'un paquet autorisé : une dépendance saine aujourd'hui peut être compromise par une mise à jour, d'où la quarantaine.
- Il ne protège ni le runner CI compromis, ni l'exfiltration de secrets, ni l'image déjà construite et non signée.
- Il ne produit ni SBOM ni provenance : ce sont d'autres briques de ce module.
Surtout, la configuration du registre incite à passer par le firewall mais
ne l'impose pas : un développeur ou un job peut toujours écrire
npm config set registry https://registry.npmjs.org. Refermer ce
contournement est un sujet à part entière.
Empêcher le contournement (CI et postes de dev)
Section intitulée « Empêcher le contournement (CI et postes de dev) »Un firewall ne protège que ce qui passe par lui. Tant que les clients
peuvent joindre registry.npmjs.org ou pypi.org en direct, n'importe qui
peut le court-circuiter d'une seule commande. La règle tient en une phrase :
la configuration incite, le réseau impose.
Sur les runners CI : verrouiller l'egress
Section intitulée « Sur les runners CI : verrouiller l'egress »Côté CI, le contournement se ferme proprement parce que vous maîtrisez
l'environnement. Placez les runners dans un réseau sans route sortante
vers Internet : seul le firewall d'artefacts est joignable. Une tentative
npm config set registry https://registry.npmjs.org échoue alors faute de
route. Sous Kubernetes, une NetworkPolicy egress qui n'autorise que le
service du firewall produit le même effet, et des runners éphémères
empêchent toute configuration locale persistante.
Sur les postes de dev : le cas difficile
Section intitulée « Sur les postes de dev : le cas difficile »Le poste du développeur est plus dur à contraindre : le développeur y a
souvent les droits administrateur, donc aucune configuration
applicative n'est infalsifiable. Pousser un .npmrc, un pip.conf ou un
GOPROXY par MDM ou gestion de configuration réduit la friction, mais
reste contournable d'un --registry. Le contrôle robuste est, là encore,
réseau :
| Solution | Effet | Robustesse |
|---|---|---|
| Couper l'egress direct vers npmjs, pypi, Docker Hub | Le registre public n'a plus de route | Élevée |
DNS interne : registry.npmjs.org résolu vers le firewall | Même une URL publique en dur atterrit sur le firewall | Élevée, avec l'egress fermé |
| Poste sans route Internet directe | Tout transite par le proxy interne | Maximale |
| Environnement de dev distant (dev container, VDI) | On contrôle le réseau de l'environnement | Élevée |
Configuration gérée (.npmrc, pip.conf, GOPROXY) | Oriente le défaut | Faible seule |
Aucune ligne ne suffit isolément sur une machine où le développeur est administrateur. La combinaison qui tient : pas de route directe vers les registres publics, plus un DNS qui ramène les noms publics sur le firewall. La configuration gérée s'ajoute pour le confort, pas pour la sécurité.
Rattraper et détecter
Section intitulée « Rattraper et détecter »Le réseau ferme la porte ; la détection vérifie qu'elle reste fermée.
Ajoutez en CI un contrôle des lockfiles : une entrée resolved (npm) ou
une URL d'index qui pointe ailleurs que vers le firewall fait échouer le build.
OSV-Scanner repère de son côté
les dépendances vérolées qui auraient contourné le firewall, et les
journaux du proxy réseau signalent toute tentative d'accès direct aux
registres publics. Ces contournements prolongent les techniques décrites dans
Attaques via les gestionnaires de paquets.
Où le placer dans votre chaîne ?
Section intitulée « Où le placer dans votre chaîne ? »Le firewall n'est pas un substitut aux autres contrôles du module : il occupe la position la plus en amont. Une chaîne mûre les combine, chacune répondant à une question différente.
| Étape | Brique | Rôle |
|---|---|---|
| Entrée des dépendances | Varnish Artifact Firewall | Décide avant ingestion |
| Centralisation | Nexus | Cache et expose les artefacts |
| Inventaire | SBOM | Liste les composants livrés |
| Exploitabilité | VEX | Documente ce qui est réellement exploitable |
| Signature | Cosign | Signe et vérifie l'image |
| Provenance | SLSA | Atteste l'origine du build |
Le firewall réduit le bruit en aval : moins de composants douteux entrent, moins de vulnérabilités à trier ensuite. Il ne remplace pas la défense en profondeur, il la commence.
À retenir
Section intitulée « À retenir »- Un cache accélère et résiste aux pannes ; un firewall d'artefacts décide ce qui a le droit d'entrer.
- Trois actions de règle,
allow,hideetdeny, plus une quarantaine globale (default_quarantine_days) sur les publications récentes. - La sévérité prend le pas sur l'action : au-dessus du seuil de refus,
deny; sous le seuil d'autorisation,allow. - Le mode
reportjournalise les décisions sans rien bloquer : le bon départ pour mesurer une politique. -validatecontrôle la structure de la configuration, pas le contenu des règles.- Sans règle d'egress réseau, la configuration du registre se contourne.
- Chez Varnish, le firewall est Premium : l'image publique 0.18.1 démarre
avec
addons=[]et ne filtre rien. - La preuve attendue par SOCLE-INT-GEN-3 est la configuration du proxy interne et la preuve d'absence de tirage direct non filtré.
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de cette leçon est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Score par domaine
Un domaine regroupe plusieurs guides et reçoit plusieurs questions : son score est plus fiable qu'un score par thème, qui porte souvent sur une seule question.
Bilan
Points forts
Aucun sujet réussi à 80 % sur au moins deux questions pour l’instant.
Points faibles
Aucun sujet sous le seuil de réussite.
À faire ensuite
Des indices pour retenter votre chance ?
Continuer le cours : TPRM pour équipes techniques : évaluer la sécurité de vos fournisseurs
Continuer le cours : Registries GitLab : construire et publier images et packages
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications