Skip to content

7. Gestión de secretos

Temas del programa: 3.4.3 y 3.4.4

Cualquier valor que da acceso a algo · si otra persona lo tiene puede actuar como tú o como tu sistema

Credenciales

DB_PASSWORD · usuario y contraseña de servicios

Llaves

APP_KEY · llaves de API de terceros

Tokens

Tokens de Sanctum · tokens de acceso de GitLab

No son secretos APP_NAME · DB_HOST de tu máquina · el puerto · van en .env.example con su valor

AmbienteDóndeQuién lo ve
Tu máquina.env fuera del repositorioSolo tú
Pruebas locales.env o .env.testing ignoradosSolo tú
Pipeline de CIVariables de CI/CD de GitLabEl pipeline · enmascaradas en el log
ProducciónLa plataforma de despliegueEn el Bloque IV profundizarás en esto
.env DB_PASSWORD=clave-local-de-ana
▼
config/database.php 'password' => env('DB_PASSWORD'),
▼
tu código config('database.connections.pgsql.password')
// Mal: el secreto queda en el repositorio para siempre
$cliente = new ServicioCorreo('sk_live_8f3a...');
// Bien: se lee de la configuración
$cliente = new ServicioCorreo(config('services.correo.key'));

env() solo dentro de config/ · el resto del código usa config()

.env · no se versiona

DB_PASSWORD=clave-local-de-ana
APP_KEY=base64:Qm9...

.env.example · sí se versiona

DB_PASSWORD=
APP_KEY=

Terminal window
cp .env.example .env
php artisan key:generate

Una persona nueva levanta el proyecto con dos comandos sin recibir tus credenciales · STD-SEC-02

En el Bloque II viste qué no entra al repositorio · ahora interesa cómo decide Git y dónde puede fallar

# Entorno y secretos
.env
.env.*
!.env.example
# Generados
/vendor
/node_modules
.phpunit.result.cache
/storage/*.key

recursos/estandares/config-examples/.gitignore adaptado a un proyecto en la raíz

PatrónSignifica
.envCualquier archivo llamado .env
.env.*.env.testing · .env.production · .env.backup
!.env.exampleExcepción · este sí se versiona
/vendorLa carpeta vendor de la raíz solamente
*.logCualquier archivo que termine en .log
# textoComentario

Se leen de arriba hacia abajo · la última regla que coincide gana · por eso el ! va después

Terminal window
$ git check-ignore -v .env
.gitignore:2:.env .env
$ git check-ignore -v .env.testing
.gitignore:3:.env.* .env.testing
$ git status --ignored --short
!! .env
!! vendor/

check-ignore dice qué línea del .gitignore decide el destino de cada archivo

La trampa — .gitignore no deja de rastrear

Section titled “La trampa — .gitignore no deja de rastrear”

.gitignore solo afecta archivos que Git todavía no rastrea · si .env ya se había agregado seguirá subiendo cambios

Terminal window
$ git ls-files .env
.env # Git lo rastrea aunque esté en .gitignore
$ git rm --cached .env # deja de rastrearlo y conserva tu archivo local
$ git commit -m "chore: dejar de versionar .env"

Esto lo saca de los commits futuros · los anteriores lo siguen teniendo

Terminal window
git log --all --oneline -- .env
1 Rotar

Cambiar la contraseña o generar una llave nueva

2 Avisar

Al equipo y al docente

3 Prevenir

Corregir .gitignore y verificar con check-ignore

Antes del commit

git status y git diff --staged · ¿hay un .env o una llave?

En cada push

El pipeline revisa todo el historial con una herramienta de detección de secretos

Finding: DB_PASSWORD=REDACTED
File: config/database.php
Commit: 3f2a1b0

STD-SEC-03 · salida ilustrativa con el secreto ocultado

APP_DEBUG=true

El 500 muestra archivos líneas y datos de conexión

APP_DEBUG=false

El cliente recibe un mensaje genérico y el detalle queda en el log

APP_DEBUG=true solo en tu máquina · en cualquier otro ambiente APP_ENV=production y APP_DEBUG=false

A01 Broken Access ControlA02 Security MisconfigurationA03 Software Supply Chain FailuresA04 Cryptographic Failures
A05 InjectionA06 Insecure DesignA07 Authentication FailuresA08 Software or Data Integrity Failures
A09 Security Logging and Alerting FailuresA10 Mishandling of Exceptional Conditions

top10.owasp.org/2025 consultado 2026-10-20 · el estándar del proyecto aún cita la edición 2021

Inyección

A05 · datos del usuario dentro del SQL

Exposición de información

A01 A02 A10 · datos ajenos o detalles internos

Configuraciones inseguras

A02 · debug abierto o CORS sin control

Dependencias vulnerables

A03 · composer audit

A10 es exactamente el tema de manejo de errores · un error mal controlado también es una vulnerabilidad

// Vulnerable
DB::select("SELECT * FROM equipos WHERE nombre = '{$request->nombre}'");
// Seguro
Equipo::where('nombre', $request->validated('nombre'))->get();

Con x’ OR ‘1’=‘1 la primera consulta devuelve todo

Actividad A6 — mapa de amenazas de tu proyecto

Este tema se practica en el Laboratorio 4 — Desarrollo seguro.

Continúa con 8. Integración continua.