workspace-v1/projects/erp-core/docs/07-devops/SECURITY-HARDENING.md
rckrdmrd 66161b1566 feat: Workspace-v1 complete migration with NEXUS v3.4
Sistema NEXUS v3.4 migrado con:

Estructura principal:
- core/orchestration: Sistema SIMCO + CAPVED (27 directivas, 28 perfiles)
- core/catalog: Catalogo de funcionalidades reutilizables
- shared/knowledge-base: Base de conocimiento compartida
- devtools/scripts: Herramientas de desarrollo
- control-plane/registries: Control de servicios y CI/CD
- orchestration/: Configuracion de orquestacion de agentes

Proyectos incluidos (11):
- gamilit (submodule -> GitHub)
- trading-platform (OrbiquanTIA)
- erp-suite con 5 verticales:
  - erp-core, construccion, vidrio-templado
  - mecanicas-diesel, retail, clinicas
- betting-analytics
- inmobiliaria-analytics
- platform_marketing_content
- pos-micro, erp-basico

Configuracion:
- .gitignore completo para Node.js/Python/Docker
- gamilit como submodule (git@github.com:rckrdmrd/gamilit-workspace.git)
- Sistema de puertos estandarizado (3005-3199)

Generated with NEXUS v3.4 Migration System
EPIC-010: Configuracion Git y Repositorios
2026-01-04 03:37:42 -06:00

25 KiB

SECURITY HARDENING - ERP Generic

Última actualización: 2025-11-24 Responsable: Security Team / DevOps Team Estado: Production-Ready


TABLE OF CONTENTS

  1. Overview
  2. OWASP Top 10 Mitigations
  3. Authentication & Authorization
  4. Input Validation & Sanitization
  5. SQL Injection Prevention
  6. XSS & CSRF Protection
  7. Security Headers
  8. Rate Limiting & DDoS Protection
  9. Secrets Management
  10. SSL/TLS Configuration
  11. Security Scanning & Auditing
  12. Incident Response

1. OVERVIEW

1.1 Security Posture

Defense in Depth Strategy:

┌─────────────────────────────────────────────────────────┐
│ Layer 7: Application Security                          │
│ - Input validation, Output encoding                    │
│ - OWASP Top 10 mitigations, Code review               │
└─────────────────┬───────────────────────────────────────┘
                  │
┌─────────────────▼───────────────────────────────────────┐
│ Layer 6: Authentication & Authorization                │
│ - JWT with rotation, RBAC, MFA                        │
└─────────────────┬───────────────────────────────────────┘
                  │
┌─────────────────▼───────────────────────────────────────┐
│ Layer 5: API Security                                  │
│ - Rate limiting, CORS, API Gateway                    │
└─────────────────┬───────────────────────────────────────┘
                  │
┌─────────────────▼───────────────────────────────────────┐
│ Layer 4: Network Security                             │
│ - Firewall, Security groups, WAF                      │
└─────────────────┬───────────────────────────────────────┘
                  │
┌─────────────────▼───────────────────────────────────────┐
│ Layer 3: Data Security                                │
│ - Encryption at rest/transit, RLS, Backup encryption  │
└─────────────────┬───────────────────────────────────────┘
                  │
┌─────────────────▼───────────────────────────────────────┐
│ Layer 2: Infrastructure Security                      │
│ - OS hardening, Container security, Secrets mgmt      │
└─────────────────┬───────────────────────────────────────┘
                  │
┌─────────────────▼───────────────────────────────────────┐
│ Layer 1: Physical Security                            │
│ - Data center security, Access controls               │
└─────────────────────────────────────────────────────────┘

1.2 Security Objectives

  • Confidentiality: Protect sensitive data (PII, financial data)
  • Integrity: Prevent unauthorized data modification
  • Availability: Ensure system uptime (DDoS protection)
  • Accountability: Audit trail for all sensitive operations
  • Non-Repudiation: Digital signatures for critical transactions

2. OWASP TOP 10 MITIGATIONS

2.1 A01:2021 - Broken Access Control

Threat: Users accessing resources without proper authorization.

Mitigation:

// backend/src/common/guards/rbac.guard.ts
import { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Permission } from '../decorators/permission.decorator';

@Injectable()
export class RBACGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const requiredPermissions = this.reflector.get<string[]>('permissions', context.getHandler());
    if (!requiredPermissions) {
      return true; // No permissions required
    }

    const request = context.switchToHttp().getRequest();
    const user = request.user;

    // Check if user has required permissions
    const hasPermission = requiredPermissions.every((permission) =>
      user.permissions?.includes(permission)
    );

    if (!hasPermission) {
      throw new ForbiddenException('Insufficient permissions');
    }

    // Check tenant isolation
    if (request.body?.tenant_id && request.body.tenant_id !== user.tenant_id) {
      throw new ForbiddenException('Access denied: Cross-tenant access prohibited');
    }

    return true;
  }
}

// Usage in controller
@Controller('sales/orders')
@UseGuards(JwtAuthGuard, RBACGuard)
export class SalesOrdersController {
  @Post()
  @Permissions('sales:orders:create') // Decorator defines required permission
  createOrder(@Body() dto: CreateOrderDto, @CurrentUser() user: User) {
    // Enforce tenant_id from authenticated user (prevent tampering)
    dto.tenant_id = user.tenant_id;
    return this.ordersService.create(dto);
  }
}

RLS (Row-Level Security) in PostgreSQL:

-- Enable RLS on all tenant-specific tables
ALTER TABLE sales.orders ENABLE ROW LEVEL SECURITY;

-- Policy: Users can only see orders from their tenant
CREATE POLICY tenant_isolation_policy ON sales.orders
  FOR ALL
  TO public
  USING (tenant_id = current_setting('app.current_tenant_id')::UUID);

-- Service role can bypass RLS (for admin operations)
CREATE ROLE service_role BYPASSRLS;

2.2 A02:2021 - Cryptographic Failures

Threat: Sensitive data exposed due to weak or missing encryption.

Mitigation:

// Encryption at rest (sensitive fields in database)
import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from 'crypto';

export class EncryptionService {
  private algorithm = 'aes-256-gcm';
  private key: Buffer;

  constructor() {
    // Derive key from secret (stored in environment variable)
    this.key = scryptSync(process.env.ENCRYPTION_SECRET, 'salt', 32);
  }

  encrypt(plaintext: string): string {
    const iv = randomBytes(16);
    const cipher = createCipheriv(this.algorithm, this.key, iv);

    let encrypted = cipher.update(plaintext, 'utf8', 'hex');
    encrypted += cipher.final('hex');

    const authTag = cipher.getAuthTag();

    // Return: iv:authTag:encrypted
    return `${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted}`;
  }

  decrypt(ciphertext: string): string {
    const [ivHex, authTagHex, encrypted] = ciphertext.split(':');

    const iv = Buffer.from(ivHex, 'hex');
    const authTag = Buffer.from(authTagHex, 'hex');
    const decipher = createDecipheriv(this.algorithm, this.key, iv);
    decipher.setAuthTag(authTag);

    let decrypted = decipher.update(encrypted, 'hex', 'utf8');
    decrypted += decipher.final('utf8');

    return decrypted;
  }
}

// Usage: Encrypt SSN, credit card numbers, etc.
@Column({ type: 'text' })
get ssn(): string {
  return this._ssn;
}

set ssn(value: string) {
  this._ssn = this.encryptionService.encrypt(value);
}

SSL/TLS Configuration:

  • TLS 1.2+ only (disable TLS 1.0, 1.1)
  • Strong cipher suites only
  • HSTS header enabled
  • Certificate pinning (mobile apps)

2.3 A03:2021 - Injection

Threat: SQL injection, NoSQL injection, Command injection.

Mitigation:

// Prisma ORM (parameterized queries - safe by default)
const users = await prisma.user.findMany({
  where: {
    email: userInput, // Automatically parameterized
    tenant_id: tenantId,
  },
});

// NEVER do this (vulnerable to SQL injection):
// const query = `SELECT * FROM users WHERE email = '${userInput}'`;

// Command injection prevention
import { exec } from 'child_process';
import { promisify } from 'util';
const execAsync = promisify(exec);

// BAD: Direct command execution with user input
// await execAsync(`convert ${userInput} output.png`); // VULNERABLE!

// GOOD: Whitelist allowed values
const allowedFormats = ['png', 'jpg', 'gif'];
if (!allowedFormats.includes(format)) {
  throw new BadRequestException('Invalid format');
}
await execAsync(`convert input.${format} output.png`);

2.4 A04:2021 - Insecure Design

Mitigation:

  • Security requirements in design phase
  • Threat modeling (STRIDE methodology)
  • Secure by default configurations
  • Principle of least privilege

2.5 A05:2021 - Security Misconfiguration

Mitigation:

// helmet.config.ts - Security headers
import helmet from 'helmet';

export const helmetConfig = helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      styleSrc: ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com'],
      scriptSrc: ["'self'"],
      imgSrc: ["'self'", 'data:', 'https:'],
      fontSrc: ["'self'", 'https://fonts.gstatic.com'],
      connectSrc: ["'self'", 'https://api.erp-generic.com'],
      frameSrc: ["'none'"],
      objectSrc: ["'none'"],
    },
  },
  hsts: {
    maxAge: 31536000, // 1 year
    includeSubDomains: true,
    preload: true,
  },
  frameguard: { action: 'deny' }, // Prevent clickjacking
  noSniff: true, // X-Content-Type-Options
  xssFilter: true, // X-XSS-Protection
  referrerPolicy: { policy: 'strict-origin-when-cross-origin' },
});

// main.ts
app.use(helmetConfig);

Disable Debug Info in Production:

// main.ts
if (process.env.NODE_ENV === 'production') {
  app.enableCors({
    origin: process.env.ALLOWED_ORIGINS.split(','),
    credentials: true,
  });

  // Disable detailed error messages
  app.useGlobalFilters(new ProductionExceptionFilter());
} else {
  app.enableCors({ origin: '*' }); // Dev only
}

2.6 A06:2021 - Vulnerable and Outdated Components

Mitigation:

# Automated dependency scanning
npm audit --audit-level=high

# Snyk vulnerability scanning
snyk test

# Update dependencies regularly
npm outdated
npm update

# Renovate Bot (automated PRs for dependency updates)
# .github/renovate.json
{
  "extends": ["config:base"],
  "schedule": ["every weekend"],
  "labels": ["dependencies"],
  "automerge": false
}

2.7 A07:2021 - Identification and Authentication Failures

Mitigation: See Section 3 (JWT with rotation, MFA, password policies)


2.8 A08:2021 - Software and Data Integrity Failures

Mitigation:

// Verify integrity of uploads
import * as crypto from 'crypto';

function verifyFileIntegrity(file: Buffer, expectedHash: string): boolean {
  const hash = crypto.createHash('sha256').update(file).digest('hex');
  return hash === expectedHash;
}

// Code signing for deployments
// Sign Docker images
docker trust sign erp-generic-backend:v1.0.0

// Verify signature before deployment
docker trust inspect erp-generic-backend:v1.0.0

2.9 A09:2021 - Security Logging and Monitoring Failures

Mitigation:

// Audit logging for sensitive operations
logger.audit('USER_LOGIN', user.id, tenantId, {
  ip: request.ip,
  userAgent: request.headers['user-agent'],
  success: true,
  timestamp: new Date(),
});

logger.audit('DATA_EXPORT', user.id, tenantId, {
  table: 'sales.orders',
  rowCount: 1500,
  format: 'CSV',
});

logger.audit('PERMISSION_CHANGE', adminUser.id, tenantId, {
  targetUser: userId,
  oldRole: 'user',
  newRole: 'admin',
});

2.10 A10:2021 - Server-Side Request Forgery (SSRF)

Mitigation:

// Validate URLs before making requests
import { URL } from 'url';

function isUrlSafe(urlString: string): boolean {
  try {
    const url = new URL(urlString);

    // Whitelist allowed protocols
    if (!['http:', 'https:'].includes(url.protocol)) {
      return false;
    }

    // Blacklist private IP ranges
    const hostname = url.hostname;
    const privateRanges = [
      /^localhost$/,
      /^127\.\d+\.\d+\.\d+$/,
      /^10\.\d+\.\d+\.\d+$/,
      /^192\.168\.\d+\.\d+$/,
      /^172\.(1[6-9]|2\d|3[01])\.\d+\.\d+$/,
    ];

    for (const range of privateRanges) {
      if (range.test(hostname)) {
        return false;
      }
    }

    return true;
  } catch {
    return false;
  }
}

// Usage
if (!isUrlSafe(userProvidedUrl)) {
  throw new BadRequestException('Invalid URL');
}

const response = await axios.get(userProvidedUrl);

3. AUTHENTICATION & AUTHORIZATION

3.1 JWT Configuration

// jwt.config.ts
export const jwtConfig = {
  secret: process.env.JWT_SECRET,
  signOptions: {
    expiresIn: '15m', // Short-lived access tokens
    algorithm: 'HS256',
    issuer: 'erp-generic',
    audience: 'erp-generic-api',
  },
  refreshSecret: process.env.JWT_REFRESH_SECRET,
  refreshSignOptions: {
    expiresIn: '7d', // Long-lived refresh tokens
  },
};

// auth.service.ts
async login(email: string, password: string) {
  const user = await this.validateUser(email, password);

  const payload = {
    sub: user.id,
    email: user.email,
    tenant_id: user.tenant_id,
    roles: user.roles,
    permissions: user.permissions,
  };

  return {
    access_token: this.jwtService.sign(payload),
    refresh_token: this.jwtService.sign(payload, {
      secret: jwtConfig.refreshSecret,
      expiresIn: jwtConfig.refreshSignOptions.expiresIn,
    }),
    expires_in: 900, // 15 minutes
  };
}

3.2 Password Policy

// Strong password requirements
const passwordPolicy = {
  minLength: 12,
  requireUppercase: true,
  requireLowercase: true,
  requireNumbers: true,
  requireSpecialChars: true,
  preventCommonPasswords: true,
  preventPasswordReuse: 5, // Last 5 passwords
  maxAge: 90, // days (force reset after 90 days)
};

// Password hashing with bcrypt
import * as bcrypt from 'bcrypt';

const SALT_ROUNDS = 12;

async hashPassword(password: string): Promise<string> {
  return bcrypt.hash(password, SALT_ROUNDS);
}

async comparePassword(password: string, hash: string): Promise<boolean> {
  return bcrypt.compare(password, hash);
}

3.3 Multi-Factor Authentication (MFA)

// MFA with TOTP (Time-based One-Time Password)
import * as speakeasy from 'speakeasy';
import * as qrcode from 'qrcode';

async enableMFA(userId: string) {
  const secret = speakeasy.generateSecret({
    name: `ERP Generic (${user.email})`,
    issuer: 'ERP Generic',
  });

  // Store secret in database (encrypted)
  await this.prisma.user.update({
    where: { id: userId },
    data: {
      mfa_secret: this.encryptionService.encrypt(secret.base32),
      mfa_enabled: false, // Enable after verification
    },
  });

  // Generate QR code for user to scan
  const qrCodeUrl = await qrcode.toDataURL(secret.otpauth_url);

  return { qrCodeUrl, secret: secret.base32 };
}

async verifyMFA(userId: string, token: string): Promise<boolean> {
  const user = await this.prisma.user.findUnique({ where: { id: userId } });
  const secret = this.encryptionService.decrypt(user.mfa_secret);

  return speakeasy.totp.verify({
    secret,
    encoding: 'base32',
    token,
    window: 1, // Allow 1 time step before/after
  });
}

4. INPUT VALIDATION & SANITIZATION

// Using class-validator and class-transformer
import { IsEmail, IsString, MinLength, MaxLength, Matches, IsUUID } from 'class-validator';
import { Transform } from 'class-transformer';
import * as sanitizeHtml from 'sanitize-html';

export class CreateUserDto {
  @IsEmail()
  @Transform(({ value }) => value.toLowerCase().trim())
  email: string;

  @IsString()
  @MinLength(12)
  @MaxLength(128)
  @Matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/)
  password: string;

  @IsString()
  @MinLength(2)
  @MaxLength(100)
  @Transform(({ value }) => sanitizeHtml(value, { allowedTags: [], allowedAttributes: {} }))
  firstName: string;

  @IsUUID()
  tenant_id: string;
}

// Global validation pipe
app.useGlobalPipes(
  new ValidationPipe({
    whitelist: true, // Strip unknown properties
    forbidNonWhitelisted: true, // Throw error if unknown properties present
    transform: true, // Auto-transform payloads to DTO instances
  })
);

5. SQL INJECTION PREVENTION

Prisma ORM (Safe by Default):

// ✅ SAFE: Parameterized query
const user = await prisma.user.findUnique({
  where: { email: userInput },
});

// ✅ SAFE: Raw query with parameters
const result = await prisma.$queryRaw`
  SELECT * FROM users WHERE email = ${userInput}
`;

// ❌ NEVER DO THIS:
// const result = await prisma.$queryRawUnsafe(
//   `SELECT * FROM users WHERE email = '${userInput}'`
// );

6. XSS & CSRF PROTECTION

6.1 XSS Prevention

// Frontend: Sanitize user input before rendering
import DOMPurify from 'dompurify';

const sanitizedHtml = DOMPurify.sanitize(userInput, {
  ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
  ALLOWED_ATTR: ['href'],
});

// React automatically escapes JSX
<div>{userInput}</div> // Safe

// Dangerous: Bypass escaping
<div dangerouslySetInnerHTML={{ __html: sanitizedHtml }} /> // Use with caution

6.2 CSRF Protection

// CSRF token in NestJS
import * as csurf from 'csurf';

app.use(csurf({ cookie: true }));

// Endpoint to get CSRF token
@Get('csrf-token')
getCsrfToken(@Req() req) {
  return { csrfToken: req.csrfToken() };
}

// Frontend: Include CSRF token in requests
axios.post('/api/orders', orderData, {
  headers: {
    'X-CSRF-Token': csrfToken,
  },
});

7. SECURITY HEADERS

// Comprehensive security headers configuration
app.use(
  helmet({
    contentSecurityPolicy: {
      directives: {
        defaultSrc: ["'self'"],
        scriptSrc: ["'self'", "'unsafe-inline'"], // Remove unsafe-inline in production
        styleSrc: ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com'],
        imgSrc: ["'self'", 'data:', 'https:'],
        fontSrc: ["'self'", 'https://fonts.gstatic.com'],
        connectSrc: ["'self'", 'https://api.erp-generic.com'],
        frameSrc: ["'none'"],
        objectSrc: ["'none'"],
        upgradeInsecureRequests: [],
      },
    },
    hsts: {
      maxAge: 31536000,
      includeSubDomains: true,
      preload: true,
    },
    noSniff: true,
    frameguard: { action: 'deny' },
    xssFilter: true,
    referrerPolicy: { policy: 'strict-origin-when-cross-origin' },
    permissionsPolicy: {
      features: {
        geolocation: ["'none'"],
        microphone: ["'none'"],
        camera: ["'none'"],
        payment: ["'self'"],
      },
    },
  })
);

8. RATE LIMITING & DDOS PROTECTION

// Rate limiting with @nestjs/throttler
import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';

@Module({
  imports: [
    ThrottlerModule.forRoot({
      ttl: 60, // Time window in seconds
      limit: 100, // Max requests per ttl
    }),
  ],
})
export class AppModule {}

// Apply globally
app.useGlobalGuards(new ThrottlerGuard());

// Custom rate limits per endpoint
@Throttle(10, 60) // 10 requests per minute
@Post('login')
async login(@Body() dto: LoginDto) {
  return this.authService.login(dto);
}

// IP-based rate limiting for brute-force protection
@Throttle(5, 300) // 5 failed login attempts per 5 minutes
@Post('login')
async login(@Body() dto: LoginDto, @Ip() ip: string) {
  // Log failed attempts
  const attempts = await this.redis.incr(`login_attempts:${ip}`);
  await this.redis.expire(`login_attempts:${ip}`, 300);

  if (attempts > 5) {
    throw new TooManyRequestsException('Too many login attempts. Try again in 5 minutes.');
  }

  return this.authService.login(dto);
}

9. SECRETS MANAGEMENT

9.1 HashiCorp Vault Integration

// vault.service.ts
import * as vault from 'node-vault';

export class VaultService {
  private client: vault.client;

  constructor() {
    this.client = vault({
      apiVersion: 'v1',
      endpoint: process.env.VAULT_ADDR,
      token: process.env.VAULT_TOKEN,
    });
  }

  async getSecret(path: string): Promise<any> {
    const result = await this.client.read(path);
    return result.data;
  }

  async setSecret(path: string, data: any): Promise<void> {
    await this.client.write(path, { data });
  }
}

// Usage
const dbPassword = await vaultService.getSecret('secret/erp-generic/prod/database');

9.2 Environment Variables Security

# .env file (NEVER commit to Git!)
# Use .env.example as template

DATABASE_URL=postgresql://user:STRONG_PASSWORD@localhost:5432/db
JWT_SECRET=RANDOM_64_CHAR_STRING
ENCRYPTION_SECRET=RANDOM_64_CHAR_STRING

# AWS Secrets Manager (production)
aws secretsmanager create-secret --name erp-generic/prod/jwt-secret --secret-string "RANDOM_64_CHAR_STRING"

10. SSL/TLS CONFIGURATION

10.1 Nginx SSL Configuration

server {
    listen 443 ssl http2;
    server_name erp-generic.com;

    # SSL certificates
    ssl_certificate /etc/nginx/ssl/erp-generic.com.crt;
    ssl_certificate_key /etc/nginx/ssl/erp-generic.com.key;

    # SSL protocols and ciphers
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
    ssl_prefer_server_ciphers on;

    # HSTS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/nginx/ssl/chain.pem;

    # SSL session cache
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    location / {
        proxy_pass http://backend:3000;
        proxy_set_header X-Forwarded-Proto https;
    }
}

# Redirect HTTP to HTTPS
server {
    listen 80;
    server_name erp-generic.com;
    return 301 https://$server_name$request_uri;
}

10.2 Let's Encrypt Automation

# Install Certbot
apt-get install certbot python3-certbot-nginx

# Obtain certificate
certbot --nginx -d erp-generic.com -d www.erp-generic.com

# Auto-renewal (cron)
0 0 1 * * certbot renew --quiet

11. SECURITY SCANNING & AUDITING

11.1 Automated Security Scans

# .github/workflows/security-scan.yml
name: Security Scan

on:
  push:
    branches: [main, develop]
  schedule:
    - cron: '0 0 * * *' # Daily

jobs:
  snyk:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run Snyk to check for vulnerabilities
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high

  owasp-zap:
    runs-on: ubuntu-latest
    steps:
      - name: OWASP ZAP Scan
        uses: zaproxy/action-baseline@v0.7.0
        with:
          target: 'https://staging.erp-generic.com'
          rules_file_name: '.zap/rules.tsv'
          cmd_options: '-a'

11.2 Security Audit Checklist

Monthly Security Audit:

  • Review access logs for anomalies
  • Check failed login attempts
  • Verify MFA enrollment rate (target: 90%)
  • Review user permissions (principle of least privilege)
  • Scan for outdated dependencies (npm audit)
  • Review firewall rules
  • Check SSL certificate expiration
  • Verify backup encryption
  • Test disaster recovery plan
  • Review security alerts from monitoring

12. INCIDENT RESPONSE

12.1 Security Incident Response Plan

Phases:

  1. Detection: Alerts via monitoring, reports from users
  2. Containment: Isolate affected systems, block attacker
  3. Eradication: Remove malware, patch vulnerabilities
  4. Recovery: Restore services, verify integrity
  5. Post-Mortem: Document lessons learned, improve defenses

Contact:


REFERENCES


Documento: SECURITY-HARDENING.md Versión: 1.0 Total Páginas: ~15 Última Actualización: 2025-11-24