
Tencent BrowserSkill solo comprobaba que el ID de una extensión pareciera real — cualquier extensión podía alimentar al agente con páginas falsificadas
- OrcaNUEVOOrcaCyber: Qwen3.8 Flash Next Abliterated2026-10-26$0.80 / $1.60 por 1M de tokens · 98 tok/s
- OrcaNUEVOOrcaCyber: MiMo V2.6 Flash Abliterated2026-10-26$0.80 / $1.60 por 1M de tokens · 115 tok/s
- MoonshotNUEVOMoonshotAI: Kimi K3.1 Pro2026-10-2455Inteligencia
- OrcaNUEVOOrcaCyber: DeepSeek V4.1 Flash Abliterated2026-10-23$0.80 / $1.60 por 1M de tokens · 138 tok/s
- minimaxNUEVOMiniMax: M3.1 Flash2026-10-1943Inteligencia
- OrcaNUEVOOrca: OrcaCyber Ultra 1.02026-10-17$5.00 / $10.00 por 1M de tokens · 43 tok/s
- deepseekNUEVODeepSeek: DeepSeek V4.1 Flash 10172026-10-1745Inteligencia
- DeepSeekNUEVODeepSeek: DeepSeek V4.1 Flash2026-10-1740Inteligencia
- OrcaOrca: OrcaCyber Zero 1.52026-10-10$3.00 / $7.50 por 1M de tokens · 111 tok/s
- openaiOpenAI: GPT-6.1 Sol2026-09-2952Inteligencia
- anthropicAnthropic: Claude Sonnet 5.52026-09-2856Inteligencia
- typesafeTypeSafe: Jev 1.132026-09-24$0.04 / $0.00 por 1M de tokens · 698 tok/s
- OpenAIOpenAI: GPT-6 Luna2026-09-2238Inteligencia
- OpenAIOpenAI: GPT-6 Sol2026-09-2248Inteligencia
- AnthropicAnthropic: Claude Opus 5.52026-09-2258Inteligencia
- xiaomiXiaomi: MiMo-V2.6-Flash2026-09-21$0.14 / $0.28 por 1M de tokens · 45 tok/s
- xiaomiXiaomi: MiMo-V2.6-Pro2026-09-21$0.43 / $0.87 por 1M de tokens · 50 tok/s
- xAIGrok 4.72026-09-2146Inteligencia
- OrcaOrca: OrcaCyber Zero 1.02026-09-17$3.00 / $7.50 por 1M de tokens · 231 tok/s
- OrcaOrca: OrcaVerify Text 1.02026-09-16$2.00 / $0.00 por 1M de tokens · 3445 tok/s
El 17 de septiembre de 2026, un usuario de GitHub que publicaba como carfeii abrió el issue #273 contra el proyecto de código abierto BrowserSkill de Tencent con una afirmación concreta: el demonio local que conecta la extensión del navegador con un agente de IA no comprobaba qué extensión se conectaba, solo que la conexión pareciera una extensión. Tres días después, el 20 de septiembre, VulnCheck publicó el hallazgo como CVE-2026-94111, describiendo un demonio que «acepta cualquier origen de chrome-extension con 32 caracteres en el rango a-p», lo clasifica como CWE-346 (error de validación de origen) y acredita a George Chen. El aviso lo puntúa con CVSS 4.0 6.9, medio, con impacto en integridad calificado como alto y confidencialidad y disponibilidad bajos. Nada en el registro sugiere que la falla se haya utilizado: el archivo no registra explotación y califica la entrada con confianza A, con real_harm en false. Este es un registro en el archivo de incidentes de IA, donde cada entrada incluye sus propias fuentes, gravedad, grado de confianza y indicador de disputa.
Una verificación de formato que nunca comprobó la identidad
El código en el centro del registro es pequeño. En crates/bsk-cli/src/daemon/ws.rs, la función origin_allowed() toma el encabezado Origin del handshake de WebSocket, elimina la cadena chrome-extension:// y devuelve true si lo que queda tiene exactamente 32 caracteres de longitud y cada carácter está entre a y p. Esa es la prueba completa. Se ejecuta una vez, dentro del callback de actualización HTTP, y un fallo devuelve un 403 cuyo mensaje dice "Origin not in chrome-extension allow-list"; aunque, tal como se publicó, no había ninguna lista en la que estar.
El patrón no es arbitrario. Los ID de extensión de Manifest V3 de Chrome son 32 caracteres tomados exactamente de esas dieciséis letras, por lo que la comprobación reconoce correctamente la forma de un origen de extensión real. El defecto es que todas las extensiones tienen esa forma. La comprobación pregunta si quien llama parece una extensión de navegador, nunca si es la extensión de navegador de este proyecto, y el identificador con el que debería haberse comparado ya era público: el README del proyecto enlaza la ficha de Chrome Web Store, cuyo ID es hhcmgoofomhgciiibhipgmgkgnoenaoi, y el ID de Edge Add-ons junto a ella. Ninguna de las dos cadenas aparece en ningún lugar del control.
El daemon escucha en un puerto local fijo, 52800, declarado como DEFAULT_WS_PORT en la CLI y usado sin variación en la ruta de conexión local. El puerto está documentado, es constante y es accesible por cualquier cosa que ya se esté ejecutando en el perfil del navegador del usuario. La ubicación es la razón por la que el vector del aviso comienza con AV:L — el atacante necesita un punto de apoyo en la máquina, y PR:L registra que uno de bajos privilegios es suficiente. Una extensión instalada en el mismo perfil es exactamente ese tipo de punto de apoyo.
Cuánto vale el escaño y qué parte de ello está consolidada
La frase de impacto del aviso es amplia: un atacante que registre una extensión maliciosa como cliente de navegador puede «interceptar y manipular el contenido de la página, el DOM y las capturas de pantalla devueltas al agente de IA». Esa es la descripción que comparten la CVE, el registro de aviso de GitHub GHSA-x6f2-qp26-2xrh y el archivo, y explica la calificación alta de integridad del CVSS. También es un resumen escrito por la parte que asignó la CVE, no un informe de un ataque demostrado.
Un informe más cuidadoso llegó esa misma semana, en el propio hilo de la incidencia. El 20 de septiembre, un comentarista que publicaba como bb6894 informó de que había vuelto a comprobar el código con main en el commit fa953dc6 (18 de septiembre) y trazó qué puede alcanzar realmente un cliente externo después del handshake. La mayoría de los métodos de herramienta entrantes, según el comentario, devuelven UnknownMethod a un par de WebSocket; las solicitudes de auditoría se limitan a los propios registros del cliente; y las acciones entre sesiones, como window_closed, user_interrupt y update_interaction, están protegidas frente a sesiones propiedad de otro navegador. Lo que sobrevive a ese filtro es más limitado y, para un agente, podría decirse que peor que la interceptación: una extensión externa puede ocupar una ranura de navegador con un instance_id elegido por el atacante y, si es el único navegador registrado —un arranque en frío o un reinicio del daemon—, recibe las solicitudes de herramienta del agente y las responde con contenido de página, DOM o capturas de pantalla fabricados. El comentarista lo llama «falsificación de resultados hacia el agente» y «un canal hacia la percepción del agente». Un segundo efecto es una denegación de servicio: si también hay un navegador genuino en línea y no hay selector, el arranque de la sesión puede fallar con MultipleBrowsersOnline.
Ninguna de las dos versiones se ha demostrado en público. El reportero describió una prueba de concepto como «disponible previa solicitud»; nadie ha publicado ninguna, y no hay explotación registrada. Así que la diferencia entre las dos versiones es una diferencia entre dos lecturas del mismo archivo fuente, no entre una teoría y un exploit funcional — y el artículo informa de ambas en lugar de elegir. Lo que puede afirmarse sin reservas es que nunca hubo una segunda verificación de identidad después del handshake, de modo que todo lo que la puerta admitió permaneció admitido durante toda la vida de la conexión.
El código ya sabía
El documento más incómodo de este registro no es el aviso. Es el comentario directamente encima de la función, incluido en la versión etiquetada a la que apunta el aviso. Marca la brecha como TODO(M10/M12), nombra la lista de permitidos que pretende construir —un DaemonConfig::allowed_extension_ids conjunto poblado desde un archivo de configuración o un flujo de emparejamiento— y luego expone el motivo por el que se aplazó: «una brecha de defensa en profundidad aceptable por ahora porque el emparejamiento se produce a través de la ventana emergente, pero una extensión instalada por carga lateral en la misma máquina actualmente pasa el filtro».
Leído sin rodeos, los mantenedores sabían qué llamador dejaba pasar la puerta, dejaron constancia de que lo sabían y publicaron. Eso no hace que la exposición sea mayor de lo que indica el aviso; la hace menos sorprendente y traslada la pregunta de «cómo pasó esto la revisión» a «qué habría hecho urgente la corrección aplazada». La suposición de diseño mitigadora es real y también está documentada: la conexión local es opcional (opt-in). Según el README, el usuario instala la extensión, abre su ventana emergente y habilita la conexión local, y el daemon tiene que estar en ejecución para que algo de esto sea alcanzable. Un perfil con la extensión instalada pero el interruptor desactivado, o sin ningún daemon bsk en ejecución, no es un objetivo a la escucha.
Cinco semanas después, el portón sigue igual

El rango afectado del registro es "hasta 0.3.0", y ese es el rango que asignó el CNA. No es el final de la historia en el repositorio. La versión 0.3.0 de la CLI se etiquetó el 17 de septiembre a las 02:22 UTC; el issue se presentó ese mismo día a las 15:14 UTC, unas trece horas después. Desde entonces se han publicado tres versiones más de la CLI — 0.3.1 el 23 de septiembre, 0.3.2 el 30 de septiembre, y 0.3.3 el 15 de octubre —y la función origin_allowed() en cada una de esas etiquetas es la misma comprobación descrita arriba, con el TODO todavía justo encima. La rama principal también la incluye a fecha de 27 de octubre.
Existe una solución, pero solo como propuesta. El 28 de septiembre, un colaborador que publica como dangzitou abrió la solicitud de extracción #363 desde una bifurcación personal, titulada "fix(daemon): fijar la puerta de origen de WS a los propios ID de extensión de BrowserSkill." Sustituye la prueba de forma por una comparación con los dos ID de la tienda y añade BSK_ALLOWED_EXTENSION_IDS como una vía de admisión explícita para compilaciones de desarrollo y de carga lateral, cuyos ID sin empaquetar se derivan de la ruta de instalación. El cuerpo de la solicitud de extracción afirma que cierra tanto la vía de falsificación como la denegación de servicio MultipleBrowsersOnline. A fecha de 27 de octubre, sigue abierta y sin fusionar, y la incidencia sigue abierta sin ninguna declaración del proveedor adjunta.
La consecuencia práctica es que no hay ninguna versión a la que actualizar que contenga la corrección. Cualquiera que aconseje «actualizar más allá de 0.3.0» está aconsejando un paso que aún no existe: las versiones posteriores son más recientes, no están corregidas. El intervalo del registro debe leerse como el intervalo que la CNA evaluó el 20 de septiembre, no como una declaración de que 0.3.1 y posteriores están limpios.
Qué está establecido y qué no
• Confirmado: el código fuente publicado en la etiqueta cli-v0.3.0 contiene una validación de origen que acepta cualquier origen chrome-extension de 32 caracteres (a–p). El reportero, el CNA y el propio archivo coinciden, y el código es público.
• Establecido: la puerta se ejecutó una vez, en la actualización de WebSocket, sin ninguna comprobación de identidad posterior, en un puerto local fijo de 52800.
• Establecido: el propio comentario del código fuente del proyecto reconocía que una extensión instalada mediante carga lateral sería aceptada, y aplazaba la lista de permitidos.
• Establecido: CVSS 4.0 6.9 y CVSS 3.1 6.6 son ambas puntuaciones de VulnCheck, registradas por NVD como secundarias. El estado propio de NVD para la entrada es Diferido, lo que significa que ha publicado los datos del CNA sin añadir un análisis elaborado por NVD.
• Establecido: La evaluación SSVC de CISA, fechada el 21 de septiembre, registra la explotación como ninguna, lo automatizable como no y el impacto técnico como parcial. El EPSS de FIRST sitúa la probabilidad de explotación en los próximos treinta días en 0,00135, el percentil 2,9, a fecha de 26 de octubre.
• No establecido: ningún uso real. Sin explotación, sin prueba de concepto publicada, sin recuento de instalaciones afectadas. Las métricas del repositorio del proyecto no son un recuento de instalaciones, y nadie ha publicado ninguna.
• No establecido: qué relato del impacto prevalece. El "interceptar y manipular" del CNA y la "falsificación de resultados más denegación de servicio" del hilo describen techos distintos, y ninguno se ha demostrado fuera de la lectura del código.
• No se ha establecido: que la falla termine en 0.3.0. La cadena de versión es la evaluación de la CNA; el código no ha cambiado en las tres versiones posteriores, y ninguna declaración del proveedor las exime.
• Contradicho, sin resolver: un agregador, DevGuard, muestra una señal de «se han detectado intentos de explotación» para esta CVE sin nombrar una fuente, un IOC ni un proveedor de telemetría. Eso choca con la evaluación registrada de la CISA de que no hay explotación y con la ausencia de cualquier informe público; el archivo tampoco registra explotación. Considera la señal del agregador como no fundamentada en lugar de como un segundo punto de datos.

Por qué el transporte es el objetivo interesante
Las orientaciones sobre inyección de prompts trazan el mismo límite: tratan el texto de la página recuperada como no confiable y el mecanismo que lo entrega como confiable. Se supone que una herramienta que lee una página web está leyendo la página; la cuestión es qué dice la página. Este registro invierte eso. Lo que el agente recibe como contenido de página, DOM y capturas de pantalla es lo que el cliente al otro extremo de un socket local elija enviar, y la única barrera de ese socket planteaba una pregunta que todo candidato podía responder correctamente. Si el cliente es ajeno, «verificar lo que dice la página» no tiene nada contra lo que verificar.
Es también la razón por la que la gravedad se sitúa donde se sitúa y no en un nivel más alto. El ataque es local, presupone una extensión ya instalada en el perfil u otro código local, y requiere que el daemon esté en ejecución con la conexión local habilitada. Esas condiciones son habituales para los usuarios previstos de la herramienta e inusuales para todos los demás. La gravedad media del archivo y la ausencia de daño registrada son coherentes con esa forma: una ampliación real de la confianza justo en el límite que el diseño debía vigilar, sin pruebas de que nadie lo haya cruzado.
El estrecho consejo práctico que sigue no es una mitigación que alguien haya publicado, sino solo el límite que el código deja en pie. Dado que la admisión se decide una sola vez en el handshake sobre un puerto publicado, la superficie alcanzable la determina qué extensiones están instaladas en el perfil que ejecuta el daemon y si ese daemon y la conexión local de la extensión están activados en ese momento. Hasta que se publique una lista de permitidos de ID de extensión, esos dos hechos constituyen todo el control.

CVE-2026-94111 envejecerá de una de dos maneras. O se fusiona la pull request y el registro se convierte en una entrada breve sobre una laguna conocida que tardó en resolverse, o la misma comprobación de forma sigue en el árbol dentro de un año y la entrada se cita como un ejemplo temprano de la clase a la que pertenece: no una página que lleva una instrucción hostil, sino la tubería que decide qué página está leyendo el agente.
