
Détecte et corrige automatiquement les secrets codés en dur dans les dépôts Python — refuse lorsque la correction pourrait casser votre code
Autonoma détecte les secrets codés en dur et les remplace par des références os.environ[...] en utilisant des réécritures AST. Les modifications ne sont appliquées que lorsque la réécriture est déterministe et préserve la sémantique.
Les réécritures utilisent l'arbre syntaxique analysé — pas des regex sur le texte brut. S'exécute localement sans appels réseau. Fonctionne en CI avec des diffs idempotents et minimaux.

Secrets codés en dur dans les codebases :
La plupart des outils les détectent.
Autonoma ne touche que ce dont il peut prouver qu'il est sûr de modifier.
autonoma scan .
autonoma fix .
git diff
pip install autonoma-cli
Ajoutez ceci à votre .pre-commit-config.yaml pour empêcher les secrets d'entrer dans votre historique :
- repo: local
hooks:
- id: autonoma
name: Autonoma Scan
entry: autonoma scan
language: system
types: [python]
# 1. Create a test file with hardcoded secrets
cat > test_secrets.py << 'EOF'
SENDGRID_API_KEY = "sg-live-abc123xyz789"
DB_PASSWORD = "Pr0dAccess2024!"
EOF
# Also create the env contract file (required for safe remediation)
printf 'SENDGRID_API_KEY=\nDB_PASSWORD=\n' > .env.example
# 2. Scan — emits JSON findings to stdout
autonoma scan test_secrets.py
# 3. Fix — rewrites the file in place
autonoma fix test_secrets.py
# 4. Scan again — should now be clean (exit 0)
autonoma scan test_secrets.py
# 5. Inspect the result
cat test_secrets.py
Résultat attendu après correction :
import os
SENDGRID_API_KEY = os.environ["SENDGRID_API_KEY"]
DB_PASSWORD = os.environ["DB_PASSWORD"]
Mode de détection. Envoie du JSON vers stdout et un résumé lisible vers stderr. Non-mutant — ne modifie jamais les fichiers.
# Scan a directory (JSON findings to stdout)
autonoma scan src/
# Save JSON results to a file
autonoma scan src/ > findings.json
Codes de sortie pour scan :
| Code | Signification |
|---|---|
0 | Aucun résultat |
1 | Résultats détectés |
3 | Erreur de l'outil |
Corrige les secrets codés en dur en utilisant des réécritures AST. Modifie les fichiers sur place.
# Apply fixes
autonoma fix src/
# Preview patches before writing
autonoma fix src/ --diff
# Write remediation audit log
autonoma fix src/ --report-out audit.json
Codes de sortie pour fix :
| Code | Signification |
|---|---|
0 | Aucun résultat — le dépôt était déjà propre |
1 | Résultats existants avant correction (la correction peut avoir réussi — vérifiez le comptage FIXED/REFUSED dans la sortie) |
3 | Erreur de l'outil |
La commande
fixretourne1chaque fois qu'elle a trouvé des secrets avant de tenter une correction, que la réécriture ait réussi ou non. C'est intentionnel : les pipelines CI doivent signaler le commit où les secrets ont été introduits, même après correction automatique. Exécutezautonoma scanensuite pour confirmer que le dépôt est propre.
Analyse l'historique git pour les secrets qui ont été commités puis supprimés ou modifiés.
[!NOTE] Détection uniquement. Cette commande ne réécrit pas l'historique git ni ne modifie les commits.
autonoma history-scan .
Voici les modèles qu'Autonoma corrige actuellement.
# settings.py
SENDGRID_API_KEY = "sg-live-abc123xyz789"
DB_PASSWORD = "Pr0dAccess2024!"
autonoma fix .)# settings.py
import os
SENDGRID_API_KEY = os.environ["SENDGRID_API_KEY"]
DB_PASSWORD = os.environ["DB_PASSWORD"]
# f-string — refused because the rewrite would change semantics
api_key = f"prefix_{BASE_KEY}"
# → REFUSED: refuse_fstring_mixed_expression
# Dict/nested value — refused because the target is not a simple assignment
DATABASES = {
"default": {"PASSWORD": "Pr0d@ccess2024!"}
}
# → REFUSED: unsupported assignment target type
Les résultats refusés sont signalés dans la sortie JSON et provoquent une sortie non nulle en CI. Les fichiers avec des résultats refusés ne sont jamais modifiés.
| Modèle | Exemple | Comportement | Raison |
|---|---|---|---|
| Assignation simple | api_key = "sk-abc123" | Corrigé | Réécriture AST déterministe |
| Attribut de classe | class C: SECRET = "abc" | Corrigé | Réécriture AST déterministe |
| Argument nommé | connect(password="abc") | Corrigé | Réécriture AST déterministe |
| f-string | key = f"prefix_{v}" | Refusé | La réécriture modifierait le comportement à l'exécution |
| Concaténation | key = "sk-" + suffix | Refusé | La réécriture modifierait le comportement à l'exécution |
| Valeur dictionnaire/imbriquée | cfg = {"pass": "abc"} | Refusé | Pas une cible d'assignation simple |
| Assignation multiple | A = B = "secret" | Refusé | Cible ambiguë |
| Déjà sûr | key = os.getenv("KEY") | Ignoré | Aucun changement nécessaire |
.env.example manquant | tout modèle | Refusé | Pas de contrat d'environnement pour dériver le nom de variable |
Relancer sur un fichier propre ne fait aucune modification. Les réécritures conservent l'indentation et les commentaires d'origine. import os n'est ajouté que s'il manque.
Pour faire échouer votre build si des secrets sont détectés :
- name: Scan for secrets
run: autonoma scan .
analyze est conservé pour la compatibilité ascendante. Migrez vers scan ou fix.
# Equivalent to 'autonoma scan'
autonoma analyze src/ --detect-only
# Equivalent to 'autonoma fix'
autonoma analyze src/ --auto-fix
API_KEY = "secret"class Config: PASS = "secret"connect(password="secret")A = B = "secret") ou déballage de tuple..env.example ou contrat d'environnement n'est trouvé dans le dépôt.Les cas refusés sont signalés dans la sortie JSON et provoqueront des codes de sortie non nuls en CI. Le fichier n'est jamais modifié si un problème qu'il contient est refusé.
<file>.bak avant modification.SEC002 combine actuellement des modèles de valeurs de credentials avec une logique de routage conditionnée par mots-clés. Les credentials assignés à des noms de variables très atypiques peuvent ne pas être détectés actuellement.
Autonoma évite intentionnellement une détection large basée uniquement sur l'entropie, à moins que l'impact sur la précision puisse être mesuré par rapport à un corpus étiqueté de faux positifs.
autonoma scan produit un rapport detect-only sur stdout :
{
"schema_version": "1.0",
"tool_name": "autonoma",
"tool_version": "0.1.5",
"generated_at": "2026-03-24T12:00:00Z",
"mode": "detect-only",
"summary": {
"files_processed": 3,
"total_findings": 2,
"safe_to_fix": 1,
"refused": 1
},
"findings": [
{
"file": "settings.py",
"line": 4,
"pattern_type": "api_key",
"severity": "high",
"rule_id": "SEC002",
"safe_to_fix": true,
"suggested_env_var": "SENDGRID_API_KEY",
"refusal_reason": null,
"fingerprint": "sha256:abc123..."
}
]
}
Licence MIT