Xterm.js: Soporta hipervínculos ansi escapes

Creado en 28 nov. 2017  ·  29Comentarios  ·  Fuente: xtermjs/xterm.js

Los emuladores de terminal están comenzando a admitir hipervínculos . Si bien muchos terminales han detectado URL durante mucho tiempo y las han vinculado, lo que le permite hacer Comando + Clic o Control + Clic para abrir un navegador, se vio obligado a imprimir las URL largas y antiestéticas en la pantalla. A partir de la primavera de 2017, algunos terminales comenzaron a admitir enlaces tipo HTML, donde el texto del enlace y el destino se podían especificar por separado.

Ejemplo de iTerm2 3.1:
screen shot 2017-11-28 at 12 08 20

areapi arelinks help wanted typenhancement

Comentario más útil

iTerm2 muestra la URL así:

screen shot 2017-11-28 at 14 50 20

Esto también es similar a cómo Chrome muestra la URL cuando colocas el cursor sobre los enlaces.

Todos 29 comentarios

¡Buena idea, PR bienvenido!

Podría convertirse en un estándar y facilitar el análisis.
Problema relacionado: https://github.com/xtermjs/xterm.js/issues/583

El mayor beneficio es que podemos vincular texto sin tener que enviar spam al terminal con una URL larga. Por ejemplo, se puede vincular a la documentación en mensajes de error sin que sea muy detallado.

Esto debe implementarse con cuidado, debe poder pasar el enlace para ver a dónde conduce, de lo contrario, podría vincular a los usuarios sin saberlo a sitios maliciosos. Este ya es un gran problema en el phishing por correo electrónico.

Por ejemplo, podría crear un enlace que tuviera el título "login.facebook.com" pero en realidad vincularlo a login.faceboook.com, con una página que se ve exactamente igual, pero guardando la contraseña de los usuarios al iniciar sesión.

iTerm2 muestra la URL así:

screen shot 2017-11-28 at 14 50 20

Esto también es similar a cómo Chrome muestra la URL cuando colocas el cursor sobre los enlaces.

Si / cuando esto se implemente, envíe un problema o RP a supports-hyperlinks , que tiene la intención de detectar soporte para esta capacidad.

@jamestalmage, esto probablemente deba dejarse en manos de los integradores xterm.js, ahora mismo el entorno es propiedad de los emuladores de terminal que usan xterm.js. Por ejemplo, Hyper y VS Code se configuran individualmente TERM_PROGRAM .

@Tyriar : en ese caso, tal vez solo incluya una referencia a supports-hyperlinks en la confirmación que aterriza esto, y en las notas de la versión cuando se amplíe. No estoy seguro de si hay supports-hyperlinks equivalentes para otros idiomas, pero si es así, probablemente valga la pena mencionarlos también.

Tengo una implementación de prueba de concepto:

links.txt

Existe un problema fundamental en el que estos enlaces no se almacenan en el búfer de forma real, por lo que desaparecen si se cambia el tamaño de la ventana. En cambio, la información del enlace se almacena en el MouseZoneManager que se borra con _mouseZoneManager.clearAll .

Creo que una solución real tiene que esperar hasta que se complete la reimplementación del búfer. Necesitamos un mecanismo para anotar celdas y / o rangos de celdas, que sea estable al cambiar el tamaño.

(O tal vez me estoy perdiendo algo, siendo nuevo en esta base de código).

Creo que una solución real tiene que esperar hasta que se complete la reimplementación del búfer. Necesitamos un mecanismo para anotar celdas y / o rangos de celdas, que sea estable al cambiar el tamaño.

@PerBothner, sí, probablemente tengas razón. Otra cosa en la que debemos pensar antes de que esto se pueda enviar es cómo se expone la URL subyacente desde xterm.js para que los integradores puedan mostrarla en la interfaz de usuario. Probablemente también querríamos desactivarlo de forma predeterminada por razones de seguridad (ya que la URL no aparecería de forma predeterminada).

Actualicé mi parche y lo envié a una rama: https://github.com/PerBothner/xterm.js/tree/hyperlinks

Sin embargo, no está listo para una solicitud de extracción; varios problemas mencionados anteriormente no se han abordado.

Propuesta para que la API use esto:

export class Terminal {
    /**
     * Adds a handler for the ANSI hyperlink escape `\x1b]8;;url\alabel\x1b]8;;`, you should use
     * this API to display the full URL to the user. Note that ANSI hyperlinks will only work if
     * there is a handler for security reasons.
     * <strong i="6">@param</strong> onHover The callback that fires when the mouse enters a link's zone.
     * <strong i="7">@param</strong> onLeave The callback that fires when the mouse leaves a link's zone.
     * <strong i="8">@return</strong> An IDisposable which can be used to disable the handler.
     */
    addAnsiHyperlinkHandler(onHover: (event: MouseEvent, url: string) => void, onLeave: () => void): IDisposable;
}

@mofux @jerch ¿ comentarios sobre la forma de la API? No puedo encontrar ese hilo hablando de la forma de estos, pero tal vez debería ser set lugar de add ya que solo tiene sentido tener 1.

También podría ser mejor usar algo como ILinkHoverEvent :

interface ILinkHoverEvent {
  // Maybe the cell the mouse is under is also needed?
  x1: number;
  y1: number;
  x2: number;
  y2: number;
  url: string;
}

export class Terminal {
    addAnsiHyperlinkHandler(onHover: (event: ILinkHoverEvent) => void, onLeave: () => void): IDisposable;
}

Otra alternativa:

interface ILinkHoverEvent {
  linkStart: Cell;
  linkEnd: Cell;
  mousePosition: Cell;
  url: string
}

@Tyriar En mi opinión , no tiene mucho sentido crear un controlador separado para esto. El probable consumidor de esta API sería nuestro renderizador que muestra la URL en una información sobre herramientas si colocamos el cursor sobre el texto vinculado, ¿no es así? ¿Quizás tendría sentido extender nuestro vinculador con los ganchos antes mencionados por onLinkHover y onLinkLeave , y que esos hipervínculos ansi se manejen como lo hacemos con los enlaces web en este momento?

El probable consumidor de esta API sería nuestro renderizador que muestra la URL en una descripción emergente.

@mofux Estaba pensando más como el complemento de búsqueda, el incrustador proporciona la interfaz de usuario en el estilo que quieran, solo proporcionamos las devoluciones de llamada para hacerlo. Buen punto que esto no te permite manejar las cosas todavía. Supongo que se fusiona con la API de enlace existente y tiene una configuración ITerminalOptions.enableAnsiHyperlinks para optar y detalla el por qué.

Supongo que se fusiona con la API de enlace existente y tiene una configuración ITerminalOptions.enableAnsiHyperlinks para optar y detalla el por qué.

¿Cómo sería la historia para que los integradores admitieran esta función? Abrir el enlace (invisible) al hacer clic en el texto vinculado es potencialmente peligroso, especialmente si no mostramos la URL vinculada en ninguna parte 🤔

Si bien mostrar el objetivo por adelantado es realmente agradable, no creo que haya un problema para abrir URL "desconocidas". Los aspectos de seguridad se han discutido en los comentarios bajo las especificaciones. Los navegadores abren URL "desconocidas" todo el tiempo, por ejemplo, cuando hay un código JS que altera el objetivo justo antes de abrirlo, a menudo para mostrar una URL "agradable" al usuario, pero en realidad lo abre a través de un redirector.

Hablando de eso ... algo que no se me ha ocurrido hasta ahora ...

Si xterm.js se está ejecutando dentro de un navegador real y abre el enlace en, digamos, una nueva pestaña de ese navegador: Supongo que filtrar la URL de xterm.js a través del campo Referer es algo de lo que preocuparse. No estoy seguro del soporte actual para rel = "noreferrer", pero parece algo que debería usarse.

Vea esta discusión relacionada del texto flotante . Ese problema se trata de anotar secciones de la salida con "tapas de herramientas" y otras ventanas emergentes al pasar el mouse, lo cual no es lo mismo que mostrar la URL cuando se pasa el mouse sobre un enlace. Sin embargo, es posible que ambos quieran utilizar el mismo mecanismo para mostrar el texto flotante real. Ambos probablemente usarían un MouseZoneManager .

¿Tenemos expertos en XSS dando vueltas? Quizás necesitemos una auditoría, jajaja.

Para mi conocimiento limitado sobre la seguridad del navegador, el principal vector de ataque con xterm.js son los datos que cruzan el borde del terminal / navegador:

  • XSS desde el navegador (JS) al terminal (datos)
    Eso ya es posible y, en mi humilde opinión, es responsabilidad del integrador (xterm.js no puede controlar esto de ninguna manera). Regla de oro: nunca importe scripts de una fuente que no sea de confianza en la página del terminal o en el websocket pty y, por lo tanto, el sistema que aloja el pty se perderá. No permita que se inserte contenido de usuario sin filtrar en la página y demás, básicamente todas las cosas típicas de XSS, o se perderá el contenido.
  • XSS desde el terminal (datos) al navegador (JS)
    Esa es una nueva cualidad que podríamos ingresar con las URL, si no nos aseguramos de que los datos del terminal nunca lleguen al contexto JS de la página de incrustación (por lo tanto, el objeto del terminal en sí). Si eso es posible (supongamos que por un segundo) un atacante puede obtener acceso a la página del navegador y, por lo tanto, realizar un ataque de terminal (datos) - navegador (JS) - terminal (datos). Supongamos además que xterm.js se ejecuta mucho en portales de servicios de orquestación en la nube y que el administrador usa sesiones de terminal en diferentes máquinas. Outch. Una vez que el atacante obtiene acceso a la página del navegador incrustado, todos los servicios en la nube a los que el administrador tiene acceso están en peligro.

La pregunta es: ¿hay posibilidades de cruzar el borde de la terminal (datos) - navegador (JS) con URL? Nuevamente, mi conocimiento limitado sobre la seguridad del navegador no ayuda mucho aquí. El único escenario en el que puedo pensar son los marcadores que se inyectan en el JS de la página. No tengo ni idea de si podemos evitar esto abriendo siempre cosas en una nueva ventana / pestaña solamente (supongo que la sesión aún se filtrará, si no es httpOnly? ¿Qué pasa con la conexión websocket?) Lo que me hace pensar que tenemos que analizar la URL y eliminar cualquier "contenido que parezca JS", oh cielos ...

Editar: tenga en cuenta que los websockets pierden la mayoría de las configuraciones de seguridad del navegador, ni siquiera tienen una verificación confiable del mismo origen (vaya con un sondeo largo ajax si lo necesita). Mmmm ...

bookmarklets [...] eliminan cualquier "contenido con apariencia JS"

Creo que es una buena idea incluir en la lista blanca solo las URL que comienzan con "http: //", "https: //", tal vez "ftp: //" y rechazar cualquier otra cosa. O al menos poner en una lista negra la falta de esquema y "javascript:".

En mi rama de hipervínculos agregué un parche https://github.com/PerBothner/xterm.js/commit/b2647b90d301c52229d01720800865a0d39f436f para una función de devolución de llamada configurable con un clic. Esto permite cambiar cómo se maneja el enlace. Por ejemplo, cuando DomTerm está configurado para usar mi rama xterm.js después de ls --hyperlink=auto tintinear en la mayoría de los nombres de archivo, se abrirá el archivo en emacs, pero los archivos html abrirán el archivo en su navegador predeterminado, según su configuración .

(Tenga en cuenta que hay algunas irregularidades en el prototipo. No sé si eso es específico del prototipo DomTerm).

Los navegadores abren URL "desconocidas" todo el tiempo, por ejemplo, cuando hay un código JS que altera el objetivo justo antes de abrirlo, a menudo para mostrar una URL "agradable" al usuario, pero en realidad lo abre a través de un redirector.

@egmontkob en los navegadores, generalmente comienza desde un lugar seguro, como un motor de búsqueda, que le dice muy claramente cuándo es el dominio. Para los terminales, necesitaría confiar en los programas (algunos de los cuales pueden imprimir contenido remoto), incluso la captura de un archivo podría mostrar un enlace malicioso. Parece que sería mejor estar seguro de forma predeterminada y tener una configuración que solo describa los riesgos y ofrezca mitigaciones.

En mi rama de hipervínculos, agregué un parche PerBothner @ b2647b9 para una función de devolución de llamada configurable con un clic.

@PerBothner ya hay un controlador aquí en el complemento webLinks: https://github.com/xtermjs/xterm.js/blob/509ce5fa3a698ee7847419117e9dd6b979b105bf/src/addons/webLinks/webLinks.ts to bit#L37, parece un bit#L37 configurar 2 controladores de enlaces web diferentes.

(Perdón por la respuesta tardía, me desvié).

@Tyriar escribió "ya hay un controlador aquí en el complemento webLinks". El problema es que webLinksInit crea un ILinkMatcher y asocia el controlador dado con un ILinkMatcher específico, que contiene un conjunto de expresiones regulares para coincidir. Pero, ¿cómo especificamos el controlador de enlaces para los hipervínculos creados por una secuencia de escape y, por lo tanto, no son el resultado de una coincidencia de expresiones regulares? Ese controlador debe ser "global", en el sentido de no estar asociado con ningún ILinkMatcher o regex. Configurar ese controlador global / predeterminado usando webLinksInit o Terminal.registerLinkMatcher no funciona.

Me parece que necesitamos un campo linkHandler en la Terminal; tener un campo handler en ILinkMatcher no es suficiente. Y si tenemos un campo linkHandler en Terminal , tiene sentido que ese controlador sea el predeterminado utilizado por registerLinkMatcher. Esto es lo que hace mi parche.

Si alguien quiere ayudar con esto, esto es lo que debe suceder:

  • Averigüe cómo lidiar con las implicaciones de seguridad de tener enlaces que no se muestran como URL, esto probablemente sea para hacer que la función se habilite y exponga un gancho para que los consumidores puedan mostrar una ventana emergente.
  • Encuentre una buena API para abrir un enlace, ya tenemos algo muy similar con la API de enlace de enlace, ¿se puede generalizar?
  • Agregue la lógica al analizador y almacene los enlaces en algún lugar, tal vez como IMarker s?

Mi rama de hipervínculos https://github.com/PerBothner/xterm.js/tree/hyperlinks puede ser un punto de partida. (Aunque es un poco antiguo, es posible que ya no funcione).

¿Cuál es el estado de la rama anterior? ¿Alguien está trabajando en esto?
@Tyriar enumeró muy bien los pasos necesarios. ¿Se ha realizado alguno de estos pasos?

@ Jma353 No creo que nadie esté trabajando activamente en esto, así que siéntete libre de implementar los bits necesarios.

@Tyriar No he leído la especificación con todos los detalles, pero parece que implementarla implicaría algunos malabarismos con el manejador del analizador, especialmente. algo así como una sobrecarga InputHandler.print temporal. Es un poco extraño que esté hecho así (de alguna manera lleva el estado del terminal al analizador, un hecho que ninguna otra secuencia de escape lo hace hasta ahora), pero debería ser factible reemplazando el controlador de impresión en el medio.

@jerch, sí, necesitaría algunos cambios en el analizador. Cambiar el tamaño de los enlaces envueltos es un caso en el que deberíamos asegurarnos de que también funcione.

VS Code ahora tiene soporte para mostrar desplazamientos detallados para enlaces, por lo que conectar esto resolverá el problema:

image

Es una pena que sean secuencias un poco extrañas ya que nuestros ganchos del analizador no lo cubren. Si lo hicieran, esto podría hacerse completamente como un complemento utilizando ganchos de analizador, marcadores y las API del proveedor de enlaces.

@Tyriar También con # 2751 el almacenamiento de atributos extendido se puede usar para anotar cosas de URL en las celdas de búfer.

Es una pena que sean secuencias un poco extrañas ya que nuestros ganchos del analizador no lo cubren. Si lo hicieran, esto podría hacerse completamente como un complemento utilizando ganchos de analizador, marcadores y las API del proveedor de enlaces.

Sí, eso es un problema y, en mi humilde opinión, no se puede resolver a nivel de complemento, incluso si expondríamos un gancho de controlador de impresión. Creo que esto tiene que ir directamente al código base más algunas condiciones excepcionales (como cualquier acción que no sea de impresión antes de que se reconozca el finalizador debería romper el marcado de URL de las celdas y demás).

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

pfitzseb picture pfitzseb  ·  3Comentarios

jerch picture jerch  ·  3Comentarios

Mlocik97-issues picture Mlocik97-issues  ·  3Comentarios

jestapinski picture jestapinski  ·  3Comentarios

Tyriar picture Tyriar  ·  4Comentarios