
Detecta y corrige automáticamente secretos codificados en repositorios de Python — se niega cuando la corrección podría romper tu código.
Autonoma detecta secretos hardcodeados y los reemplaza con referencias a os.environ[...] usando reescrituras del AST. Los cambios se aplican solo cuando la reescritura es determinista y preserva la semántica.
Las reescrituras usan el árbol sintáctico analizado — no regex sobre texto crudo. Funciona localmente sin llamadas de red. Funciona en CI con diffs idempotentes y mínimos.

Secretos hardcodeados en bases de código:
La mayoría de las herramientas los detectan.
Autonoma solo toca lo que puede demostrar que es seguro cambiar.
autonoma scan .
autonoma fix .
git diff
pip install autonoma-cli
Agrega esto a tu .pre-commit-config.yaml para evitar que los secretos entren en tu historial:
- 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
Salida esperada después del fix:
import os
SENDGRID_API_KEY = os.environ["SENDGRID_API_KEY"]
DB_PASSWORD = os.environ["DB_PASSWORD"]
Modo de detección. Emite JSON a stdout y un resumen legible a stderr. No mutante — nunca modifica archivos.
# Scan a directory (JSON findings to stdout)
autonoma scan src/
# Save JSON results to a file
autonoma scan src/ > findings.json
Códigos de salida para scan:
| Código | Significado |
|---|---|
0 | Sin hallazgos |
1 | Hallazgos detectados |
3 | Error de herramienta |
Remedia secretos hardcodeados usando reescrituras del AST. Modifica archivos en el lugar.
# Apply fixes
autonoma fix src/
# Preview patches before writing
autonoma fix src/ --diff
# Write remediation audit log
autonoma fix src/ --report-out audit.json
Códigos de salida para fix:
| Código | Significado |
|---|---|
0 | Sin hallazgos — el repo ya estaba limpio |
1 | Hallazgos existían antes de la remediación (la remediación puede haber tenido éxito — revisa la salida para conteos de FIXED/REFUSED) |
3 | Error de herramienta |
El comando
fixsale con1cada vez que encontró secretos antes de intentar la remediación, independientemente de si la reescritura tuvo éxito. Esto es intencional: los pipelines de CI deben marcar el commit donde se introdujeron los secretos, incluso después del auto-fix. Ejecutaautonoma scandespués para confirmar que el repositorio está limpio.
Escanea el historial de git en busca de secretos que fueron comiteados y luego eliminados o cambiados.
[!NOTE] Solo detección. Este comando no reescribe el historial de git ni modifica commits.
autonoma history-scan .
Estos son los patrones que Autonoma realmente arregla hoy.
# 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
Los hallazgos rechazados se reportan en la salida JSON y causan una salida distinta de cero en CI. Los archivos con hallazgos rechazados nunca se modifican.
| Patrón | Ejemplo | Comportamiento | Por qué |
|---|---|---|---|
| Asignación simple | api_key = "sk-abc123" | Arreglado | Reescritura determinista del AST |
| Atributo de clase | class C: SECRET = "abc" | Arreglado | Reescritura determinista del AST |
| Argumento de palabra clave | connect(password="abc") | Arreglado | Reescritura determinista del AST |
| f-string | key = f"prefix_{v}" | Rechazado | La reescritura cambiaría el comportamiento en runtime |
| Concatenación | key = "sk-" + suffix | Rechazado | La reescritura cambiaría el comportamiento en runtime |
| Valor de diccionario/anidado | cfg = {"pass": "abc"} | Rechazado | No es un objetivo de asignación simple |
| Asignación múltiple | A = B = "secret" | Rechazado | Objetivo ambiguo |
| Ya seguro | key = os.getenv("KEY") | Omitido | No se necesita cambio |
Falta .env.example | cualquier patrón | Rechazado | Sin contrato de env para derivar nombre de variable |
Re-ejecutar sobre un archivo limpio no hace cambios. Las reescrituras mantienen la indentación y comentarios originales. import os se agrega solo si falta.
Para que tu build falle si se detectan secretos:
- name: Scan for secrets
run: autonoma scan .
analyze se mantiene por compatibilidad hacia atrás. Migra a scan o fix.
# Equivalente a 'autonoma scan'
autonoma analyze src/ --detect-only
# Equivalente a 'autonoma fix'
autonoma analyze src/ --auto-fix
API_KEY = "secret"class Config: PASS = "secret"connect(password="secret")A = B = "secret") o desempaquetado de tuplas..env.example o contrato de entorno en el repo.Los casos rechazados se reportan en la salida JSON y causarán códigos de salida distintos de cero en CI. El archivo nunca se modifica si algún problema en él es rechazado.
<file>.bak antes de la modificación.