Auditoría de Seguridad y Licencias - CreaRack Pro
Documento de referencia obligatoria al instalar nuevas dependencias. Última auditoría: 06-02-2026 Versión auditada: v6.5.9
Resumen Ejecutivo
| Categoría | Estado | Observaciones |
|---|---|---|
| Configuración de seguridad | ✅ OK | HTTPS, HSTS, CSRF configurados |
| Vulnerabilidades código | ✅ OK | innerHTML protegido con escapeHtml() |
| Rate Limiting | ✅ OK | Middleware implementado (100 req/min) |
| Content Security Policy | ✅ OK | CSP middleware con directivas estrictas |
| Licencias Python | ✅ OK | Todas compatibles (MIT, BSD, Apache) |
| Licencias JavaScript | ✅ OK | MIT, Apache |
| Datos sensibles | ✅ OK | .env en .gitignore |
| OWASP Top 10 | ✅ OK | Sin vulnerabilidades críticas |
1. Configuración de Seguridad Django
1.1 Producción (config/settings/production.py)
| Setting | Valor | Estado |
|---|---|---|
DEBUG | False | ✅ Correcto |
SECURE_SSL_REDIRECT | True | ✅ Fuerza HTTPS |
SESSION_COOKIE_SECURE | True | ✅ Cookies solo HTTPS |
CSRF_COOKIE_SECURE | True | ✅ CSRF solo HTTPS |
SECURE_HSTS_SECONDS | 31536000 | ✅ 1 año HSTS |
SECURE_HSTS_INCLUDE_SUBDOMAINS | True | ✅ Incluye subdominios |
SECURE_HSTS_PRELOAD | True | ✅ Preload list |
SECURE_CONTENT_TYPE_NOSNIFF | True | ✅ Previene MIME sniffing |
X_FRAME_OPTIONS | DENY | ✅ Previene clickjacking |
SECURE_BROWSER_XSS_FILTER | True | ✅ Filtro XSS navegador |
1.2 Desarrollo (config/settings/base.py)
| Setting | Valor | Nota |
|---|---|---|
SESSION_COOKIE_HTTPONLY | True | ✅ No accesible desde JS |
SESSION_COOKIE_SAMESITE | Lax | ✅ Protección CSRF |
SESSION_COOKIE_SECURE | False | ⚠️ Normal en dev (True en prod) |
SECRET_KEY | Desde .env | ✅ No hardcodeada |
1.3 Middleware de Seguridad
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware", # ✅
"django.middleware.csrf.CsrfViewMiddleware", # ✅
"django.middleware.clickjacking.XFrameOptionsMiddleware", # ✅
]
2. Análisis de Vulnerabilidades (OWASP Top 10)
2.1 Injection (A03:2021)
| Tipo | Estado | Detalle |
|---|---|---|
| SQL Injection | ✅ Seguro | Usa Django ORM exclusivamente |
| Command Injection | ⚠️ Controlado | local_agent.py ejecuta comandos SSH - validados |
| Template Injection | ✅ Seguro | No usa mark_safe ni ` |
Archivos revisados:
- No se encontró uso directo de
cursor.execute()con strings sin parametrizar - No se encontró uso de
mark_safeque podría inyectar HTML
2.2 Cross-Site Scripting - XSS (A07:2021)
| Patrón | Ocurrencias | Riesgo |
|---|---|---|
innerHTML = | 100 en 18 archivos | ✅ Mitigado |
document.write | 0 | ✅ Ninguno |
eval() | 0 (excepto libs) | ✅ Ninguno |
Análisis Detallado de innerHTML (100 usos)
Clasificación por riesgo:
| Categoría | Cantidad | Riesgo | Estado |
|---|---|---|---|
| HTML estático/templates | ~70 | ✅ Bajo | No requiere acción |
| Datos del servidor | ~25 | ✅ Solucionado | Protegido con escapeHtml() |
| Datos de usuario directo | ~5 | ✅ Solucionado | Protegido con escapeHtml() |
Archivos con usos de innerHTML:
| Archivo | Usos | Estado | Fecha Fix |
|---|---|---|---|
network_tools.js | 34 | ✅ Protegido | 29-01-2026 |
import_export.js | 10 | ✅ Protegido | 29-01-2026 |
backups.js | 9 | ✅ Protegido | 29-01-2026 |
base.js | 9 | ✅ Protegido | 29-01-2026 |
sftp_ui.js | 4 | ✅ Protegido | 29-01-2026 |
script_manager.js | 4 | ✅ Protegido | 29-01-2026 |
dashboard.js | 5 | ✅ Bajo (estático) | N/A |
Mitigación Implementada (29-01-2026)
Función escapeHtml() añadida a static/js/base.js:
/**
* Escapes HTML special characters to prevent XSS attacks.
* @param {string} str - The string to escape
* @returns {string} - HTML-escaped string
*/
function escapeHtml(str) {
if (str === null || str === undefined) return '';
const div = document.createElement('div');
div.textContent = String(str);
return div.innerHTML;
}
window.escapeHtml = escapeHtml; // Disponible globalmente
Casos corregidos:
| Archivo | Línea | Variable | Antes | Después |
|---|---|---|---|---|
base.js | 131 | message | ${message} | ${escapeHtml(message)} |
import_export.js | 183 | err.error | ${err.error} | ${escapeHtml(err.error)} |
import_export.js | 460 | cat.name | ${cat.name} | ${escapeHtml(cat.name)} |
backups.js | 620 | e.message | ${e.message} | ${escapeHtml(e.message)} |
sftp_ui.js | 169 | msg | ${msg} | ${escapeHtml(msg)} |
script_manager.js | 74 | error.message | ${error.message} | ${escapeHtml(error.message)} |
network_tools.js | 1869 | port, serviceName | ${port} | ${escapeHtml(port)} |
Casos de Riesgo Bajo (No requieren acción)
Los ~70 casos restantes son HTML estático/templates que:
- No incluyen variables interpoladas con datos externos
- Son estructuras de UI predefinidas (tablas, layouts)
- El esfuerzo de refactorización no justifica el beneficio nulo
Ejemplo de caso de riesgo bajo (NO requiere cambio):
// HTML completamente estático - seguro
resultsDiv.innerHTML = `
<table class="results-table">
<thead><tr><th>IP</th><th>Status</th></tr></thead>
<tbody id="results-tbody"></tbody>
</table>
`;
Recomendaciones Pendientes
| Prioridad | Acción | Estado |
|---|---|---|
escapeHtml() centralizada | ✅ Completado | |
| ✅ Completado | ||
| Media | Implementar CSP (Content Security Policy) | 🔲 Pendiente |
Guía para Nuevos Desarrollos
OBLIGATORIO usar escapeHtml() cuando:
- Se inserta cualquier dato del servidor en innerHTML
- Se muestran mensajes de error
- Se muestran nombres de entidades (categorías, usuarios, etc.)
// ✅ CORRECTO - Dato dinámico escapado
div.innerHTML = `<span>${escapeHtml(userData.name)}</span>`;
// ❌ INCORRECTO - Dato dinámico sin escapar
div.innerHTML = `<span>${userData.name}</span>`;
// ✅ CORRECTO - HTML estático (no necesita escape)
div.innerHTML = '<table><tr><th>Header</th></tr></table>';
// Uso:
div.innerHTML = `<label>${escapeHtml(cat.name)}</label>`;
2.3 Broken Authentication (A07:2021)
| Control | Estado |
|---|---|
| Password validators | ✅ 4 validators activos |
| Session timeout | ✅ 2 semanas |
| Session en cache (no DB) | ✅ Más seguro |
2.4 Sensitive Data Exposure (A02:2021)
| Dato | Protección |
|---|---|
| Credenciales DB | ✅ En .env (no en repo) |
| API Keys (Gemini, etc.) | ✅ En .env |
| Passwords de red | ✅ Cifrados con Fernet |
.env en .gitignore | ✅ Verificado |
3. Licencias de Dependencias
3.1 Dependencias Python
| Paquete | Versión | Licencia | Uso Comercial |
|---|---|---|---|
| Django | 6.0.1 | BSD-3-Clause | ✅ Permitido |
| django-ninja | 1.5.3 | MIT | ✅ Permitido |
| channels | 4.3.0 | BSD-3-Clause | ✅ Permitido |
| daphne | 4.1.2 | BSD-3-Clause | ✅ Permitido |
| psycopg2-binary | 2.9.11 | LGPL | ✅ Permitido (binario) |
| redis | 5.2.1 | MIT | ✅ Permitido |
| cryptography | 43.0.0+ | Apache-2.0/BSD | ✅ Permitido |
| pydantic | 2.10+ | MIT | ✅ Permitido |
| Pillow | 11.1.0 | HPND | ✅ Permitido |
| requests | 2.32.3 | Apache-2.0 | ✅ Permitido |
| asyncssh | 2.18.0 | EPL-2.0 | ✅ Permitido |
| scrapli | 2024.7.30 | MIT | ✅ Permitido |
| huey | 2.5.2 | MIT | ✅ Permitido |
| gunicorn | 23.0.0 | MIT | ✅ Permitido |
| uvicorn | 0.34.0 | BSD-3-Clause | ✅ Permitido |
| werkzeug | 3.1.3 | BSD-3-Clause | ✅ Permitido |
| google-genai | 1.60.0+ | Apache-2.0 | ✅ Permitido |
| openai | 1.0.0+ | MIT | ✅ Permitido |
| anthropic | 0.52.0+ | MIT | ✅ Permitido |
| groupdocs-conversion-cloud | 24.8.0 | MIT | ✅ Permitido |
| django-allauth | 65.4.0 | MIT | ✅ Permitido |
| fido2 | 1.1.x | BSD-2-Clause | ✅ Permitido |
| PyJWT | 2.8.0+ | MIT | ✅ Permitido |
| pysnmp | 6.2.0+ | BSD-2-Clause | ✅ Permitido |
| icmplib | 3.0.4+ | LGPL-3.0 | ✅ Permitido (como librería) |
| aiohttp | 3.11.0+ | Apache-2.0 | ✅ Permitido |
3.2 Dependencias JavaScript
| Librería | Versión | Licencia | Ubicación |
|---|---|---|---|
| Konva.js | 9.2.1 | MIT | static/js/lib/konva.min.js |
| Apache ECharts | 5.5.0 | Apache-2.0 | static/js/vendor/echarts.min.js |
| Flatpickr | 4.6.13 | MIT | static/js/vendor/flatpickr.min.js |
| GridStack.js | 12.4.2 | MIT | static/js/vendor/gridstack-all.min.js |
| jQuery | (admin) | MIT | staticfiles/admin/js/vendor/ |
| Select2 | (admin) | MIT | staticfiles/admin/js/vendor/ |
| xregexp | (admin) | MIT | staticfiles/admin/js/vendor/ |
| Playwright | 1.57.0 | Apache-2.0 | devDependency (tests) |
3.3 Resumen de Licencias
| Licencia | Cantidad | Compatible SaaS |
|---|---|---|
| MIT | 19 | ✅ Sí |
| BSD-3-Clause | 6 | ✅ Sí |
| BSD-2-Clause | 2 | ✅ Sí |
| Apache-2.0 | 7 | ✅ Sí |
| LGPL | 1 | ✅ Sí (binario) |
| LGPL-3.0 | 1 | ✅ Sí (como librería) |
| EPL-2.0 | 1 | ✅ Sí |
| HPND | 1 | ✅ Sí |
Conclusión: Todas las licencias son compatibles con uso comercial SaaS.
Nota sobre LGPL-3.0 (icmplib): Uso permitido como librería sin modificaciones. Si se modifica el código fuente de icmplib, los cambios deben publicarse bajo LGPL-3.0.
4. Datos Sensibles y Secretos
4.1 Archivos Protegidos
| Archivo | En .gitignore | Estado |
|---|---|---|
.env | ✅ Sí | Protegido |
.env.local | ✅ Sí | Protegido |
.env.*.local | ✅ Sí | Protegido |
db.sqlite3 | ✅ Sí | Protegido |
logs/ | ✅ Sí | Protegido |
media/uploads/ | ✅ Sí | Protegido |
media/temp/ | ✅ Sí | Protegido |
4.2 Variables de Entorno Requeridas
# Obligatorias en producción
DJANGO_SECRET_KEY=<clave-segura-256-bits>
POSTGRES_PASSWORD=<password-seguro>
DJANGO_ALLOWED_HOSTS=dominio.com
CSRF_TRUSTED_ORIGINS=https://dominio.com
# APIs externas
GEMINI_API_KEY=<api-key>
# Opcionales
EMAIL_HOST_PASSWORD=<smtp-password>
GITHUB_TOKEN=<token>
5. Checklist para Nuevas Dependencias
OBLIGATORIO: Antes de instalar cualquier nueva dependencia, verificar:
5.1 Seguridad
- ¿Tiene vulnerabilidades conocidas? (verificar en Snyk o Safety)
- ¿Última actualización < 1 año?
- ¿Tiene mantenimiento activo? (commits recientes)
- ¿Código fuente disponible y auditable?
5.2 Licencia
- ¿Licencia compatible con uso comercial?
- ¿Requiere atribución? (MIT, Apache: sí)
- ¿Licencia viral? (GPL: verificar implicaciones)
- Registrar en este documento (sección 3)
5.3 Licencias Compatibles (SaaS)
| Licencia | Permitida | Requisitos |
|---|---|---|
| MIT | ✅ | Mantener copyright |
| BSD (2/3-Clause) | ✅ | Mantener copyright |
| Apache 2.0 | ✅ | Mantener copyright + NOTICE |
| ISC | ✅ | Mantener copyright |
| LGPL | ⚠️ | Solo como librería dinámica |
| GPL | ❌ | Evitar (viral) |
| AGPL | ❌ | Evitar (muy restrictiva) |
5.4 Registro Obligatorio
Al añadir una dependencia, actualizar:
requirements.txtopackage.json- Este documento (sección 3)
core/licenses.py— Registro público visible en/licenses(listasPYTHON_DEPENDENCIES,FRONTEND_DEPENDENCIESoINFRASTRUCTURE_DEPENDENCIES)CHANGELOG.md
6. Recomendaciones de Mejora
6.1 Estado de Implementación
| # | Recomendación | Estado | Fecha |
|---|---|---|---|
| 1 | Auditar usos de innerHTML en JS | ✅ Completado | 29-01-2026 |
| 2 | Implementar CSP (Content Security Policy) | ✅ Completado | 29-01-2026 |
| 3 | Rate limiting en API | ✅ Completado | 29-01-2026 |
| 4 | Añadir headers de seguridad adicionales | ✅ Completado | 29-01-2026 |
| 5 | Implementar logging de seguridad | ✅ Existente | SystemLog model |
| 6 | Escaneo automático de dependencias | 🔲 Pendiente | CI/CD futuro |
6.2 Rate Limiting Implementado
Ubicación: core/middleware/rate_limit.py
Configuración (en settings/base.py y settings/production.py):
RATE_LIMIT_ENABLED = True # False en desarrollo, True en producción
RATE_LIMIT_REQUESTS = 100 # Peticiones por ventana
RATE_LIMIT_WINDOW = 60 # Ventana en segundos
# Límites específicos por endpoint
RATE_LIMIT_ENDPOINTS = {
'/api/auth/login': {'requests': 5, 'window': 60}, # 5/min
'/api/auth/register': {'requests': 3, 'window': 60}, # 3/min
'/api/blueprints/auto-plan': {'requests': 10, 'window': 60}, # AI
'/admin/login/': {'requests': 5, 'window': 60}, # Admin
}
Headers de respuesta:
X-RateLimit-Limit: Límite máximoX-RateLimit-Remaining: Peticiones restantesX-RateLimit-Reset: Timestamp de resetRetry-After: Segundos para reintentar (solo en 429)
6.3 Content Security Policy (CSP) Implementado
Ubicación: core/middleware/csp.py
Modos:
- Desarrollo:
CSP_REPORT_ONLY = True(solo reporta, no bloquea) - Producción:
CSP_REPORT_ONLY = False(bloquea violaciones)
Directivas configuradas:
| Directiva | Valor | Propósito |
|---|---|---|
default-src | 'self' | Solo recursos propios |
script-src | 'self' 'unsafe-inline' | Scripts (legacy requiere inline) |
style-src | 'self' 'unsafe-inline' fonts.googleapis.com | Estilos |
font-src | 'self' fonts.gstatic.com data: | Fuentes |
img-src | 'self' data: blob: | Imágenes (Konva exports) |
connect-src | 'self' ws: wss: 127.0.0.1:5050 | WebSocket + Agent |
frame-src | 'none' | Sin iframes |
object-src | 'none' | Sin plugins |
frame-ancestors | 'none' | Anti-clickjacking |
6.4 Pendientes para Futuro
| # | Recomendación | Prioridad | Notas |
|---|---|---|---|
| 1 | Eliminar 'unsafe-inline' de CSP | Media | Requiere refactor JS |
| 2 | Escaneo automático de dependencias | Baja | Añadir a CI/CD |
| 3 | CSP reporting endpoint | Baja | Para monitorear violaciones |
7. Historial de Auditorías
| Fecha | Versión | Auditor | Resultado |
|---|---|---|---|
| 29-01-2026 | v6.1.1 | Claude | ✅ Aprobado con observaciones |
8. Próxima Auditoría
- Fecha recomendada: Trimestral o al añadir dependencias críticas
- Triggers automáticos:
- Nueva dependencia de red/auth
- Actualización major de Django
- Cambio en manejo de credenciales
Mantenido por: Equipo CreaRack + Claude Última actualización: 06-02-2026
Véase también
- [[crearack-tech—reports—security-audit-04-04-2026]] — auditoría de seguridad crearack.com
- [[crearack-tech—guides—security-guide]] — guía de seguridad
- [[crearack-tech—guides—secret-rotation-playbook]] — playbook de rotación de secretos
- [[crearack-tech—backend—passkeys-authentication]] — autenticación con passkeys
- [[workspace-tech—tecnico—security-audit-11-04-2026]] — auditoría seguridad workspace
- [[crearack-tech—reports—infrastructure-robustness-audit-04-04-2026]] — auditoría de robustez infra