Precinto · sala de evaluación

Los números, y el comando para desconfiar de ellos

Todo lo que se afirma en el sitio se mide acá, con el comando que lo reproduce en tu máquina en menos de un minuto. Incluida la parte que no favorece al producto.

Reproducilo entero
pip install precinto

precinto demo --out banco
precinto bench banco/support-bundle-demo.tar.gz \
         --canaries banco/canaries.json --profile demo

Qué mide el banco

Un paquete de diagnóstico sintético con 17 canarios en 14 clases: credenciales, cadenas de conexión, identificadores personales y nombres internos, plantados en registros, configuración, variables de entorno y volcados binarios. Ningún valor es real; se generan con semilla fija, así que cualquiera obtiene exactamente los mismos.

DesenlaceQué significaCantidad
Neutralizadoreemplazado por un pseudónimo estable15
Retenidosu archivo se bloqueó entero por no ser inspeccionable1
Marcadotambién enmascarado, pero con una decisión humana pendiente1
Escapadosalió en claro sin que nadie lo señalara0

El desglose tiene cuatro estados y no dos a propósito. Un banco binario se felicita solo: la primera versión de éste informaba 100% sin haber medido nada, porque comparaba cada canario contra cada archivo y lo daba por contenido en cuanto faltaba en uno cualquiera. Y hubo una segunda vez: cuando pasamos a enmascarar también lo marcado, la condición «el valor ya no está» ganaba siempre y el estado «marcado» se volvió inalcanzable — este sitio llegó a publicar 16 neutralizados cuando eran 15 más 1 marcado.

Contra la línea de base

La pregunta que corresponde no es «¿encuentra cosas?» sino «¿encuentra más que un guion de veinte líneas con expresiones regulares?». Medido sobre el mismo banco:

MétodoContenidosTiempo
Expresiones regulares obvias (contraseña, clave de AWS, token de GitHub, PEM, correo)6 de 17 · 35%1 ms
Precinto — reglas, política, bloqueo de formatos17 de 17 · 100%5 ms

Lo que la línea de base deja pasar

Es la lista que importa, porque describe qué estás comprando:

ClaseDónde estaba
token JWTlogs/app.log
cadena de conexión con contraseñalogs/app.log
cabecera Authorization: Bearerlogs/app.log
dirección de red internalogs/app.log
asignación de contraseña en YAMLconfig/application.yaml
clave de OpenAI y de Stripeconfig/.env
token de Slacksupport/diagnostics.json
nombres de cliente y de proyectosupport/diagnostics.json
cadena opaca de alta entropíalogs/worker.log
Y lo que este número NO dice

Es un banco sintético. Mide que los detectores encuentran lo que se les plantó — no qué encontrarían en tus paquetes, que es la única pregunta que importa. Un banco propio siempre favorece a quien lo escribió: los canarios los elegí yo, sabiendo qué detecta la herramienta.

Por eso el paso siguiente con un fabricante es correrlo sobre su corpus, en su máquina, con la herramienta sin ver nada. Si en tus datos el número es malo, es un resultado útil y lo diré.

Lo que no hace, comprobado

AfirmaciónCómo se comprueba
No abre conexiones de redun test corre un escaneo completo con socket.socket, create_connection y getaddrinfo anulados, y falla si algo intenta usarlos
Nunca modifica el originaltests con --output-name apuntando al propio original, con .., con el nombre reservado del manifiesto, y con el manifiesto siendo un enlace simbólico
El manifiesto no lleva valores de secretose comprueba que ningún canario aparezca en el JSON, incluidos los que estaban en nombres de archivo
Una firma falsificada no pasaclave identidad con S=0 —la firma universal— rechazada; codificación prohibida rechazada; 200 firmas legítimas de OpenSSL aceptadas
La copia no importa archivos de fueraenlaces simbólicos a archivos y a directorios externos: no se copian ni se siguen
git clone https://github.com/hernaninverso/precinto.git && cd precinto
python3 test_precinto.py        # 104 comprobaciones
node test_verificador_web.js    # 26 sobre el verificador del navegador

Tres auditorías adversarias

El código pasó por tres pases de auditoría con un modelo de frontera, con el encargo explícito de demolerlo. Dos encontraron fallos que destruían datos del usuario, y los tres informes están resumidos acá porque ocultarlos sería exactamente lo que este proyecto critica.

PaseLo más grave que encontró
PrimeroUn perfil con una acción inventada dejaba el token intacto y el resultado seguía siendo «pasa». Y el verificador del navegador aceptaba una firma universalmente falsificable (clave identidad, R identidad, S=0): daba «Verificada» a cualquier mensaje.
Segundo--output-name con una ruta truncaba el paquete original: reproducido, de 2755 a 1774 bytes. Y shutil.copytree(symlinks=False) sigue los enlaces en vez de preservarlos, así que importaba archivos de fuera del paquete.
TerceroEl manifiesto se escribía sin ninguna de las comprobaciones puestas para el tar: una entrada llamada manifest.json se procesaba bien y después se destruía.
La lección que más vale de las tres

La primera auditoría corrió después de publicar. Fue el error, y por eso las otras dos corrieron antes. Un producto que sostiene que la evidencia debe preceder a la afirmación no puede auditarse a posteriori.