Postura de seguridad · OWASP ASVS v4

Nuestra postura de seguridad.

Esta es la auto-evaluación de AlgizSec contra el estándar OWASP ASVS (Application Security Verification Standard). Cada control apunta a evidencia técnica verificable en nuestro código. Sin maquillaje.

8
Verificado en código
5
Parcial: la ficha dice qué falta
1
Vía proveedor certificado
0
En roadmap
Matriz de controles ASVS · 14 áreas evaluadas
V1
Arquitectura y Modelado de Amenazas
Verificado en código

Separación de datos por organización aplicada a nivel de base de datos.

Row Level Security (RLS) en todas las tablas de cliente: aunque dos empresas compartan infraestructura, jamás ven datos de la otra. La separación la hace Postgres, no el código.

Fuente: supabase/migrations/20260606_rls_all_tables.sql
V2
Autenticación
Verificado en código

JWT firmado, validado en los endpoints que actúan por un usuario.

Supabase Auth con PKCE. Los endpoints que actúan por un usuario validan el token con auth.getUser(token) antes de procesar y responden 401 si no sirve. Son públicos por diseño el chat comercial, la salud del sistema y los webhooks, que validan su propia firma.

Fuente: api/email.js, api/scan/virustotal.js, api/whatsapp/webhook.js
V3
Gestión de Sesiones
Verificado en código

Rotación automática de tokens, sesión persistente segura.

autoRefreshToken: true + flowType: pkce. Supabase Auth rota el refresh token en cada renovación. La sesión se guarda en el localStorage del navegador.

Fuente: src/supabase.ts
V4
Control de Acceso
Verificado en código

Roles a nivel de base de datos. Defensa en profundidad.

Rol admin codificado en app_metadata del JWT y validado por políticas RLS de Postgres. Aunque la aplicación falle, RLS rechaza el acceso.

Fuente: supabase/migrations/20260611_sales_pipeline.sql
V5
Validación de Entradas
Parcial: la ficha dice qué falta

Límite de tamaño y detección de inyección en los endpoints de IA.

El chat comercial limita el cuerpo a 16 KB, quita caracteres de control y tiene un detector heurístico de prompt injection que responde sin gastar cuota de IA; el chat de la app limita a 100 KB. Los demás endpoints validan sus campos uno a uno, sin un límite de tamaño común.

Fuente: api/sales/chat.ts, api/chat/gemini.js
V6
Cifrado de Datos en Reposo
Vía proveedor certificado

Cifrado at-rest vía infraestructura cloud certificada.

Datos persistidos en Supabase, que cifra en reposo con AES-256 por defecto, sobre infraestructura de AWS. Los archivos, igual. La aplicación no agrega un cifrado propio.

Fuente: Supabase Postgres + Storage
V7
Manejo de Errores y Logging
Verificado en código

Bitácora de auditoría de solo escritura. Trazabilidad forense.

Cada acción se firma con HMAC-SHA256 (id|user|ip|metadata|timestamp) al insertarse. Triggers de Postgres rechazan UPDATE, DELETE y TRUNCATE sobre audit_logs: comprobado intentando modificarla con permisos totales de base de datos. La clave de firma la custodia AlgizSec, así que la bitácora es inalterable para cualquier usuario de la plataforma; el anclaje ante un tercero independiente está en desarrollo.

Fuente: supabase/migrations/20260410_audit_integrity.sql
V8
Protección de Datos Sensibles
Parcial: la ficha dice qué falta

Datos sensibles nunca llegan al cliente sin autorización.

Service role key solo en el backend. Anon key con permisos limitados por RLS. La mayoría de los endpoints responde un mensaje genérico ante un error interno; algunos todavía devuelven el mensaje del proveedor, y se están cerrando.

Fuente: api/cadena.js, api/inbound-email.js, api/whatsapp/verify.js
V9
Comunicaciones (TLS)
Parcial: la ficha dice qué falta

HTTPS obligatorio con HSTS preload. CSP estricto en la aplicación y en las páginas de seguridad y cumplimiento; en la portada y las páginas legales, no.

Strict-Transport-Security con preload, includeSubDomains y max-age de 2 años. En /app, /auditoria, /transparencia, /seguridad, /security, /cumplimiento y /ley-21663 —incluida ésta— el script-src solo admite el propio dominio y Google. En la portada, /privacidad y /terminos-y-condiciones admite unsafe-inline y unsafe-eval. frame-ancestors self, X-Frame-Options SAMEORIGIN y Referrer-Policy strict-origin-when-cross-origin. La versión de TLS la negocia Vercel.

Fuente: vercel.json
V10
Código Malicioso (XSS, Inyección)
Verificado en código

DOMPurify sobre el HTML que se pinta y CSP estricto en la aplicación.

DOMPurify sobre todo HTML que se pinta con dangerouslySetInnerHTML, y el CSP estricto de /app. Sin SQL concatenado: las consultas van por el SDK de Supabase o por funciones de Postgres con parámetros.

Fuente: src/modules/Gemelo/MarkdownPreview.tsx, src/components/WordEditor.tsx, vercel.json
V11
Lógica de Negocio (Rate Limiting)
Parcial: la ficha dice qué falta

Defensa contra abuso, picos de costo y proveedores caídos.

Límite de peticiones con contador en Postgres, compartido entre instancias, en los endpoints que actúan por un usuario (17 de 26); no en los webhooks, los cron ni la salud del sistema. Cortacircuitos para Twilio y Resend: 3 fallos en 60 s abren el circuito, y los envíos quedan en cola en Inngest. El estado del circuito vive en cada instancia, no es compartido.

Fuente: api/_lib/rateLimit.js + api/_lib/circuitBreaker.js
V12
Manejo de Archivos
Verificado en código

Upload directo a bucket cifrado. URLs firmadas con expiración.

Archivos suben directo del navegador a Supabase Storage (no pasan por servidor de aplicación). Bucket protegido con RLS por user_id. Visualización vía signed URL con expiración de 1 hora.

Fuente: src/hooks/useVaultFiles.ts + src/components/PDFViewer.tsx
V13
Seguridad de API
Parcial: la ficha dice qué falta

Límite de peticiones y token en los endpoints que actúan por un usuario.

El patrón —límite de peticiones, token Bearer, validación de campos y respuesta sin detalles internos— lo siguen los endpoints que actúan por un usuario, no todos: la salud del sistema es pública y los webhooks validan su propia firma en vez de un token.

Fuente: api/scan/virustotal.js, api/email.js, api/cadena.js
V14
Configuración Segura
Verificado en código

Secretos fuera del cliente. Headers de seguridad por defecto.

API keys solo en variables de entorno del backend. Al cliente llegan solo valores públicos por diseño: la anon key de Supabase (limitada por RLS), los identificadores de Google y el DSN de Sentry. Un pre-commit bloquea .env, .pem e id_rsa/id_ecdsa en el repositorio.

Fuente: .githooks/pre-commit + .vercelignore

Lo que esta página es — y lo que no

  • Es una declaración honesta y verificable de cómo está implementada hoy nuestra seguridad. Cada fila apunta a un archivo del repositorio que un auditor puede revisar.
  • No es una certificación de tercero (ISO 27001, SOC 2). Esas son auditorías formales en el roadmap; las publicaremos aquí cuando estén firmadas.
  • No es garantía absoluta. Ninguna lo es. Es nuestra mejor implementación al día de hoy, abierta a escrutinio.
Divulgación responsable

¿Encontró algo? Cuéntenos primero.

Si descubre una vulnerabilidad en AlgizSec, repórtela de forma privada a security@algizsec.com. Respondemos en menos de 72 horas y reconocemos públicamente a quienes reportan en buena fe. No tomamos acciones legales contra investigación responsable de seguridad.

PGP / consulta de coordinación disponible bajo solicitud.
AlgizSec · Última revisión: 2026-11-13← Volver al inicio