Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
openlore-PoC — PoC — path traversal mediante un campo de dominio derivado del LLM sin sanear en OpenLore (GHSA-5j8x-q7q6-58j5, CVE-2026-87001, CVSS 4.7). | Kitploit
Herramientas/GitHubGitHub/squeeze440/openlore-poc
Análisis de VulnerabilidadesAnálisis de CódigoExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónPapers e Investigación
GitHubsqueeze440/openlore-poc

openlore-PoC

PoC — path traversal mediante un campo de dominio derivado del LLM sin sanear en OpenLore (GHSA-5j8x-q7q6-58j5, CVE-2026-87001, CVSS 4.7).

Ver Repositorio
hace 7 díasAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Path Traversal en el escritor de generación de especificaciones de OpenLore a través del campo domain derivado del LLM sin sanitizar

Estado del CVE: solicitado, pendiente de asignación. Este hallazgo se publica como GHSA-5j8x-q7q6-58j5. Tras la asignación del CVE, este repositorio se renombra a CVE-YYYY-NNNNN-openlore-PoC y este banner se reemplaza con el enlace al CVE.

InvestigadorDostxodjayev Abdullox (@squeeze440)
AvisoGHSA-5j8x-q7q6-58j5
CVSS 3.14.7 (Medio)
DebilidadCWE-22, CWE-73

Path Traversal en el escritor de generación de especificaciones de OpenLore a través del campo domain derivado del LLM sin sanitizar

Resumen: Un atacante que controle el contenido de un repositorio analizado por openlore generate puede provocar que el pipeline de generación de especificaciones de OpenSpec escriba Markdown influenciado por el atacante en una ruta arbitraria del sistema de archivos fuera del proyecto objetivo, porque el valor domain devuelto por la llamada de extracción del LLM de la Etapa 3 se usa literalmente para construir la ruta de salida de una especificación sin sanitización de traversal y sin comprobación de confinamiento antes de fs.writeFile.

Producto

OpenLore (clay-good/OpenLore), paquete npm openlore, pipeline de generación de especificaciones (el generador y escritor de formato OpenSpec de openlore generate). No es la ruta determinista de analyze/orient/guardarraíl MCP — esta es la única ruta de código del proyecto que intencionalmente coloca un LLM en el bucle de generación, según el propio README/especificación del proyecto ("un LLM se usa solo donde la generación es inevitable (autoría de especificaciones), nunca en la ruta de recuperación o de guardarraíl").

Versión probada

Commit de Git 1f2de00dfe75530efb256320c374dce36607ee70 (2026-07-31), versión de package.json 2.1.7.

CVSS v3.1 estimado

4.7 (Medio) — CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:N

  • AV:L — el desencadenante es una invocación local de la CLI (openlore generate) contra un directorio en disco, no un servicio de red.
  • AC:H — la explotación requiere que el operador ejecute el comando generate respaldado por LLM (no la ruta de guardarraíl por defecto) con un proveedor configurado, y requiere que la inyección indirecta de prompt del repositorio analizado haga realmente que el modelo emita una cadena de traversal en el campo domain — una condición que el atacante influye pero no controla por completo.
  • UI:R — el operador debe elegir ejecutar la generación de especificaciones contra el repositorio malicioso.
  • I:H / C:N / A:N — el fallo es una primitiva de escritura con contenido parcialmente plantillado por el atacante que aterriza en una ruta elegida por el atacante fuera del proyecto; no se demostró que lea datos confidenciales ni que degrade la disponibilidad de forma fiable, por lo que esas métricas son conservadoramente N.

Detalles

ExtractedService.domain (src/types/pipeline.ts:105) se rellena directamente desde la llamada al LLM de la Etapa 3, a la que se le pasa contenido de archivo sin procesar del repositorio que se está analizando y se le pide que devuelva un array JSON de servicios:

  • src/core/generator/stages/stage3-services.ts:45-52 construye el prompt a partir de fileChunks[i] (texto fuente literal del repositorio analizado) y llama a pipeline.llm.completeJSON<ExtractedService[]>(..., STAGE3_SERVICE_SCHEMA).
  • src/core/generator/schemas.ts:100 — STAGE3_SERVICE_SCHEMA.items.properties.domain es { type: 'string' }: sin pattern, sin enum, sin lista de permitidos. Cualquier cadena que devuelva el modelo es aceptada.
  • src/core/generator/openspec-format-generator.ts:161 — const domainName = service.domain || this.inferDomain(...) usa esa cadena tal cual.
  • src/core/generator/openspec-format-generator.ts:563 — path: \openspec/specs/${domain.name.toLowerCase()}/spec.md`la interpola directamente en la ruta de salida declarada de la especificación. Nótese quenormalizeDomainName() (src/core/generator/openspec-compat.ts:655) existe en el grafo de dependencias del mismo archivo y SÍ se aplica en otros lugares (src/core/generator/openspec-writer.ts:167`, para la comparación de directorios de dominio obsoletos) — pero nunca se llama aquí, en el único lugar donde el valor se convierte realmente en una ruta del sistema de archivos.
  • src/core/generator/openspec-writer.ts:248 — const fullPath = join(this.rootPath, spec.path); usa el simple node:path.join, que resuelve léxicamente los segmentos ../, sin llamar al propio safeJoin() del proyecto (src/utils/path-confinement.ts) por el que toda otra superficie de ruta no confiable en este código base (los manejadores MCP, /api/skeleton y /api/spec-requirements de openlore view) está obligada a pasar según openspec/specs/mcp-security/spec.md.
  • src/core/generator/openspec-writer.ts:277 / :294 luego hacen writeFile(fullPath, spec.content, 'utf-8'), y ensureDir() (openspec-writer.ts:497-499) hace mkdir(dirname(filePath), { recursive: true }) sobre la misma ruta no confinada, creando cualquier directorio intermedio faltante en el camino de salida de la raíz del proyecto.

Efecto neto: un valor domain como ../../../../../../tmp/x sobrevive intacto desde la respuesta JSON del LLM hasta una llamada real a writeFile, aterrizando completamente fuera del proyecto analizado. Este es exactamente el modelo de amenaza de "el contenido del repositorio redirige una escritura fuera de la raíz del proyecto" que el propio openspec/specs/mcp-security/spec.md del proyecto define explícitamente y refuerza en las superficies MCP/serve/view (safeJoin, confinamiento consciente de enlaces simbólicos, puerta de cobertura de parámetros de ruta) — la superficie del generador/escritor simplemente no tiene una puerta equivalente.

Prueba de concepto

No se realizó ninguna llamada real al LLM (el cumplimiento del modelo con una instrucción inyectada es probabilístico y no es la parte interesante de este fallo); en su lugar, la PoC llama al OpenSpecFormatGenerator y OpenSpecWriter reales y sin modificar de OpenLore con un PipelineResult cuyo único campo ExtractedService.domain contiene exactamente la forma de cadena que STAGE3_SERVICE_SCHEMA permite que un LLM devuelva hoy, y exactamente lo que un comentario en un archivo fuente que instruya "establece domain a ../../../.../tmp/x" podría provocar en la Etapa 3 (que pasa el contenido sin procesar del archivo al modelo).

Script: ~/engagements/openlore/source/poc-domain-traversal.ts (raíz del repositorio del clon probado), ejecutado contra un proyecto de pruebas en ~/engagements/openlore/evidence/victim-project:

root@kitploit:~
cd ~/engagements/openlore/source
npx tsx poc-domain-traversal.ts

Resultado: OpenSpecFormatGenerator.generateSpecs() (sin modificar) emite una especificación de dominio con path: "openspec/specs/../../../../../../../../../../../../../../../../../../../../tmp/openlore_traversal_proof/spec.md", y OpenSpecWriter.writeSpecs() (sin modificar) la escribe — aterrizando en /tmp/openlore_traversal_proof/spec.md, completamente fuera de la raíz de victim-project, mientras que victim-project/openspec/specs/ solo contiene los dos directorios legítimos overview/architecture.

Capturas de pantalla (capturas genuinas de Xvfb+fluxbox+xterm, scrot -w <window id>):

  • ../evidence/poc-generator-write.png — la ejecución de la PoC: el spec.path sin procesar del generador conteniendo el traversal, la línea de registro del escritor Wrote openspec/specs/../../.../tmp/openlore_traversal_proof/spec.md, y la propia confirmación del script de que /tmp/openlore_traversal_proof/spec.md existe con contenido influenciado por el atacante.
  • ../evidence/poc-outside-fs-proof.png — confirmación independiente: ls de victim-project/openspec/specs/ muestra solo architecture/overview (sin rastro del dominio malicioso dentro del proyecto), mientras que ls -la /tmp/openlore_traversal_proof/ muestra el spec.md escapado situado directamente bajo /tmp.

Impacto

Un atacante que pueda conseguir que un objetivo ejecute openlore generate (generación de especificaciones respaldada por LLM) contra un repositorio que él haya creado — un escenario plausible para una herramienta de CLI cuyo propósito explícito es apuntarse a bases de código de terceros/no confiables — puede escribir un archivo con contenido influenciado por el atacante en cualquier ruta en la que el usuario del sistema operativo del operador pueda escribir, limitado solo por cuántos segmentos ../ se necesiten para escapar y por los permisos del sistema de archivos. No se confirma que la escritura sea directamente ejecutable, pero una ruta de proyecto suficientemente superficial podría permitir que el traversal alcance ubicaciones que son ejecutadas o cargadas automáticamente por otras herramientas en la misma cuenta (archivos rc del shell, directorios de usuario de cron, configuración del editor/IDE), lo cual no se probó y no se afirma aquí.

Debilidades

  • CWE-22: Limitación incorrecta de un nombre de ruta a un directorio restringido ('Path Traversal')
  • CWE-73: Control externo del nombre de archivo o ruta
  • CWE-20: Validación de entrada incorrecta (causa raíz — la salida JSON del LLM se confía como si fuera generada internamente)

Remediación

  1. Aplicar el normalizeDomainName() existente (o una regex de lista de permitidos equivalente, p. ej. ^[a-z][a-z0-9-]{0,63}$) a domain.name / service.domain en el punto en que se aceptan por primera vez desde la respuesta del LLM (groupByDomain() en openspec-format-generator.ts), no solo en el sitio posterior de comparación de directorios obsoletos.
  2. Encaminar el cálculo de fullPath de OpenSpecWriter.writeSpec() a través del propio safeJoin() del proyecto (src/utils/path-confinement.ts) en lugar del simple node:path.join, igualando el confinamiento ya exigido a toda otra superficie de ruta no confiable en este código base.
  3. Añadir una restricción pattern a STAGE3_SERVICE_SCHEMA.domain (y a cualquier otro campo del esquema que luego se use para construir una ruta del sistema de archivos) para que los proveedores que aplican esquemas de salida estructurada rechacen de plano los valores no conformes.
  4. Añadir una prueba de regresión — en el espíritu de la "Path-Parameter Coverage Gate" de MCP existente — que afirme que un GeneratedSpec.path que contenga .. o que resuelva fuera de rootPath es rechazado antes de que OpenSpecWriter toque el sistema de archivos.

Crédito

Dostxodjayev Abdullox

Canal de reporte

El reporte privado de vulnerabilidades de GitHub está habilitado para este repositorio: https://github.com/clay-good/OpenLore/security/advisories/new (flujo GHSA estándar). Confirmado mediante gh api repos/clay-good/OpenLore/security-advisories devolviendo [] (sin avisos previos) antes de esta auditoría.

Descargar herramienta