Guía de seguridad¶
AMRnet implementa medidas de seguridad integrales para proteger los datos del usuario y asegurar la integridad de la información de vigilancia de resistencia antimicrobiana. Esta guía cubre políticas de seguridad, mejores prácticas y detalles de implementación.
Política de seguridad¶
AMRnet sigue las prácticas de seguridad estándar de la industria para aplicaciones web que manejan datos sensibles de salud e investigación.
Reporte de vulnerabilidad¶
🚨 Proceso de divulgación responsable
Si descubre una vulnerabilidad de seguridad, siga estos pasos:
NO crear un problema público en GitHub
Informe de seguridad por correo electrónico a: amrnetdashboard@gmail.com
Incluye información detallada: - Descripción de la vulnerabilidad - Pasos para reproducir el problema - Evaluación de impacto Potential - Correcciones sugeridas (si está disponible)
Respuesta cronológica:
24 horas: Confirmación inicial
72 horas: Evaluación preliminar y clasificación de gravedad
7 días: Respuesta detallada con línea de tiempo fija
30 días: Resolución objetivo de vulnerabilidades críticas
Versiones soportadas¶
Se proporcionan actualizaciones de seguridad para:
Versión |
Soportado |
|---|---|
1.x |
✅ Sí |
1.0.x |
✅ Sí |
< 1.0 |
❌ No |
Seguridad de la aplicación¶
AMRnet implementa múltiples capas de controles de seguridad:
Seguridad del entorno¶
Protección variable de entorno:
# Never commit sensitive environment variables
# Use .env.example as template, create .env locally
# Production secrets management
NODE_ENV=production
MONGODB_URI=mongodb+srv://[REDACTED]
SESSION_SECRET=[GENERATED_SECRET]
# Security headers
ENABLE_SECURITY_HEADERS=true
CORS_ORIGIN=https://amrnet.org
Ejemplo de Configuración Segura:
// config/security.js
const securityConfig = {
// HTTPS enforcement
httpsOnly: process.env.NODE_ENV === 'production',
// Security headers
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"],
fontSrc: ["'self'", "https://fonts.gstatic.com"],
imgSrc: ["'self'", "data:", "https:"],
scriptSrc: ["'self'"]
}
},
// Rate limiting
rateLimit: {
windowMs: 15 * 60 * 1000, // 15 minutes
max: 1000 // limit each IP to 1000 requests per windowMs
}
};
Seguridad de la base de datos¶
Configuración de seguridad de MongoDB:
// Secure MongoDB connection
const mongoOptions = {
useNewUrlParser: true,
useUnifiedTopology: true,
// Authentication
authSource: 'admin',
// SSL/TLS
ssl: true,
sslValidate: true,
// Connection limits
maxPoolSize: 10,
minPoolSize: 5,
// Timeouts
serverSelectionTimeoutMS: 5000,
socketTimeoutMS: 45000,
// Security options
bufferMaxEntries: 0,
bufferCommands: false
};
Sanitización de datos:
const sanitize = require('mongo-sanitize');
const validator = require('validator');
// Input sanitization middleware
const sanitizeInput = (req, res, next) => {
// Sanitize against NoSQL injection
req.body = sanitize(req.body);
req.query = sanitize(req.query);
req.params = sanitize(req.params);
// Additional validation
Object.keys(req.query).forEach(key => {
if (typeof req.query[key] === 'string') {
req.query[key] = validator.escape(req.query[key]);
}
});
next();
};
Seguridad API¶
Autenticación y Autorización:
const jwt = require('jsonwebtoken');
const rateLimit = require('express-rate-limit');
// API rate limiting
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 1000, // limit each IP to 1000 requests per windowMs
message: 'Too many requests from this IP',
standardHeaders: true,
legacyHeaders: false,
});
// JWT authentication for protected endpoints
const authenticateToken = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.sendStatus(401);
}
jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
};
Configuración CORS:
const cors = require('cors');
const corsOptions = {
origin: function (origin, callback) {
const allowedOrigins = [
'https://amrnet.org',
'https://www.amrnet.org',
process.env.NODE_ENV === 'development' && 'http://localhost:3000'
].filter(Boolean);
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
credentials: true,
optionsSuccessStatus: 200
};
Seguridad de Frontend¶
Política de seguridad del contenido:
<!-- Security headers in HTML -->
<meta http-equiv="Content-Security-Policy"
content="default-src 'self';
script-src 'self' 'unsafe-inline';
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src 'self' https://fonts.gstatic.com;
img-src 'self' data: https:;">
Prevención XSS:
import DOMPurify from 'dompurify';
// Sanitize user input before rendering
const SafeHTML = ({ content }) => {
const cleanHTML = DOMPurify.sanitize(content);
return <div dangerouslySetInnerHTML={{ __html: cleanHTML }} />;
};
// Input validation
const validateInput = (input) => {
if (typeof input !== 'string') return false;
if (input.length > 1000) return false;
// Check for malicious patterns
const maliciousPatterns = [
/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
/javascript:/gi,
/on\w+\s*=/gi
];
return !maliciousPatterns.some(pattern => pattern.test(input));
};
Privacidad de datos¶
AMRnet implementa principios de privacidad por diseño para manejar datos de vigilancia:
Clasificación de datos¶
Datos públicos: - Estadísticas de vigilancia agregadas - Datos de prevalencia a nivel del país - Conjuntos de datos de investigación disponibles públicamente
Datos restringidos: - Identificadores individuales de muestra (cuando están presentes) - Coordenadas geográficas detalladas - Datos de investigación no publicados
Datos prohibidos: - Información personal de salud (PHI) - Identificadores del paciente - Detalles clínicos más allá de los patrones de resistencia
Controles de privacidad¶
Minimización de datos:
// Example: Remove sensitive fields before transmission
const sanitizeDataForPublic = (data) => {
return data.map(record => ({
// Include only necessary fields
country: record.COUNTRY_ONLY,
year: record.YEAR,
genotype: record.GENOTYPE,
resistance: record.RESISTANCE_PROFILE,
// Exclude: individual IDs, precise coordinates, etc.
}));
};
Anonimización:
// Geographic aggregation for privacy
const aggregateByRegion = (data) => {
const aggregated = {};
data.forEach(record => {
const region = getRegionFromCountry(record.country);
if (!aggregated[region]) {
aggregated[region] = {
count: 0,
resistanceProfiles: {}
};
}
aggregated[region].count++;
// Aggregate resistance data without individual records
});
return aggregated;
};
Desarrollo seguro¶
Prácticas de seguridad para el desarrollo y la implementación:
Código de seguridad¶
Gestión de dependencias:
# Regular security audits
npm audit
# Update vulnerable dependencies
npm audit fix
# Use lock files to prevent supply chain attacks
npm ci # Use exact versions from package-lock.json
Linting de seguridad:
# ESLint security plugin
npm install --save-dev eslint-plugin-security
# .eslintrc.js
module.exports = {
plugins: ['security'],
extends: ['plugin:security/recommended'],
rules: {
'security/detect-object-injection': 'error',
'security/detect-non-literal-regexp': 'error',
'security/detect-unsafe-regex': 'error'
}
};
Seguridad Git¶
Prácticas de repositorio seguras:
# Git hooks for security
# pre-commit hook
#!/bin/sh
# Check for secrets in commits
git diff --cached --name-only | xargs grep -l "password\|secret\|key\|token" && {
echo "Potential secret detected! Commit aborted."
exit 1
}
# Run security linting
npm run lint:security
Gestión secreta:
# .gitignore - Never commit sensitive files
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# Security credentials
*.pem
*.key
*.crt
# Database dumps
*.sql
*.dump
Seguridad de despliegue¶
Configuraciones de seguridad para el despliegue de producción:
Seguridad del servidor¶
Encabezados de seguridad:
const helmet = require('helmet');
app.use(helmet({
// Content Security Policy
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"],
fontSrc: ["'self'", "https://fonts.gstatic.com"],
imgSrc: ["'self'", "data:", "https:"],
scriptSrc: ["'self'"],
connectSrc: ["'self'", "https://api.amrnet.org"]
}
},
// Other security headers
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
},
frameguard: { action: 'deny' },
noSniff: true,
xssFilter: true,
referrerPolicy: { policy: 'same-origin' }
}));
Seguridad de la infraestructura¶
Configuración HTTPS:
# Nginx SSL configuration
server {
listen 443 ssl http2;
server_name amrnet.org www.amrnet.org;
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/private.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
ssl_prefer_server_ciphers off;
# Security headers
add_header Strict-Transport-Security "max-age=63072000" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
}
Monitoreo y Respuesta de Incidentes¶
Seguimiento continuo de la seguridad y respuesta a incidentes:
Monitoreo de seguridad¶
Registro y alerta:
const winston = require('winston');
// Security event logging
const securityLogger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'logs/security.log' })
]
});
// Failed authentication attempts
const logFailedAuth = (req, ip, reason) => {
securityLogger.warn('Failed authentication attempt', {
ip: ip,
userAgent: req.get('User-Agent'),
reason: reason,
timestamp: new Date().toISOString()
});
};
Detección de intrusión:
// Suspicious activity detection
const suspiciousActivityDetector = {
failedAttempts: new Map(),
checkFailedLogins: (ip) => {
const attempts = this.failedAttempts.get(ip) || 0;
this.failedAttempts.set(ip, attempts + 1);
if (attempts > 5) {
// Trigger security alert
this.triggerSecurityAlert(`Multiple failed login attempts from ${ip}`);
}
},
triggerSecurityAlert: (message) => {
securityLogger.error('Security Alert', { message });
// Send notification to security team
}
};
Respuesta de incidente¶
Procedimientos de respuesta:
Detección: El equipo de seguridad de las alertas de monitorización automática
Evaluación: Determina la gravedad y el alcance del incidente
Contenencia: Aislar los sistemas afectados si es necesario
Investigación: Analiza los registros y determina la causa raíz
Recuperación: Restaurar operaciones normales
Lecciones aprendidas: Actualizar medidas de seguridad basadas en los hallazgos
Prueba de seguridad¶
Las pruebas de seguridad regulares garantizan protección continua:
Prueba automatizada¶
Suite de prueba de seguridad:
// __tests__/security.test.js
describe('Security Tests', () => {
it('should prevent SQL injection in API endpoints', async () => {
const maliciousInput = "'; DROP TABLE users; --";
const response = await request(app)
.get(`/api/organisms?country=${maliciousInput}`)
.expect(400);
expect(response.body.error).toContain('Invalid input');
});
it('should enforce rate limiting', async () => {
const requests = Array(1001).fill().map(() =>
request(app).get('/api/organisms')
);
const responses = await Promise.all(requests);
const rateLimited = responses.filter(r => r.status === 429);
expect(rateLimited.length).toBeGreaterThan(0);
});
});
Pruebas de penetración¶
Evaluaciones de seguridad regulares:
Análisis de vulnerabilidades trimestrales
Pruebas anuales de penetración por empresas de seguridad de terceros
Seguimiento continuo de la seguridad
Programa de recompensas de errores para divulgación responsable
Lista de mejores prácticas¶
Lista de control de seguridad de desarrollo:
✅ Seguridad del entorno - [ ] Nunca comprometer secretos al control de versiones - [ ] Usar gestión segura de variables de entorno - [ ] Implementar rotación secreta adecuada
✅ Seguridad de la aplicación - [ ] Validación y saneamiento de la entrada - [ ] Codificación de salida para prevenir XSS - [ ] Prevención de inyección SQL - [ ] Autenticación y autorización
✅ Seguridad en Infraestructura - [ ] Implementación de HTTPS - [ ] Implementación de cabeceras de seguridad - [ ] Actualizaciones regulares de dependencias - [ ] Controles de acceso a base de datos
✅ Monitoreo y Respuesta - [ ] Registro de eventos de seguridad - [ ] Sistemas de detección de intrusos - [ ] Procedimientos de respuesta a incidentes - [ ] Evaluaciones de seguridad regulares
Información de contacto¶
Contacto del equipo de seguridad:
Email: amrnetdashboard@gmail.com
Clave PGP: disponible bajo petición
Tiempo de respuesta: 24 horas para reconocimiento inicial
Para preguntas de seguridad general:
Discusiones de GitHub: https://github.com/amrnet/amrnet/discussions
Documentación: https://amrnet.readthedocs.io