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:

  1. NO crear un problema público en GitHub

  2. Informe de seguridad por correo electrónico a: amrnetdashboard@gmail.com

  3. 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:

Soporte para versiones

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:

  1. Detección: El equipo de seguridad de las alertas de monitorización automática

  2. Evaluación: Determina la gravedad y el alcance del incidente

  3. Contenencia: Aislar los sistemas afectados si es necesario

  4. Investigación: Analiza los registros y determina la causa raíz

  5. Recuperación: Restaurar operaciones normales

  6. 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: