DevShield est un garde-fou local pour les
installations de dépendances. Vous enveloppez la commande d'installation ; il coupe les scripts
hostiles, exige un lockfile pinné, repère les secrets exposés et bloque les connexions réseau
hors liste — le tout sur votre machine, zéro dépendance externe.
i
DevShield est un modèle checkpoint : il ne protège que les installations que vous
routez à travers lui. Un npm ci brut lancé à côté lui est invisible.
On durcit sa CI et son chemin d'installation béni — pas « installez ceci et vous êtes protégé partout ».
Installation
Compiler et poser sur le PATH.
Aucune dépendance externe : une chaîne Rust stable suffit.
# depuis le dépôt Proxia
cd devshield
cargo build --release # binaire → target/release/devshield
cp target/release/devshield /usr/local/bin/ # optionnel : sur le PATH
La commande centrale
devshield run — envelopper une installation.
DevShield exécute votre commande, applique les garde-fous que vous activez, et (avec
--audit-log) écrit une trace JSONL locale. Chaque garde-fou est en mode
warn par défaut (non destructif) ; vous montez en block
ou fail quand vous voulez durcir.
Chacune est indépendante et non destructive par défaut. Empilées, elles couvrent les vecteurs
d'installation les plus courants.
// 1 · exécution
Scripts de cycle de vie
--scripts-mode warn|block|fail
block désactive les scripts d'installation npm (injecte
--ignore-scripts) ; fail refuse (code 21)
avant même de lancer. Couvre aussi npx / npm exec /
pnpm dlx comme exécution de code arbitraire. pip : avertissement seul.
La couche qui stoppe les charges type Shai-Hulud / Axios.
// 2 · intégrité
Posture du lockfile
--preflight-lockfile [--lockfile-mode warn|fail]
Signale (ou refuse, code 22) un lockfile npm absent ou sans empreintes d'intégrité, ou une
commande qui mute le lockfile (npm install) au lieu de le
respecter (npm ci). Posture, pas détection d'altération — npm vérifie
déjà les empreintes. pip : meilleur effort, avertissement seul.
// 3 · secrets
Préflight secrets
--preflight-secrets [--preflight-mode warn|fail]
Repère les variables d'environnement et fichiers porteurs de secrets
(.env, .npmrc, .pypirc…)
avant de lancer l'installation — sans jamais afficher les valeurs.
fail → code 20.
// 4 · réseau
Proxy d'egress
--egress-proxy [--egress-mode warn|enforce]
Un proxy local (127.0.0.1) à travers lequel l'installation est routée. enforce
bloque (403) toute connexion vers un hôte hors liste d'autorisation. Sans MITM : bloque par
hôte, jamais par contenu. warn journalise tout ; l'échec de liaison en
enforce → code 23 (fail-closed).
Modes · scripts-mode
Mode
Effet
DEVSHIELD_MODE
warndéfaut
Lance sans changement ; journalise un événement lifecycle_scripts.
audit-only
block
Désactive les scripts pour npm (injecte --ignore-scripts + npm_config_ignore_scripts). pip / npx : avertissement seul.
enforce
fail
Sort en 21 avant de lancer si des scripts s'exécuteraient. Commande inconnue → refus (fail-closed).
enforce
!
Nuance couverture : la désactivation des scripts en block est vérifiée pour npm. yarn Berry (v2+) ignore npm_config_* et n'honore pas --ignore-scripts ; vérifiez avant de vous y fier pour pnpm/yarn.
Codes de sortie
Un code par refus — scriptable en CI.
Code
Signification
0
Enfant exécuté ; aucun garde-fou n'a refusé.
code enfant
Propagé depuis la commande enveloppée.
20
--preflight-mode fail : risque de secret détecté.
21
--scripts-mode fail : des scripts s'exécuteraient.
22
--lockfile-mode fail : risque de posture lockfile.
23
--egress-mode enforce : le proxy n'a pas pu démarrer (fail-closed).
10
check / observe egress : destination bloquée par la politique.
2
Erreur d'usage / d'argument.
125 · 127
Échec d'écriture du journal (125) · échec d'exécution de la commande (127).
Adoption · la CI d'abord
Le meilleur point d'ancrage.
C'est là que les attaques de chaîne d'approvisionnement frappent réellement, c'est central, et
impossible à oublier. Remplacez une ligne et faites échouer le build en cas de risque :
# .github/workflows/ci.yml — build durci
- run: |
devshield run --profile npm \
--scripts-mode fail \
--preflight-lockfile --lockfile-mode fail \
--preflight-secrets --preflight-mode fail \
--egress-proxy --egress-mode enforce \
--audit-log devshield-audit.jsonl \
-- npm ci
- run: devshield audit read --audit-log devshield-audit.jsonl # trace dans le log de build
Autres points d'ancrage : un alias shell
(alias npm='devshield run … -- npm') pour un dev transparent ;
une cible Makefile / just partagée par l'équipe ; le postCreateCommand
d'un dev container.
Journal d'audit
Une trace JSONL locale, lisible.
devshield audit read --audit-log <fichier> # résumé de chaque événementdevshield audit trace --audit-log <fichier> --context-id <id> # une commande + ses egress
Événements : command_run, lifecycle_scripts,
secret_preflight, lockfile_preflight,
egress_observation. Tout est local ; rien n'est transmis.
Honnêteté · ce que DevShield n'est pas
Un contenant, pas une baguette magique.
// portée
Uniquement les installations routées
Pas d'interception à l'échelle du système. Un npm ci brut est invisible. L'alias shell s'en rapproche, mais reste opt-in et contournable.
// nature
Contenance, pas intégrité
--scripts-mode empêche l'exécution/exfiltration ; il ne vous dira pas qu'un paquet a été échangé. npm vérifie déjà l'intégrité à l'installation.
// réseau
Hôte, pas contenu
Le proxy bloque par hôte:port, sans MITM. Il ne distingue pas un téléchargement d'un publish sur un hôte autorisé. github.com reste autorisé par défaut.
// destruction
Pas de défense fichier
Un postinstall qui efface des fichiers n'est stoppé que si les scripts sont désactivés (block/fail). Aucun contrôle réseau n'aide ici.
Utilisez DevShield pour durcir votre CI et votre chemin
d'installation béni, en couche avec le pinning de lockfile et la provenance des paquets — pas comme
« installez ceci et vous êtes protégé partout ».