#!/usr/bin/env bash # ============================================================================== # verificar-anonimato.sh # ============================================================================== # Escanea el contenido versionado de un repositorio buscando datos que NO # deben publicarse: nombres de personas, rutas con usuario, IPs reales, # dominios reales, credenciales y archivos sensibles sin trackear. # # Uso: # ./tools/verificar-anonimato.sh # revisa el repo actual # ./tools/verificar-anonimato.sh /ruta/repo # revisa otro repo # # Salida: 0 = sin hallazgos | 1 = hay hallazgos # ============================================================================== set -uo pipefail REPO="${1:-.}" cd "$REPO" || { echo "No se pudo acceder a: $REPO"; exit 1; } # Nombres de la entidad que publica el codigo: son publicos por decision propia # y no se anonimizan (ver docs/publicacion-anonima.md, exencion institucional). ALLOWLIST_INSTITUCIONAL='Gugler|FCyT' RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BOLD='\033[1m' NC='\033[0m' FINDINGS=0 section() { printf '\n%s== %s ==%s\n' "$BOLD" "$1" "$NC" } hit() { printf ' %s[%s]%s %s\n' "$RED" "$2" "$NC" "$1" FINDINGS=$((FINDINGS + 1)) } printf '%s=== Verificación de anonimato ===%s\n' "$BOLD" "$NC" printf 'Repositorio: %s\n' "$(pwd)" # ----------------------------------------------------------------------------- section "Archivos sensibles trackeados" SENSITIVE=$(git ls-files 2>/dev/null | grep -Ei \ '(^|/)\.env($|\.)|\.pem$|\.key$|\.crt$|acme\.json$|\.sql$|\.dump$|\.p12$|\.pfx$' \ | grep -vE '\.env\.(example|sample|template|global|dist)$' || true) if [ -n "$SENSITIVE" ]; then while IFS= read -r f; do hit "$f" "CRÍTICO" done <<< "$SENSITIVE" else printf ' %s✓%s ninguno\n' "$GREEN" "$NC" fi # ----------------------------------------------------------------------------- section "Dependencias y artefactos pesados" HEAVY=$(git ls-files 2>/dev/null | grep -E '^(vendor/|node_modules/)' | head -10 || true) if [ -n "$HEAVY" ]; then hit "$(echo "$HEAVY" | wc -l) archivos en vendor/ o node_modules/ deben excluirse" "ALTO" else printf ' %s✓%s ninguno\n' "$GREEN" "$NC" fi # ----------------------------------------------------------------------------- section "Rutas con nombre de usuario" PATHS=$(git grep -nE '/home/[a-zA-Z0-9._-]+/' -- . 2>/dev/null | grep -vE 'docker|/home/runner' | head -10 || true) if [ -n "$PATHS" ]; then while IFS= read -r l; do hit "$l" "MEDIO"; done <<< "$PATHS" else printf ' %s✓%s ninguna\n' "$GREEN" "$NC" fi # ----------------------------------------------------------------------------- section "Direcciones IP" IPS=$(git grep -nE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' -- . 2>/dev/null \ | grep -vE '(0\.0\.0\.0|127\.0\.0\.1|255\.|192\.0\.2\.|198\.51\.100\.|203\.0\.113\.|192\.168\.|10\.[0-9]+\.|172\.(1[6-9]|2[0-9]|3[01])\.|1\.1\.1\.1|8\.8\.8\.8)' \ | head -10 || true) if [ -n "$IPS" ]; then while IFS= read -r l; do hit "$l" "MEDIO"; done <<< "$IPS" else printf ' %s✓%s ninguna (solo rangos de documentación)\n' "$GREEN" "$NC" fi # ----------------------------------------------------------------------------- section "Credenciales en texto" CREDS=$(git grep -nEi \ '(password|passwd|secret|api[_-]?key|access[_-]?token)[[:space:]]*[:=][[:space:]]*["'"'"']?[A-Za-z0-9/+_-]{6,}' \ -- . 2>/dev/null | grep -vE '\$\{|CHANGEME|changeme|<[^>]+>|password: *\$|PASSWORD=\$|example' | head -10 || true) if [ -n "$CREDS" ]; then while IFS= read -r l; do hit "$l" "ALTO"; done <<< "$CREDS" else printf ' %s✓%s ninguna\n' "$GREEN" "$NC" fi # ----------------------------------------------------------------------------- section "Emails y dominios" MAILS=$(git grep -nEi '[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}' -- . 2>/dev/null \ | grep -vEi '@(localhost|example\.(com|org|net)|gnu\.org|fsf\.org|w3\.org|iana\.org|localhost\.localdomain)|@?(gugler\.com\.ar)' \ | head -10 || true) if [ -n "$MAILS" ]; then while IFS= read -r l; do hit "$l" "MEDIO"; done <<< "$MAILS" else printf ' %s✓%s ninguno\n' "$GREEN" "$NC" fi # ----------------------------------------------------------------------------- section "Licencia" if [ -f LICENSE ] || [ -f LICENSE.md ] || [ -f COPYING ]; then printf ' %s✓%s presente\n' "$GREEN" "$NC" else printf ' %s[!]%s falta un archivo LICENSE\n' "$YELLOW" "$NC" FINDINGS=$((FINDINGS + 1)) fi # ----------------------------------------------------------------------------- section "Autores en el historial" AUTHORS=$(git log --format='%an <%ae>' --all 2>/dev/null | sort -u | head -10 || true) if [ -n "$AUTHORS" ]; then INST=$(printf '%s\n' "$AUTHORS" | grep -E "$ALLOWLIST_INSTITUCIONAL" || true) REV=$(printf '%s\n' "$AUTHORS" | grep -Ev "$ALLOWLIST_INSTITUCIONAL" || true) if [ -n "$INST" ]; then printf ' %sAutores institucionales (exentos):%s\n' "$GREEN" "$NC" while IFS= read -r a; do printf ' - %s\n' "$a"; done <<< "$INST" fi if [ -n "$REV" ]; then printf ' %sAutores a revisar:%s\n' "$YELLOW" "$NC" while IFS= read -r a; do printf ' - %s\n' "$a"; done <<< "$REV" printf ' %s Revisá que no expongan datos institucionales.%s\n' "$YELLOW" "$NC" fi else printf ' %s✓%s sin commits\n' "$GREEN" "$NC" fi # ----------------------------------------------------------------------------- printf '\n%s=== Resultado ===%s\n' "$BOLD" "$NC" if [ "$FINDINGS" -eq 0 ]; then printf '%s✓ Sin hallazgos: el repositorio puede publicarse.%s\n' "$GREEN" "$NC" exit 0 fi printf '%s✗ %d hallazgo(s). Corregí lo anterior antes de publicar.%s\n' "$RED" "$FINDINGS" "$NC" exit 1