Spec v0.10 draft: no invisible characters in the creator's text

The author approved it on 30-09-2026, after Unicode 18.0.0 warned that
sequences of invisible variation selectors are used to attack AI
applications. The comment and the declared author allowed the tag
characters and loose variation selectors, which hide text a model
reads, and paths allowed runs of ZWJ, ZWNJ, VS15 and VS16.

- R4b: VS15 and VS16 only right after a character that
  emoji-variation-sequences.txt pairs with that selector, and ZWJ and
  ZWNJ never first, last or twice in a row in a segment.
- Section 29.6: the comment and the declared author carry no
  Default_Ignorable_Code_Point except that whitelist, placed as R4b
  says, each line standing for a segment.
- The tables add emoji-variation-sequences.txt; section 76 records the
  change as number 12, with mutations and vectors.
- The five new references of section 77 regain the two trailing spaces
  that break their line, like the others.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.10
dev 1 week ago
parent 52f01f6fd8
commit 631d09ca66

@ -1159,6 +1159,11 @@ R1 y R8 son de la capa 3 y se comprueban sobre todo el array; las demás, de la
- de la propiedad `Default_Ignorable_Code_Point`, salvo los de la lista blanca: U+200C (ZWNJ), U+200D (ZWJ), U+FE0E (VS15) y U+FE0F (VS16), que hacen falta en emoji y en varias escrituras. La propiedad incluye los controles bidi (U+061C, U+200E, U+200F, U+202A a U+202E y U+2066 a U+2069), U+00AD, U+034F, U+200B, U+2060 a U+206F, U+3164, U+FEFF, los demás selectores de variante y las etiquetas U+E0000 a U+E007F, que permiten nombres visualmente idénticos;
- de U+F000 a U+F0FF, del área de uso privado: Cygwin, WSL y el SMB de macOS representan con ellos los caracteres prohibidos en Windows, así que «informe», U+F03A y «anexo» se verían allí como «informe:anexo»;
- de la categoría general Cn, que incluye los no-caracteres y los puntos sin asignar: una versión futura de Unicode podría plegarlos o volverlos ignorables.
- **R4b.** Los puntos de la lista blanca de R4 solo van donde su uso es conforme:
- VS15 y VS16, justo detrás de un carácter para el que `emoji-variation-sequences.txt` (§29.5.1) define la secuencia con ese selector;
- ZWJ y ZWNJ, nunca al principio ni al final del segmento, ni justo detrás de otro ZWJ o ZWNJ.
Así un segmento no puede llevar secuencias invisibles, que esconden datos: Unicode 18.0.0 advierte de que las secuencias de selectores de variante invisibles sirven para atacar aplicaciones de IA. Los emoji compuestos siguen valiendo, como la bandera arcoíris, U+1F3F3 U+FE0F U+200D U+1F308.
- **R5.** Ningún segmento empieza por U+0020 ni termina en U+0020 o en '.'.
- **R6.** La parte del segmento anterior a su primer '.', o todo el segmento si no lo tiene, sin los U+0020 finales y sin distinguir mayúsculas ASCII, no es CON, PRN, AUX, NUL, CONIN$, CONOUT$, de COM0 a COM9, de LPT0 a LPT9, COM¹, COM², COM³, LPT¹, LPT² ni LPT³.
- **R6b.** Contando puntos de código, no se cumplen a la vez estas tres condiciones, que describen un alias 8.3 de NTFS:
@ -1175,13 +1180,13 @@ R1 y R8 son de la capa 3 y se comprueban sobre todo el array; las demás, de la
- **R9.** Hay como mucho 65 535 carpetas implícitas, es decir, prefijos propios distintos de las rutas.
- **R10.** La clave de R7 del primer segmento no empieza por «.datekeys-». La implementación de referencia escribe el árbol en `DIR/.datekeys-*` antes de moverlo a su destino (§56), y una entrada con ese nombre chocaría con él.
Orden de las comprobaciones de la capa 4 en la clave 5: para cada entrada, en su orden, R2, R3, R4, R5, R6, R6b, R6c, R10 y la maquetación de §29.4; después de todas las entradas, R7 y R9. Todas dan `ERR_HEAD_INVALID`, y la primera que falla decide.
Orden de las comprobaciones de la capa 4 en la clave 5: para cada entrada, en su orden, R2, R3, R4, R4b, R5, R6, R6b, R6c, R10 y la maquetación de §29.4; después de todas las entradas, R7 y R9. Todas dan `ERR_HEAD_INVALID`, y la primera que falla decide.
### 29.5.1 Tablas
R3, R4, R6c y R7 usan datos fijos, no los de la plataforma:
R3, R4, R4b, R6c, R7 y la regla de invisibles de §29.6 usan datos fijos, no los de la plataforma:
- **Unicode 18.0.0:** `UnicodeData.txt`, con la categoría general, la clase de combinación canónica y las descomposiciones canónicas; `DerivedCoreProperties.txt`, con `Default_Ignorable_Code_Point`; `CaseFolding.txt`, con sus entradas C y F; y NFD según UAX #15, con la descomposición algorítmica de Hangul.
- **Unicode 18.0.0:** `UnicodeData.txt`, con la categoría general, la clase de combinación canónica y las descomposiciones canónicas; `DerivedCoreProperties.txt`, con `Default_Ignorable_Code_Point`; `CaseFolding.txt`, con sus entradas C y F; `emoji/emoji-variation-sequences.txt`, con los caracteres que admiten VS15 y VS16 (R4b); y NFD según UAX #15, con la descomposición algorítmica de Hangul.
- **WindowsBestFit,** de unicode.org: los quince ficheros `bestfit874.txt`, `bestfit932.txt`, `bestfit936.txt`, `bestfit949.txt`, `bestfit950.txt`, de `bestfit1250.txt` a `bestfit1258.txt` y `bestfit1361.txt`, con la conversión de Unicode a su código de página de su sección `WCTABLE`.
Una implementación MUST aplicar las tablas generadas de esos ficheros, fijados por su SHA-256 (por fijar al implementar), y MUST NOT usar las funciones de Unicode de su plataforma para estas reglas: `normalize`, `toLowerCase`, las clases `\p{…}` de las expresiones regulares, el paquete `unicode` de Go o `golang.org/x/text`. Su versión de Unicode cambia con cada motor: Go 1.26.8 trae la 15.0.0, y Node 24.9, la 16.0. La implementación de referencia genera desde esos ficheros el código de las dos implementaciones, y sus pruebas comprueban los digests.
@ -1198,8 +1203,9 @@ El comentario y el autor declarado del head (§29.4) son UTF-8 válido. «Espaci
- **Comentario.** Ningún punto de código es de U+0000 a U+0008, de U+000B a U+001F, de U+007F a U+009F, de U+202A a U+202E, de U+2066 a U+2069, U+2028, U+2029, U+FEFF ni un no-carácter. Se admiten TAB y LF; el escritor convierte CR LF, y un CR suelto, en LF.
- **Autor declarado.** Lo mismo que el comentario, y además ni TAB, ni LF, ni U+061C, U+200E ni U+200F. No empieza ni termina en U+0020.
- **Invisibles.** Ni el comentario ni el autor declarado llevan puntos de la propiedad `Default_Ignorable_Code_Point` salvo los de la lista blanca de R4, y esos van solo donde R4b los admite, con cada línea en el papel del segmento. Quedan fuera las etiquetas U+E0000 a U+E007F y los selectores de variante fuera de una secuencia de emoji, con los que se esconde un texto que no se ve en pantalla pero que un modelo de IA sí lee. Por eso quedan fuera también las banderas de subdivisión, como la de Escocia, que usan etiquetas.
Así, ningún texto ni ruta puede llevar ESC ni un control C1 a un terminal, ni cambiar la dirección del texto que lo sigue.
Así, ningún texto ni ruta puede llevar ESC ni un control C1 a un terminal, cambiar la dirección del texto que lo sigue ni esconder un texto invisible.
---
@ -2747,6 +2753,10 @@ rutas "A" y "a/b" ERR_HEAD_INVALID, paso 17
autor declarado con LF ERR_HEAD_INVALID, paso 17
start de la primera entrada distinto de 0 ERR_HEAD_INVALID, paso 17
end − start distinto de size ERR_HEAD_INVALID, paso 17
ruta "a" seguida de VS16 ERR_HEAD_INVALID, paso 17
ruta con dos ZWJ seguidos ERR_HEAD_INVALID, paso 17
comentario con la etiqueta U+E0041 ERR_HEAD_INVALID, paso 17
comentario con el selector de variante VS17 ERR_HEAD_INVALID, paso 17
start de una entrada distinto del end de la anterior
ERR_HEAD_INVALID, paso 17
end del último fichero distinto de C ERR_INTEGRITY, paso 17
@ -2853,7 +2863,7 @@ Los de formato 3 cubren, como mínimo:
Serán `format3_single.dkc`, `format3_tree.dkc`, `format3_comment_only.dkc`, `format3_bloque256.dkc`, `format3_time_and_key_portable.dkc` con su `.dkk`, `format3_area_1024.dkc`, `format3_security_v2.dkc`, `format3_signature_unsupported.dkc` y `format3_seal_unsupported.dkc` (por implementar). Los vectores de rutas y del head van en `testdata/vectors/paths.json`, `head_schema.json` y `path_fold.json`, y los de `security`, en `security.json`.
Los vectores de rutas y del head cubren, como mínimo: U+00A0 y U+3000 al principio y al final de un segmento, con el veredicto que dan las tablas, que para U+3000 es el rechazo por R6c; best-fit; alias 8.3, «~1» incluido; Cn; `["b/..", "a"]`; U+206A a U+206F, las etiquetas y otros ignorables fuera de la lista blanca; «.» seguido de ZWJ y un segmento hecho solo de ZWJ; 127 veces «ΐ»; U+F03A; «.datekeys-x» en el primer nivel y en otro; el orden de U+FF5E y U+1F600; «ab» con y sin ZWNJ; y «¿», «§» y «♥», que se aceptan. Los de `security.json` cubren: el mapa exterior con la clave 2 que no es una cadena de bytes, con una clave 4 o con un byte de más dentro de `SECURITY_LEN` (X); `alg` 0 o una clave vacía dentro de la clave 2 (F1, con el sello intacto); y un `seal` que incumple su schema con un `seal_type` desconocido (S2).
Los vectores de rutas y del head cubren, como mínimo: U+00A0 y U+3000 al principio y al final de un segmento, con el veredicto que dan las tablas, que para U+3000 es el rechazo por R6c; best-fit; alias 8.3, «~1» incluido; Cn; `["b/..", "a"]`; U+206A a U+206F, las etiquetas y otros ignorables fuera de la lista blanca; «.» seguido de ZWJ y un segmento hecho solo de ZWJ; 127 veces «ΐ»; U+F03A; «.datekeys-x» en el primer nivel y en otro; el orden de U+FF5E y U+1F600; «ab» con y sin ZWNJ; «¿», «§» y «♥», que se aceptan; VS16 tras un emoji que lo admite, que se acepta, y tras «a», que no; ZWJ al principio, al final y dos seguidos; y la bandera arcoíris, que se acepta, y la de Escocia, que no. Los de `head_schema.json` cubren además un comentario con etiquetas y con selectores de variante sueltos. Los de `security.json` cubren: el mapa exterior con la clave 2 que no es una cadena de bytes, con una clave 4 o con un byte de más dentro de `SECURITY_LEN` (X); `alg` 0 o una clave vacía dentro de la clave 2 (F1, con el sello intacto); y un `seal` que incumple su schema con un `seal_type` desconocido (S2).
Los vectores de las reglas de relleno (§29.1) van en un fichero propio, `testdata/vectors/padding.json`, con L, código, P, la longitud de `PAYLOAD_AGE`, L_MAX y, como dato informativo, E, S y lastBits.
@ -3192,8 +3202,9 @@ head
mtime opcional; hasta 65 535 ficheros y 16 MiB; ERR_HEAD_INVALID
paths
= R1 a R10, con tablas propias de Unicode 18.0.0 y WindowsBestFit;
orden por bytes UTF-8
= R1 a R10 y R4b, con tablas propias de Unicode 18.0.0 y WindowsBestFit;
orden por bytes UTF-8; ningún invisible en el texto del creador salvo
ZWJ, ZWNJ, VS15 y VS16 donde su uso es conforme
security
= mapa de versión 1 con la firma y el sello codificados aparte; nunca
@ -3512,6 +3523,12 @@ La v0.10 añade el formato 3 de `.dkc`, que guarda varios ficheros con sus rutas
- Caso: el `lastModified` de un `File` del navegador y `ModTime().Unix()` en Go pueden ser negativos, para una fecha anterior a 1970, y el schema del head solo admite enteros sin signo.
- Pruebas previstas: las del escritor de la referencia y de `datekeys-ts`.
12. **Invisibles** (§29.5 R4b, §29.5.1, §29.6).
- Cambio: ningún texto del creador, sean rutas, comentario o autor declarado, lleva puntos de `Default_Ignorable_Code_Point` salvo ZWJ, ZWNJ, VS15 y VS16, y estos solo donde su uso es conforme: VS15 y VS16 tras un carácter que los admite según `emoji-variation-sequences.txt`, y ZWJ y ZWNJ nunca al principio ni al final, ni dos seguidos.
- Motivo: Unicode 18.0.0 aclara qué usos de los selectores de variante son conformes y advierte de que sus secuencias invisibles sirven para atacar aplicaciones de IA. Un comentario o un nombre con texto oculto se vería normal en pantalla, y lo leería un modelo al que se pasara la cápsula abierta.
- Caso: cada etiqueta de U+E0020 a U+E007E es un carácter ASCII invisible: «Hola» seguida de U+E0049, U+E0047, U+E004E, U+E004F, U+E0052 y U+E0041 se muestra como «Hola» y lleva escrito IGNORA. Cada selector de VS1 a VS256 detrás de un emoji codifica un byte que tampoco se ve. El borrador anterior admitía los dos en el comentario, y en las rutas admitía secuencias de ZWJ, ZWNJ, VS15 y VS16 de cualquier longitud.
- Pruebas previstas: las mutaciones de invisibles de §64 y los vectores de `paths.json` y `head_schema.json`.
`ERR_HEAD_INVALID` es el único código nuevo (§69).
Ningún objeto de formato 1 ni de formato 2 cambia de veredicto ni de código, salvo que `VERSION` 3 deja de dar `ERR_UNSUPPORTED_VERSION` en el paso 2. Producen `VERSION` 3 solo dos de los 125 casos de `mutations.json`, «version changed» y «format 2: version changed», y ninguno de los 4 380 de `inspect_differential.json`. Cambian estos datos de prueba:
@ -3546,7 +3563,7 @@ Ningún objeto de formato 1 ni de formato 2 cambia de veredicto ni de código, s
- K. Nikitin, L. Barman, W. Lueks, M. Underwood, J.-P. Hubaux, B. Ford — «Reducing Metadata Leakage from Encrypted Files and Communication with PURBs», Proceedings on Privacy Enhancing Technologies 2019(4), pp. 6–33: función de relleno Padmé (§29.1)
https://doi.org/10.2478/popets-2019-0056
- The Unicode Standard, Version 18.0.0 — Unicode Character Database: `UnicodeData.txt`, `DerivedCoreProperties.txt` y `CaseFolding.txt` (§29.5.1)
- The Unicode Standard, Version 18.0.0 — Unicode Character Database: `UnicodeData.txt`, `DerivedCoreProperties.txt`, `CaseFolding.txt` y `emoji/emoji-variation-sequences.txt` (§29.5.1)
https://www.unicode.org/Public/18.0.0/ucd/
- UAX #15 — Unicode Normalization Forms: NFD (§29.5.1)

Loading…
Cancel
Save

Powered by TurnKey Linux.