HTML, chmod, contenedores y cron
El razonamiento detrás de cuatro utilidades: por qué un editor HTML necesita una lista de permitidos y una zona de pruebas, por qué es importante la S mayúscula en una cadena chmod, qué no puede expresar un comando docker run en compose y las dos reglas cron que atrapan a todos.
El editor HTML: una lista de permitidos, no un filtro
El editor produce HTML, y el HTML que proviene de un cuadro de texto es el vector de inyección más antiguo que existe. Aquí se confunden dos cuestiones diferentes, por lo que vale la pena separarlas. La primera es "¿se puede engañar a este editor para que emita un marcado que ejecute código en la página que lo muestra?" La segunda es "¿es esta una forma segura de limpiar HTML hostil de una fuente que no es de confianza?" Esta herramienta responde sí a la primera y no a la segunda, y lo dice en el panel en lugar de permitirle asumir lo contrario.
El mecanismo es una lista de permitidos. Se permite una lista de elementos; todos los demás elementos se desenvuelven, por lo que su texto sobrevive y su etiqueta no. Se permite una lista de atributos por elemento; todo lo demás se elimina, lo que hace que cada controlador de eventos sea imposible en lugar de simplemente bloquearse. Los nombres de los atributos están en minúsculas antes de esa prueba, por lo que oNeRrOr y ONERROR son el mismo nombre rechazado que onerror. Los elementos cuyo contenido el analizador HTML trata como texto sin formato (script, estilo, área de texto, iframe, título) se eliminan junto con su contenido, porque al desenvolverlos se pegaría el código fuente del script en el documento como marcado.
Las direcciones de enlace tienen su propia comprobación. El valor se decodifica como entidad y se eliminan espacios y caracteres de control antes de leer su esquema, porque eso es lo que hace un navegador al navegar: javascript:alert(1) y jav\tascript:alert(1) llegan al mismo sitio. Solo sobreviven las direcciones http, https, mailto, tel, ftp y relativas. Si la herramienta no puede resolver una referencia de carácter —: es el ejemplo clásico—, se rechaza la dirección completa en lugar de pasarla, porque un filtro que entiende menos de la entrada que el navegador tiene un agujero.
No hay ningún botón de imagen e img no está en la lista de permitidos. Una etiqueta de imagen permitida es una solicitud saliente desde donde termine el documento y una superficie de error. Para un editor que produce prosa tampoco vale la pena.
La defensa que no depende de que nada de esto sea perfecto es la previa. Se representa en un iframe con un atributo de zona de pruebas que no otorga nada en absoluto: ni scripts, ni formularios, ni acceso del mismo origen. Si una carga útil alguna vez sobreviviera a la lista de permitidos, el navegador aún se negaría a ejecutarla allí. Esa es una garantía estructural más que una promesa sobre nuestro código.
La limitación honesta: este es un desinfectante basado en cadenas, no un analizador HTML5 completo. Los diferenciales del analizador (entradas en las que un navegador crea un árbol diferente al de este tokenizador) son la debilidad conocida de cada desinfectante creado de esta manera. Para la salida, la genera usted mismo en este editor, eso está bien. Para limpiar HTML que llegó de un extraño, use un desinfectante que se ejecute en un analizador real, en un servidor que usted controle.
Chmod: la letra mayúscula es el mensaje completo
Un modo de archivo Unix tiene doce bits: tres bits de permiso para cada propietario, grupo y otros, además de setuid, setgid y el bit adhesivo. La forma octal es una lectura directa de esos bits, por eso 4 + 2 + 1 = 7 significa leer, escribir y ejecutar.
La forma simbólica que imprime ls es donde los bits especiales se vuelven interesantes, porque no tienen su propia columna. setuid reemplaza el carácter de ejecución del propietario, setgid reemplaza el carácter de ejecución del grupo y sticky reemplaza el otro carácter de ejecución. La letra está en minúscula cuando el bit de ejecución subyacente también está configurado y en MAYÚSCULA cuando no lo está.
Entonces 4755 es rwsr-xr-x (un programa setuid que se puede ejecutar) mientras que 4644 es rwSr--r--, un archivo setuid que nadie puede ejecutar. La S mayúscula es el sistema que le dice que la broca es inerte y casi siempre es un error más que una elección. Lo mismo se aplica a 1644, que muestra rw-r--r-T: un bit adhesivo en un archivo normal donde el otro bit de ejecución está claro, que en un kernel moderno no hace precisamente nada.
Dos distinciones más que vale la pena tener en cuenta. La cadena de nueve caracteres que imprime ls no es el argumento que toma chmod: chmod quiere una lista de asignaciones como u=rwx,g=rx,o=rx,u+s. Y los mismos bits significan cosas diferentes en un directorio que en un archivo: ejecutar significa "puede entrar y atravesar", setgid significa "los archivos nuevos heredan este grupo" y el bit adhesivo significa "cualquiera puede crear, solo el propietario puede eliminar", razón por la cual /tmp es 1777.
Docker ejecuta para componer: análisis y qué no convierte
El convertidor divide el comando con un tokenizador con reconocimiento de cotizaciones escrito para esta herramienta. No se ejecuta, evalúa ni entrega nada a un shell. Un comando que contiene comillas invertidas, $(...) o un punto y coma se lee como caracteres literales, porque lo único que hace esta herramienta con su entrada es leerla.
La mayoría de las banderas se asignan limpiamente: puertos, volúmenes, entorno, etiquetas, política de reinicio, capacidades, comprobaciones de estado, límites de recursos, DNS y hosts adicionales tienen claves de redacción con el mismo significado. Los volúmenes con nombre y las redes definidas por el usuario necesitan una declaración de nivel superior, así como la referencia del servicio, por lo que la salida lleva una: con externo: verdadero en las redes, porque una ejecución de la ventana acoplable de red podría unirse a una que ya existía.
Algunas banderas no tienen equivalente de composición, y aquí es donde los convertidores suelen fallar silenciosamente. --rm no es una propiedad de servicio: un servicio de redacción no se elimina cuando sale. -d describe cómo invocó la CLI, no cuál es el servicio. --link es heredado, --mount necesita un formato largo que esta herramienta no escribe, --gpus depende de su controlador. Cada uno de estos produce una advertencia con nombre en lugar de desaparecer. Una bandera desconocida también produce una advertencia y se trata como si no tomara ningún valor, porque adivinar que tomó uno convertiría el nombre de su imagen en un argumento y produciría un archivo seguramente incorrecto.
La salida no incluye una versión de nivel superior: clave. Compose v2 lo ignora y las versiones actuales advierten al respecto; Ha quedado obsoleto desde que la especificación de composición reemplazó las versiones antiguas de formato de archivo.
Citar no es cosmético. Una asignación de puerto escrita como 8080:80 sin comillas se lee como un número por los analizadores YAML 1.1, y sí, no, encendido y apagado son valores booleanos en el mismo dialecto. Se cita todo lo que pueda malinterpretarse; todo lo que se lea claramente como una cadena se deja solo, por lo que el archivo sigue siendo legible.
Cron: dos reglas que atrapan a todos
La primera es la regla del día. Cuando tanto el día del mes como el día de la semana están configurados en un valor distinto de *, cron ejecuta el trabajo cuando CUALQUIERA coincide, no cuando ambos lo hacen. Entonces 0 0 13 * 5 es "medianoche del día 13 y medianoche todos los viernes", que es aproximadamente cinco veces al mes, no "viernes 13", que es una o dos veces al año. El generador advierte cuando ambos campos están restringidos y la oración que escribe dice "o" en lugar de "y".
El segundo es la zona horaria. Cron usa la zona de la máquina en la que se ejecuta, que frecuentemente es UTC en un servidor y casi nunca la zona de la persona que escribe el crontab. Por lo tanto, la vista previa de la siguiente ejecución pregunta qué zona usar en lugar de asumir la suya. Los tiempos se calculan como tiempos de reloj de pared en esa zona, por lo que un trabajo diario permanece en la misma hora local durante un cambio de horario de verano en lugar de variar una hora, y una hora local que no existe, en la hora que se omite cada primavera, se deja fuera de la lista, porque cron tampoco se ejecutará en ese momento.
La sintaxis en sí es pequeña: una estrella, un número, un rango a-b, una lista a,b,c, un paso */n o a-b/n, y los nombres de mes y día JAN-DIC y SUN-SAT. Tanto 0 como 7 significan domingo. Un valor simple con un paso, como 5/15 en el campo de minutos, significa "desde 5 hasta el final del rango, cada 15", que es el minuto 5, 20, 35 y 50.
La validación es estricta a propósito. 60 * * * * se rechaza porque los minutos terminan en 59; * * * * 8 se rechaza porque el campo del día se detiene en 7; */0 * * * * se rechaza porque un paso de cero no coincide con nada. Seis campos generalmente significan una expresión Quartz o systemd cuyo primer campo son segundos, por lo que el error dice eso en lugar de solo contar. Un horario que es sintácticamente válido pero que nunca puede ejecutarse (0 0 30 2 * solicita el 30 de febrero) se acepta y se marca, porque rechazarlo sería incorrecto y permanecer en silencio sería peor.
¿Qué pasa con lo que pegas?
- Cada conversión, hash, decodificación y diferenciación se ejecuta en la pestaña de su navegador. Ninguna entrada se carga, registra o almacena en un servidor, porque no hay ningún servidor involucrado una vez que la página se ha cargado.
- Los hashes provienen de la implementación Web Crypto del propio navegador y los UUID de su generador aleatorio criptográficamente seguro. Ninguno de los dos implica una llamada de red.
- Nada de lo que escribe se escribe en el almacenamiento local o en una cookie. Al recargar la página se descarta; cerrar la pestaña la descarta.
- La analítica de todo el sitio se ejecutan únicamente en el host de producción canónico configurado y se describen en la Política de Privacidad; Los hosts locales y de vista previa lo rechazan. Los valores, tokens, URL y contenidos de archivos pegados están excluidos de los eventos analíticos propios de ToolAcre. La publicidad está deshabilitada en la configuración actual.
- Dicho esto: una clave JWT o API es una credencial activa. El hábito seguro es nunca pegar uno en una página web que usted no escribió, por muy confiables que sean sus afirmaciones, incluida ésta.
Preguntas
¿Puedo pegar HTML hostil en el editor para limpiarlo?
Puede pegarlo y no se ejecutará nada: el controlador de pegado desinfecta la carga útil del portapapeles antes de insertar algo, y la vista previa es un iframe en espacio aislado sin scripts permitidos. Pero no utilice el resultado como control de seguridad para entradas que no sean de confianza. Esta es una lista de permitidos basada en cadenas para la salida del propio editor, no un filtro XSS de propósito general, y el analizador de un navegador puede llegar a un árbol diferente al de un tokenizador como este. Para contenido que no sea de confianza, desinfecte en un servidor con un analizador HTML5 real.
¿Por qué el editor elimina mis imágenes y tablas?
Porque no están en la lista de permitidos. Las imágenes son una solicitud saliente y una superficie de error; Las tablas simplemente están fuera de lo que sirve este editor. Su contenido de texto sobrevive, las etiquetas no. Se trata de una lista de permitidos que funciona y no de un error, pero sí significa que no es la herramienta adecuada para editar un documento complejo existente.
¿Por qué chmod 4644 muestra una S mayúscula?
Porque setuid está configurado y el bit de ejecución del propietario no. La letra mayúscula significa que el bit especial no tiene nada sobre lo que actuar: es un archivo setuid que no se puede ejecutar. La s minúscula significa que ambos bits están configurados. La misma regla te da S para setgid y T para el bit adhesivo, y hacerlo al revés es el error más común en las calculadoras de modo.
¿El convertidor Docker ejecuta mi comando?
No, y no puede. El comando está dividido por un tokenizador que entiende las citas y nada más. No hay evaluación, ni shell, ni proceso hijo: la página no tiene forma de iniciar uno. Todo lo que pegues permanecerá en la pestaña.
¿Por qué el convertidor advierte en lugar de simplemente mostrar una señal que no puede manejar?
Porque un archivo de redacción que silenciosamente hace menos que el comando del que proviene es peor que no generar ningún resultado: lo descubres en producción. Cada bandera que no está representada tiene un nombre y qué hacer al respecto. Si no ve ninguna advertencia, no se perdió nada.
¿Por qué las siguientes ejecuciones de cron son diferentes de las que hace mi servidor?
Casi siempre la zona horaria. Cron usa la zona de la máquina que lo ejecuta; la vista previa usa la zona que usted eligió en el menú desplegable. Configúrelo en la zona de su servidor, a menudo UTC, y ellos deberían estar de acuerdo. El otro candidato es la regla del día: si se establecen tanto el día del mes como el día de la semana, cron se ejecuta en cualquiera de los dos, lo cual es más frecuente de lo que la mayoría de la gente pretende.
Limitaciones
- El desinfectante HTML es una lista de permitidos para la salida propia de este editor, implementada como un tokenizador de cadenas en lugar de un analizador HTML5 completo. No es un filtro XSS de uso general y no debe utilizarse como tal.
- El editor no tiene imágenes, tablas, colores o controles de fuentes, y no hay forma de agregarlos: todo lo que está fuera de la lista de permitidos se elimina.
- La superficie de edición utiliza document.execCommand, que está en desuso y no tiene un reemplazo implementado. Los navegadores todavía lo admiten; El comportamiento difiere ligeramente entre ellos, especialmente en torno al anidamiento de listas.
- La calculadora chmod cubre únicamente los doce bits de permiso. Las listas de control de acceso, los atributos extendidos, los contextos SELinux, la aritmética de umask y las ACL de Windows están fuera de alcance.
- El convertidor de Docker traduce un único comando de ejecución de Docker en un único servicio. No lee Dockerfiles, no resuelve imágenes y no puede expresar --mount, --gpus, --device, --link o --volumes-from; en su lugar, cada uno de ellos produce una advertencia con nombre.
- Las banderas que el convertidor no reconoce se tratan como si no tuvieran valor. Si dicha bandera tomó una, el valor se leerá mal; la advertencia así lo dice, y eliminar la bandera es la solución.
- El generador de cron lee únicamente el formato crontab de cinco campos. Expresiones Quartz y systemd de seis campos, @reboot y las expresiones no estándar L, W, # y ? Los operadores son rechazados en lugar de adivinados.
- Los horarios de la próxima ejecución provienen de la base de datos de zonas horarias del navegador a través de Intl. Son una vista previa, no una garantía: la máquina que ejecuta cron puede tener una zona diferente, una versión de base de datos diferente o un demonio que no se estaba ejecutando cuando llegó el momento.