---
id: "0060"
title: "`fn doctor secrets`: scan de secrets en TODOS los repos"
status: pendiente
type: feature
domain: []
scope: multi-app
priority: media
depends: []
blocks: []
related: []
created: 2026-05-17
updated: 2026-05-17
tags: [ausente-ready]
---
# 0060 — `fn doctor secrets`: scan de secrets en TODOS los repos

## APP Metadata

| Campo | Valor |
|-------|-------|
| **ID** | 0060 |
| **Estado** | pendiente |
| **Prioridad** | media |
| **Tipo** | feature — `cmd/fn/doctor.go` + funcion del registry |

## Dependencias

- `scan_secrets_in_dirty_bash_cybersecurity` ya existe (escanea solo dirty trees por nombres sospechosos).
- `discover_git_repos_bash_infra` ya existe.
- Pre-commit hook v2 invoca `scan_secrets_in_dirty` por repo.

## Contexto

Hoy el escaneo de secrets ocurre solo:

1. En el pre-commit hook (de cada repo, sobre dirty tree antes del commit).
2. Cuando el usuario invoca manualmente `scan_secrets_in_dirty.sh`.

NO hay un audit global "scan TODOS los repos en una pasada" para detectar secrets que ya esten commiteados (caso peor) o staged en repos que no se commitearon hoy. Riesgo: una key olvidada en un repo viejo puede estar pushed a Gitea desde hace meses sin que nadie lo sepa.

## Objetivo

Anadir subcomando `fn doctor secrets` que:

1. Itera TODOS los repos descubiertos por `discover_git_repos`.
2. Por cada uno, escanea TODO el HEAD (no solo dirty) buscando:
   - Nombres sospechosos (`*.env`, `*credentials*`, `*.key`, `*.pem`, `id_rsa*`, `*secret*`, `*token*.txt`).
   - Patterns en contenido: AWS keys (`AKIA...`), JWT tokens, GitHub tokens (`ghp_...`), Google API keys (`AIza...`).
3. Reporta hallazgos como en otros `fn doctor` (texto humano + `--json`).
4. Exit 0 si limpio, 1 si encuentra algo.

## Arquitectura

### Archivos afectados

- NUEVA funcion `scan_secrets_repo_bash_cybersecurity` (`bash/functions/cybersecurity/scan_secrets_repo.sh` + `.md`) — version "todo el repo" del existente.
- NUEVA funcion `scan_secrets_all_repos_go_cybersecurity` (`functions/cybersecurity/scan_secrets_all_repos.go`) — orquestador Go que itera repos y compone resultado.
- `cmd/fn/doctor.go` — anadir subcomando `secrets` que invoca la funcion Go.
- `.claude/rules/fn_doctor.md` — anadir entrada para `secrets`.

## Tareas

### Fase 1 — funcion bash de scan completo
1.1 Crear `scan_secrets_repo_bash_cybersecurity`:
    - Args: `<repo_dir>`.
    - Lista todos los archivos tracked por git (`git ls-files`).
    - Para cada uno, aplica los filtros de nombre y luego `grep -E` patterns en contenido.
    - Output: lineas `SECRET <type> <repo>:<file>:<line> <pattern_match>`.
    - Exit 0 si limpio, 1 si hay matches.

### Fase 2 — orquestador Go
2.1 `ScanSecretsAllRepos(registryRoot string) ([]SecretFinding, error)`.
2.2 Llama internamente `discover_git_repos` (via shell-out o portar a Go).
2.3 Por cada repo, ejecuta `scan_secrets_repo.sh` y agrega findings.
2.4 Test con repo temporal con archivo dummy `.env`.

### Fase 3 — CLI + docs
3.1 Anadir case `secrets` a `cmd/fn/doctor.go`.
3.2 Texto humano: tabla `REPO | FILE | TYPE | MATCH`.
3.3 `--json`: array de findings.
3.4 Anadir a `fn doctor` (todos los checks).
3.5 Actualizar `.claude/rules/fn_doctor.md` y CHANGELOG.

## Riesgos

- False positives en repos con muchos archivos. Mitigacion: aplicar filtros estrictos, opcion `--ignore-file` con regex.
- Lentitud: escanear todos los `git ls-files` de 32 sub-repos puede tardar segundos. Mitigacion: paralelizar por repo (goroutines).
- Si encuentra secret real, exponerlo en stdout es contradictorio. Mitigacion: redactar el match (`AKIA****REDACTED****`) en output.

## Decisiones de diseno

- Mantener la deteccion bash (scan_secrets_repo) — es lo que usan los hooks. El orquestador Go solo agrega.
- Patterns hardcodeados al principio. Despues mover a archivo de config si crecen.
- NO integrar gitleaks/trufflehog — aumenta deps externas. Los patterns basicos cubren 95% de casos.
