Auditoría de seguridad
Esta página publica los resultados de las auditorías de seguridad y de salud del código de a11yequitas.org. Las auditorías se ejecutan en cada lanzamiento.
Última ejecución: 2026-05-25. Próxima ejecución: con el próximo lanzamiento.
Metodología
- vitest: aserciones de seguridad para componentes y rutas. El sitio no inserta HTML peligroso fuera de los scripts en línea aprobados, no carga scripts externos más allá del stub de analítica y no filtra datos entre orígenes.
- Fallow: herramienta de inteligencia de código (Rust). Mide código muerto, duplicación, complejidad ciclomática, tamaño de unidad y acoplamiento. Produce una puntuación de salud de 0 a 100 con calificación con letra. Integrada en la lista de verificación de cada lanzamiento.
- pnpm audit: escaneo de vulnerabilidades en dependencias, ejecutado en cada lanzamiento mediante
pnpm run audit(encadenado con Vitest y Fallow). Los avisos de severidad alta y crítica bloquean el lanzamiento. - Cabeceras HTTP de seguridad: verificadas mediante comprobación automática e inspección manual. Cabeceras objetivo:
Content-Security-Policy,Strict-Transport-Security,X-Content-Type-Options,X-Frame-Options,Referrer-Policy,Permissions-Policy.
Calificaciones por categoría
| Categoría | Fecha | Calificación | Hallazgos |
|---|---|---|---|
| Salud del código (Fallow) | 2026-05-25 | B (78,9) | Puntuación 78,9 / 100 publicada por el último pnpm run audit en el servidor (fallow-cli 2.80.0). Métricas recientes de desarrollo (89 archivos analizados, 41 puntos de entrada, 15.718 líneas, mantenibilidad media 95,8 (buena), complejidad ciclomática media 1,9 / p90 4): 4 incidencias (1 suprimida, 0 supresiones obsoletas); duplicación 21,5 % en 30 archivos / 28 grupos de clones (2.419 líneas); 24 de 306 funciones por encima del umbral de complejidad; archivos muertos 1,1 %, exportaciones muertas 1,2 %; sin dependencias circulares. Hallazgos abiertos: public/static/styles.css reportado como no usado; las exportaciones de tipo AIDoc y SRReport reportadas como no usadas; @siteimprove/alfa-rules reportado como no usado en tests/package.json; /pagefind/pagefind.js reportado como no resuelto (esperado, se genera en tiempo de compilación desde out/pagefind/). La puntuación numérica se actualiza cuando pnpm run audit se ejecuta en el servidor de producción. |
| Escaneo de dependencias (pnpm audit) | 2026-05-25 | A | 0 críticas, 0 altas, 0 moderadas, 0 bajas. El aviso previo de postcss< 8.5.10 (GHSA-qx2v-qp2m-jg93) se resolvió mediante una sobrescritura de pnpm que fija postcss@<8.5.10 → ^8.5.10. Todos los consumidores (next, @tailwindcss/postcss, vite) ahora resuelven a postcss 8.5.15. |
| Cabeceras HTTP de seguridad | 2026-05-25 | B+ | HTTPS se aplica: HTTP en texto plano devuelve 301 a https://a11yequitas.org/. La respuesta en producción incluye Content-Security-Policy, Strict-Transport-Security: max-age=31536000; includeSubDomains; preload, X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN, Referrer-Policy: strict-origin-when-cross-origin y Permissions-Policy: camera=(), microphone=(), geolocation=(). Seguimiento: aumentar HSTS a max-age=63072000, añadir interest-cohort=() y mantener frame-ancestors 'none' como control efectivo contra encuadres. |
| Política CSP | 2026-05-25 | B | Política activa en la respuesta HTTPS en producción: default-src 'none'. La política limita los scripts a código en línea del mismo origen, más Umami y Cloudflare Insights. Permite estilos, imágenes, fuentes, workers y Pagefind del mismo origen. Fija base-uri 'self', form-action 'none' y frame-ancestors 'none'. Siguientes pasos: primero, migrar los scripts en línea a nonces o hashes; luego, eliminar 'unsafe-inline' y 'wasm-unsafe-eval' de script-src. Revisar los requisitos de imágenes de los mosaicos del mapa antes de endurecer img-src. |
| Superficie XSS / inyección | 2026-05-25 | A | Exportación estática: sin renderizado del lado del servidor, sin envíos de formularios en vivo, sin eval, sin Function(), sin document.write y sin .innerHTML = directo en el código de producción. Las coincidencias en pruebas se limitan a src/__tests__/static-html.aaa.test.ts (document.write(html) + w.eval(axeSource)), usadas para cargar HTML estático generado e inyectar axe en el DOM de prueba. 12 usos de dangerouslySetInnerHTML: 11 son literales de cadena para JSON-LD inline / restauración de tema; 1 (los extractos de Pagefind en SearchDialog) inyecta HTML del mismo origen generado en tiempo de compilación; el límite de confianza está anotado en el código. |
| Scripts de terceros | 2026-05-25 | A | Un único script de analítica Umami autoalojado (defer, sin cookies). No hay otro JavaScript de terceros. Sin fuentes ni iconos cargados desde CDN. Todos los enlaces con target="_blank" llevan rel="noopener noreferrer". |
| Privacidad / recopilación de datos | 2026-05-25 | A | Sin cookies. No se recopila información personal identificable. Las preferencias de fuente y tema se guardan únicamente en localStorage (cadenas, sin identificadores). Sin fetch de red en producción (la única solicitud POST en desarrollo dentro de ScreenReaderChecklist está controlada por NODE_ENV !== "production"). |
| Regresión de accesibilidad (Vitest + axe) | 2026-05-25 | A | 70 / 70 páginas HTML estáticas superan WCAG 2.2 AAA con axe-core en happy-dom. Fija los hallazgos de Playwright a nivel de archivo. Se ejecuta mediante pnpm run audit:vitest (23,17 s). |
| Auditoría de accesibilidad (Playwright + axe + Alfa) | 2026-05-25 | A | 352 / 352 pruebas superadas. 32 rutas × axe (6 combinaciones de tema y fuente) + Alfa por ruta + aserciones estructurales (lang, h1, título, enlace de salto). |
Postura estática del sitio
a11yequitas.org es una exportación estática completa de Next.js. El sitio no ejecuta código en el servidor. No usa base de datos. No tiene autenticación. No procesa envíos de formularios. La superficie de ataque se limita a:
- Riesgo de inyección del script de analítica de terceros (un único script, cargado con defer)
- Capa de CDN / hospedaje (Podman + Nginx sobre Rocky Linux)
localStorage: solo almacena cadenas con preferencia de fuente y tema; sin datos sensibles
Hallazgos conocidos
- postcss < 8.5.10 (resuelto 2026-05-24): XSS en la salida de stringify de CSS (GHSA-qx2v-qp2m-jg93). Corregido mediante una sobrescritura de pnpm en
pnpm-workspace.yaml; ahora todos los consumidores resuelven apostcss 8.5.15. - Salud del código en Fallow: unit_size: los componentes de página todavía incluyen entre 200 y 400 líneas de JSX por archivo. El boilerplate del envoltorio ya está extraído en
ProseArticle; queda dividir las secciones inline de cada página (alertas, tablas, listas) en subcomponentes co-ubicados. 24 de 307 funciones siguen por encima del umbral de complejidad. En seguimiento. - Salud del código en Fallow: duplicación 22,6 %: los clones dominantes son texto de contenido repetido: listas de criterios WCAG, marcado de tablas HTML accesibles y secciones de «Interacción con el teclado» compartidas entre varios tutoriales (2.591 líneas duplicadas, 29 grupos de clones en 31 archivos). Resolverlo requiere extraer componentes de contenido compartido (por ejemplo,
<WcagBulletList>) y está pautado para un ciclo de refactor de contenido. - Exportaciones y archivos no usados detectados por Fallow (2026-05-25):
public/static/styles.cssreportado como no usado; las exportaciones de tipoAIDocySRReportreportadas como no usadas;@siteimprove/alfa-rulesreportado como no usado entests/package.json. Triaje encolado para el próximo ciclo de refactor de contenido. - Importación no resuelta en Fallow (esperada):
/pagefind/pagefind.jsaparece como no resuelta porque el índice de Pagefind se genera en tiempo de compilación dentro deout/pagefind/y se carga dinámicamente desde el mismo origen. No es un hallazgo de seguridad; queda documentado aquí para que las revisiones futuras lo ignoren. - Inyección de extractos de Pagefind en SearchDialog (bajo):
dangerouslySetInnerHTMLrenderiza el HTML de extractos del índice de Pagefind. La fuente es el índice del mismo origen, construido a partir del contenido propio del sitio; no se indexa contenido de terceros. El límite de confianza está documentado en el código. Si el índice llegara a ingerir contenido externo, se debe sanear antes de renderizar.
Reportar un problema de seguridad
Para reportar un problema de seguridad, contacte a A11y Equitas a través de a11yequitas.org. Por favor, no abra incidencias públicas sobre vulnerabilidades de seguridad sin resolver.
