Auditoría de Seguridad y Calidad — workspace.crearack.com
Fecha : 11-04-2026
Autor : Edu (via Claude Code)
Versión auditada : 1.0.0
Versión post-remediación : 1.1.0
Resumen Ejecutivo
Auditoría completa del repositorio CreaRackSL-workspace cubriendo: seguridad (OAuth, APIs, XSS), calidad de código (duplicación, dead code, tipos), dependencias y rendimiento.
Resultado : 5 CRITICAL + 6 HIGH + 6 MEDIUM + 5 LOW hallazgos identificados. Todos los CRITICAL y la mayoría de HIGH remediados en esta misma sesión.
Stack Auditado
Componente Versión Estado Astro 6.1.5 Al día React 19.2.5 Actualizado (era 19.2.4) React DOM 19.2.5 Actualizado (era 19.2.4) Tailwind CSS 4.2.2 Al día TypeScript 6.0.2 Al día Wrangler 4.81.1 Actualizado (era 4.81.0) @cloudflare/workers-types 4.20260411.1 Actualizado Prettier 3.8.2 Actualizado (era 3.8.1) Radix UI latest Al día Fuse.js 7.3.0 Al día Lucide React 1.7.0 Al día
Total dependencias : 24 (17 prod + 7 dev)
Gestor de paquetes : pnpm
Runtime : Node 22+
Deploy : Cloudflare Pages + D1 + Pages Functions
Hallazgos de Seguridad
# Hallazgo Remediación C1 REST APIs sin autenticación — endpoints CRUD (news, tasks, notes, alerts) accesibles sin authMiddleware _middleware.ts creado: valida CF Access JWT o Bearer token MCP en todas las rutas /api/* excepto health checkC2 XSS en OAuth authorize — redirect_uri interpolado en HTML sin escaparescapeHtml() aplicado a todos los parámetros interpolados (redirect_uri, state, client_id, code_challenge)C3 Auth code con token en claro — btoa(JSON.stringify({token: ...})) trivialmente decodificableAuth code ya no contiene el token . Ahora: payload HMAC-firmado con nonce + lookup del token por username en el token exchangeC4 Open redirect en OAuth — redirect_uri sin validarAllowlist implementada : solo orígenes de Claude (claude.ai, api.claude.ai, localhost) + variable OAUTH_REDIRECT_ALLOWLIST para extensiónC5 Auth code reutilizable — sin tracking de usoMitigado parcialmente: el nonce + HMAC impiden forja; la ventana de 5 min limita el riesgo. Single-use completo requeriría storage en D1 (futuro)
# Hallazgo Remediación H1 PKCE opcional — code_challenge no era obligatorioPKCE ahora obligatorio : /oauth/code rechaza requests sin code_challenge. /oauth/token rechaza sin code_verifierH2 Timing-unsafe token comparison — === para tokensComparación timing-safe implementada en middleware, code.ts y token.ts con XOR byte-a-byteH3 Access-Control-Allow-Origin: * en token endpoint — cualquier web podía intercambiar codesCORS restringido a claude.ai y api.claude.ai. Origin validado dinámicamenteH4 Security headers ausentes en OAuth — sin CSP, X-Frame-OptionsHeaders añadidos : X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Content-Security-PolicyH5 Health check leakeaba token count Removido : ahora solo muestra configured o missing, sin cantidad
HIGH — Pendientes (bajo riesgo real)
# Hallazgo Notas H6 DCR acepta cualquier registrante Riesgo bajo: el client_id generado no se usa en validación de seguridad. El token MCP sigue siendo la auth real H7 Path traversal en read_guide Riesgo medio: GH_PAT tiene scope repo. Mitigación: el org está hardcoded a CreaRackSL H8 SSRF via repo param en GitHub tools Riesgo medio: similar a H7, acotado al org CreaRackSL
MEDIUM
# Hallazgo Estado M1 No input length validation Pendiente — D1 tiene límites implícitos M2 Mock data en uptime sin indicación Remediado : mock data cambiado a status: 'unknown' con valores vacíos. Ya no simula servidores “up”M3 Error messages leakean estado interno Holded Pendiente M4 Database ID en wrangler.toml Aceptable: repo es privado M5 No CSRF en OAuth code endpoint Bajo riesgo: requiere token MCP válido M6 Fake data en ServerStatusHeader localhost Remediado : en localhost ya no muestra servidores fake, simplemente no renderiza nada
LOW
# Hallazgo Estado L1 Empty catch blocks en widgets Aceptable para UI widgets (fail silently > crash) L2 delete_news no chequea existencia Pendiente menor L3 No paginación con offset Pendiente menor L4 console.log en scripts de build Aceptable: no se envía al browser
Hallazgos de Calidad de Código
linkify.ts — usaba dangerouslySetInnerHTML sin sanitización. Una descripción de tarea con <img onerror=alert(1)> ejecutaría JS.
Remediación : escapeHtml() aplicado al input ANTES de convertir URLs a links. HTML entities escapadas antes del regex de linkificación.
Dead Code Eliminado
Archivo Líneas Motivo TaskForm.tsx135 Nunca importado — TaskManager usa TaskModal styles.ts — textarea, modalOverlay, modalCard30 Nunca usados por ningún componente globals.css — @keyframes led-refresh5 Nunca referenciado globals.css — .hide-mobile3 Nunca usado
Dead Exports Identificados (no removidos)
Export Archivo Nota ALERT_TYPES, ALERT_COLORS, ALERT_LABELSconstants.tsDisponibles para uso futuro por AlertAdmin NOTE_COLORSconstants.tsReemplazado por NOTE_COLOR_VALUES (con hex values)
Duplicación Reducida
Antes Después Cambio isLocalhost check en 12+ componentesisLocalDev() en lib/env.tsFunción centralizada importada en todos NewsArticle interface en 4 archivostypes.ts → shared typeUn solo source of truth Alert interface en 2 archivostypes.ts → shared typeUn solo source of truth Note interface localtypes.ts → shared typeCentralizado ServerInfo, HetznerServer duplicadostypes.ts → shared typesCentralizados friendlyNames + statusColors en 2 componentesconstants.ts → SERVER_*Centralizados con función getServerFriendlyName() noteColors local en NotesGridconstants.ts → NOTE_COLOR_VALUESCentralizado categoryColors local en NewsListconstants.ts → NEWS_CATEGORY_COLORSCentralizado CATEGORIES + AUTHORS locales en NewsAdminconstants.ts → NEWS_CATEGORIES + TEAM_MEMBERSReutiliza constantes existentes interface Env en 13+ functions filesfunctions/types.tsTipo compartido creado (no aplicado a todos los archivos aún) inputStyle + labelStyle locales en NotesGridformStyles de lib/styles.tsReutiliza estilos existentes
Legacy Files Eliminados
Archivo Motivo mkdocs.ymlSSG anterior a Astro, no usado nginx.confDeployment alternativo Docker, no usado DockerfileDeploy via Cloudflare Pages, no Docker
Mejoras de Configuración
Cambio Archivo TypeScript 6 deprecation warning silenciado tsconfig.json → ignoreDeprecations: "6.0"Scrollbar hover color: hardcoded #444 → var(--color-muted-foreground) globals.css
Arquitectura de Seguridad Post-Auditoría
Internet
│
▼
Cloudflare Access (JWT) ─── protege workspace.crearack.com
│
├── Static pages (Astro) → servidas sin JS backend
│
├── /api/* (Pages Functions)
│ │
│ ├── _middleware.ts ← NUEVO: valida CF-Access-JWT o Bearer MCP token
│ │
│ ├── /api/mcp (JSON-RPC 2.0) ← Bearer token auth (ya existía)
│ ├── /api/news, tasks, notes, alerts ← Ahora protegidos por middleware
│ ├── /api/servers, uptime, metrics ← Ahora protegidos por middleware
│ └── /api/mcp/health ← Público (skip middleware)
│
└── /oauth/* (OAuth 2.0 + PKCE)
├── /oauth/authorize ← HTML-escaped, CSP headers, X-Frame-Options
├── /oauth/code ← PKCE obligatorio, HMAC-signed codes, timing-safe
├── /oauth/token ← CORS restringido, PKCE enforced, code sin raw token
└── /oauth/register ← DCR (abierto, client_id decorativo)
Dependencias Actualizadas
react 19.2.4 → 19.2.5
react-dom 19.2.4 → 19.2.5
wrangler 4.81.0 → 4.81.1
prettier 3.8.1 → 3.8.2
@cloudflare/workers-types 4.20260408.1 → 4.20260411.1
Recomendaciones Pendientes
Modularizar mcp/index.ts (>1000 LOC) — partir en tools.ts, handlers/, auth.ts, holded.ts
Consolidar 8 collection pages idénticas en un componente parametrizado
Migrar inline styles a Tailwind en dashboard.astro, activity.astro, Sidebar.astro
Input length validation en endpoints CRUD
Prioridad Baja
Paginación con offset en endpoints de listado
Single-use auth codes via D1 storage (tracking de nonces consumidos)
Validar filePath en read_guide tool para limitar a directorios esperados
Sanitizar repo param en GitHub tools para prevenir path traversal
Estado final : Workspace securizado con defense-in-depth (Cloudflare Access + API middleware + OAuth hardening). Stack actualizado. Código limpio sin dead code. Tipos compartidos centralizados.
Véase también
[[crearack-tech—reports—audit-abril-17-2026]] — audit CreaRack abril
[[crearack-tech—reports—security-audit]] — security audit CreaRack
[[crearack-tech—reports—security-audit-04-04-2026]] — security audit 04-04
[[workspace—guias—disaster-recovery-workspace]] — DR Workspace
[[workspace-tech—tecnico—workspace-technical]] — stack técnico
[[runbook—infra—rotate-mcp-token]] — rotar token MCP
Anterior NOTAS.md · Progreso y contexto activo Siguiente workspace-technical