
enject : Cachez les secrets .env des regards indiscrets : les secrets vivent dans des stockages locaux cryptés (par projet) et sont injectés directement dans les applications au moment de l'exécution, sans jamais toucher le disque en texte clair.
Cachez les secrets .env des regards indiscrets de l'IA.
(Remarque : ce projet s'appelait auparavant enveil et a été renommé en enject)
Les outils de codage IA comme Claude Code, Copilot, Cursor et autres peuvent lire les fichiers de votre répertoire projet, ce qui signifie qu'un fichier .env en clair est un dépotoir accidentel de secrets prêt à se produire. Ce n’est pas théorique. C’est un problème connu qui m’est arrivé plusieurs fois (même après avoir explicitement dit à Claude de ne pas regarder dans le fichier settings.json de Claude Code). enject résout ce problème en garantissant que les secrets en clair n’existent jamais sur le disque du tout. Votre fichier .env ne contient que des références symboliques ; les vraies valeurs résident dans un stockage local crypté et sont injectées directement dans votre sous-processus au lancement.
Ce projet s’inspire de la solution/article de blog de Filip Hric, qui utilise un concept similaire en s’appuyant sur 1Password. Je voulais une solution autonome qui ne dépende pas de services tiers, ce qui a donné naissance à cette solution. Et oui, ce projet a été construit presque entièrement avec Claude Code, avec beaucoup de vérification et de tests manuels.
Ce projet est principalement conçu pour atténuer le problème connu des outils IA/LLM lisant accidentellement les secrets .env dans votre projet. Les avantages supplémentaires incluent la prévention des fuites de secrets si un .env est accidentellement commité dans un dépôt, la possibilité de partager des fichiers .env contenant des références au lieu de secrets en clair, et la possibilité de partager le stockage crypté lui-même.
Ce projet n’est pas une solution miracle pour empêcher un agent IA d’obtenir vos secrets. Par exemple, un agent peut toujours écrire du code (par accident ou via une injection de prompt) qui exfiltre les secrets vers la sortie terminal ou un fichier au moment de l’exécution. Nous vous déconseillons vivement de vous fier à cet outil, ou aux fichiers .env en général, pour stocker des secrets de production.
Votre fichier .env ressemble à ceci :
DATABASE_URL=en://database_url
STRIPE_KEY=en://stripe_key
PORT=3000
Techniquement, il est sûr de le commiter (mais ne le faites pas, quand même), et plus important encore : sûr pour tout outil IA qui fouinerait accidentellement (ou peut-être pas si accidentellement).
Lorsque vous exécutez enject run -- npm start, il :
en:// à partir de la carte déchiffréeLe fichier de stockage est un blob binaire. Sans le mot de passe maître, il est indistinguable d’un bruit aléatoire. Le nonce est fraîchement généré à chaque écriture, donc la réutilisation du nonce AES-GCM est impossible. Toute modification du texte chiffré — même un seul bit inversé — entraîne un échec d’authentification et le déchiffrement est refusé.
Cette version est encore en alpha, donc nécessite d’ajouter la dernière version lors de l’appel à cargo install
cargo install enject --version 0.2.0-alpha
Nécessite Rust 1.70+.
git clone https://github.com/greatscott/enject
cd enject
cargo build --release
Le binaire compilé se trouve dans target/release/enject. Installez-le une fois dans un emplacement de votre PATH afin de pouvoir l’exécuter depuis n’importe quel projet :
macOS / Linux (bash ou zsh)
# Option A : ~/.local/bin (aucun sudo requis, courant sous Linux)
mkdir -p ~/.local/bin
cp target/release/enject ~/.local/bin/
# Option B : /usr/local/bin (nécessite sudo, disponible à l’échelle du système)
sudo cp target/release/enject /usr/local/bin/
# Option C : ~/.cargo/bin (déjà dans PATH si vous avez utilisé rustup)
cp target/release/enject ~/.cargo/bin/
Si vous avez utilisé l’option A et que ~/.local/bin n’est pas déjà dans votre PATH, ajoutez ceci à votre configuration shell (~/.zshrc, ~/.bashrc ou ~/.bash_profile) :
export PATH="$HOME/.local/bin:$PATH"
Puis rechargez-la :
source ~/.zshrc # ou ~/.bashrc
Vérifiez que cela a fonctionné :
enject --version
Le binaire est installé globalement — vous ne le réinstallez jamais. Mais chaque projet obtient son propre stockage crypté :
cd your-project
enject init
Ceci crée .enject/ dans le répertoire courant avec la configuration du projet et le stockage crypté. Ajoutez-le à .gitignore — il ne doit jamais être commité.
Exécutez ceci une fois par projet, à la racine du projet :
enject init
Ceci génère un sel aléatoire de 32 octets, écrit .enject/config.toml, crée un stockage crypté vide dans .enject/store, et vous invite à définir un mot de passe maître. Ajoutez .enject/ à votre .gitignore — le stockage ne doit jamais être commité.
enject set some_database_url
# prompts: Value for 'database_url': (hidden)
enject set some_api_key
Les valeurs sont toujours saisies de manière interactive. Il n’y a aucun moyen de passer une valeur comme argument en ligne de commande — cela empêche les secrets d’apparaître dans l’historique du shell ou dans la sortie de ps.
.envDATABASE_URL=en://some_database_url
MY_API_KEY=en://stripe_key
PORT=3000
Les lignes simples KEY=VALUE sont transmises sans modification. Seules les références en:// sont résolues.
enject run -- npm start
enject run -- python manage.py runserver
enject run -- cargo run
Tout ce qui suit -- est passé textuellement au système d’exploitation. Le sous-processus hérite de votre environnement shell complet (donc PATH, HOME, etc. sont présents) avec les valeurs de .env superposées par-dessus.
enject list # affiche les noms des clés stockées (jamais les valeurs)
enject delete <key> # supprime un secret
enject import <file> # crypte toutes les valeurs d’un .env en clair, le réécrit comme template en://
enject rotate # récrypte le stockage avec un nouveau mot de passe maître
Il n’y a pas de get ni de export. Imprimer une valeur secrète sur stdout crée un vecteur de fuite lisible par l’IA — l’intérêt même d’enject est de garder les valeurs hors du disque et de tout flux de sortie lisible.
Chaque invariant de sécurité a un test automatisé correspondant et un chemin d’inspection manuelle.
cargo test
31 tests, couvrant toutes les affirmations ci-dessous.
Automatisé : store::password::tests::test_encrypt_decrypt_roundtrip
Sauvegarde un secret, persiste le stockage, le recharge depuis le disque, le décrypte et vérifie que la valeur fait un aller-retour correct. Ne réussit que si les octets sur le disque sont un texte chiffré valide — le texte en clair échouerait au déchiffrement.
cargo test store::password::tests::test_encrypt_decrypt_roundtrip
Inspection manuelle :