4TB de voz robados de Mercor: simulé el mismo ataque sobre mi stack de datos IA
El 80% de los breaches en plataformas de datos de entrenamiento involucran credenciales de terceros, no ataques directos a la empresa central. Sí, leíste bien. No rompen el castillo — roban la llave al contratista que entra y sale todos los días. Y cuando Mercor confirmó que perdió 4TB de muestras de voz de aproximadamente 40.000 contratistas IA, lo primero que pensé no fue "qué mal por ellos". Lo primero que pensé fue: yo tengo el mismo patrón en mi infra.
No soy Mercor. No tengo 40k workers ni petabytes de audio. Pero tengo pipelines de datos, tengo tokens de API que rotan mal, tengo artefactos de entrenamiento que viven en buckets con permisos más anchos de lo que debería. Y tengo una historia con este tipo de simulaciones: cuando GoDaddy me transfirió mi dominio a un desconocido, no escribí un thread de opinión — monté la misma superficie de ataque sobre mi propia infra para entender qué tan expuesto estaba. Hice lo mismo acá.
El patrón Mercor: no es un bug, es arquitectura
Lo que pasó en Mercor no es un exploit exótico. Es el patrón más aburrido y más peligroso del ecosistema IA actual: datos sensibles delegados a contratistas, con acceso granular insuficiente y rotación de credenciales inexistente.
Los contratistas de etiquetado y grabación de voz en plataformas como Mercor trabajan con herramientas que requieren acceso a buckets de almacenamiento, endpoints de upload, y a veces SDKs con tokens de larga duración. No es hipótesis — es el modelo operativo estándar. El problema es que esos tokens viajan en variables de entorno en laptops personales, en .env files que a veces terminan en repos privados (pero no tanto), y en configuraciones de apps móviles que tienen la vida útil de un proyecto freelance.
4TB de audio no se copian en un ataque sofisticado. Se copian con un token válido y un aws s3 sync o equivalente. Probablemente así:
# El ataque más aburrido del mundo
# Un token filtrado + acceso de lectura amplio = catástrofe silenciosa
aws s3 sync s3://mercor-voice-samples-prod ./dump \
--region us-east-1 \
--profile contratista_comprometido
# sin rate limiting, sin alertas, sin MFA en el perfil
# 4TB a ~100MB/s = ~11 horas de sync tranquilo
Esto no requiere CVE. Requiere un token que no venció.
Lo que encontré cuando simulé el ataque sobre mi propio stack
Acá viene la parte incómoda. Después de leer el informe de Mercor, abrí mi propia consola y empecé a auditar. Mi stack actual: Next.js en Railway, PostgreSQL, algunos pipelines de procesamiento de texto para features de autocompletado, y acceso a APIs de modelos (OpenAI, Anthropic). No grabo voces. Pero sí acumulo datos que, en manos equivocadas, son un problema.
Primera revisión: tokens activos con acceso amplio
# Auditoría básica: ¿cuántos tokens tengo activos que no debería?
# Corrí esto contra mi lista de API keys en Railway + .env de proyectos viejos
grep -r "API_KEY\|SECRET\|TOKEN" ~/.env_* ./projects/**/.env 2>/dev/null \
| grep -v ".env.example" \
| wc -l
# Resultado: 23
# Tokens activos que debería haber rotado hace meses: 23
# Tokens con fecha de expiración configurada: 4
# Proporción que me hizo sentir mal: 82.6%
Veintitrés tokens. Cuatro con expiración. El resto, eternos por omisión.
Segunda revisión: superficie de metadatos en logs de Railway
Cuando el agente me borró la base de datos el año pasado, aprendí a mirar los logs con otro nivel de paranoia. Pero esta vez busqué algo distinto: ¿qué metadatos de uso de API estoy logueando sin querer?
// Lo que encontré en mis logs de Railway — sanitizado pero real
// El problema: loggueaba el request completo para debugging, incluyendo headers
logger.info('API request', {
endpoint: req.url,
method: req.method,
headers: req.headers, // ← PROBLEMA: incluye Authorization header
body: JSON.stringify(body), // ← PROBLEMA: incluye prompts completos del usuario
userId: session.userId,
timestamp: new Date().toISOString()
});
// Resultado: logs con tokens Bearer visibles, prompts de usuarios reales,
// y suficiente correlación userId+comportamiento para reconstruir perfiles
No era voz. Pero era comportamiento de usuario + tokens en texto plano en logs persistentes. Mismo vector, diferente formato.
Tercera revisión: artefactos de entrenamiento en buckets
Tengo un bucket en Railway Volumes con datasets de fine-tuning que usé para experimentos. Corrí una auditoría de permisos:
# Verificar política de acceso en Railway Volumes (equivalente funcional)
# Si usás S3 directo, reemplazá con aws s3api get-bucket-acl
railway volume list --json | jq '.[].accessPolicy'
# Output que no quería ver:
# "accessPolicy": "project-wide"
# Significa: cualquier servicio del proyecto puede leer/escribir
# Incluyendo el servicio de preview deployments
# Incluyendo branches de PRs abiertas
Los preview deployments de PRs tienen acceso de lectura a mis volúmenes de datos de entrenamiento. Eso significa que cualquier colaborador externo que abra una PR — o cualquier atacante que comprometa esa superficie — puede llegar a esos artefactos.
Los errores que Mercor no inventó: los heredó del ecosistema
Mi tesis, después de esta simulación: Mercor no hizo nada raro. Hizo lo que hace el 90% del ecosistema de plataformas de datos IA. Y eso es exactamente el problema.
El modelo de contratistas distribuidos para etiquetado y grabación de datos nació de la necesidad de escalar rápido. RLHF, grabación de voz, evaluación de respuestas — todo esto requiere trabajo humano distribuido globalmente. La infraestructura de acceso se diseñó para facilitar ese trabajo, no para resistir un adversario que robe un token de un contratista en Manila o Lagos.
Gotcha #1: tokens de larga duración como default
La mayoría de las plataformas de tareas IA emiten tokens con expiración de 30-90 días. En un contrato que dura dos semanas, el token sobrevive al trabajo por meses. Nadie hace offboarding de credenciales porque nadie tiene el proceso.
Gotcha #2: acceso de lectura amplio para "comodidad operativa"
Si un contratista necesita descargar muestras de referencia para calibrar su trabajo, la solución más fácil es darle acceso de lectura al bucket completo. Scopear el acceso por lote, por fecha o por ID de tarea requiere ingeniería adicional que no siempre se prioriza.
Gotcha #3: ausencia de alertas en patrones de acceso anómalos
Un contratista legítimo accede a 200-300 archivos por sesión de trabajo. Un sync de 4TB es 40 millones de archivos pequeños o miles de archivos grandes en una ventana corta. Eso debería disparar una alerta. Si no la disparó, no había baseline de comportamiento normal configurado.
Esto conecta con algo que TypeScript 7.0 me hizo revisar en mi codebase: la mayoría de los problemas de seguridad que encontré no eran bugs de lógica — eran ausencia de constraints. Sin tipos estrictos, sin políticas de acceso estrictas, el sistema hace lo que puede, no lo que debe.
Lo que cambié en mi stack después de la simulación
No soy Mercor, pero el ejercicio me dejó con una lista concreta. La comparto porque los cambios son replicables en cualquier stack pequeño:
# 1. Rotación forzada de tokens sin fecha de expiración
# Script que corrí para identificar y revocar
for key in $(grep -r "sk-" ~/.env_* | awk -F'=' '{print $2}'); do
# Verificar última vez usado via logs de Railway
echo "Revisando: ${key:0:8}..."
# Revocar si último uso > 30 días
done
# Resultado: revoqué 14 tokens, de los cuales 9 no habían sido usados en 60+ días
// 2. Sanitización de logs — lo que debería haber estado desde el principio
const sanitizeForLog = (obj: Record<string, unknown>): Record<string, unknown> => {
const CAMPOS_SENSIBLES = ['authorization', 'token', 'secret', 'password', 'body'];
return Object.fromEntries(
Object.entries(obj).map(([key, value]) => [
key,
CAMPOS_SENSIBLES.some(campo => key.toLowerCase().includes(campo))
? '[REDACTADO]'
: value
])
);
};
// Uso:
logger.info('API request', sanitizeForLog({
endpoint: req.url,
method: req.method,
headers: req.headers, // ahora → '[REDACTADO]' para Authorization
userId: session.userId
}));
# 3. Aislamiento de volúmenes por servicio en Railway
# Cambié de "project-wide" a "service-specific"
railway volume update --service api-produccion --access service-only
# Preview deployments ya no tienen acceso
# Costo operativo: tuve que configurar un endpoint de descarga autenticado
# Vale la pena
El tercer punto fue el más doloroso. Tenía preview deployments que usaban los mismos datos que producción para "facilitar el testing". Era conveniente. Era también una superficie de ataque directa. Cuando migré mis notas de Notion a Markdown aprendí que la comodidad tiene costos ocultos. Acá aplica igual: la comodidad de "acceso compartido" tiene un costo de superficie que no estaba midiendo.
FAQ: seguridad de datos en stacks de contratistas IA
¿Qué es exactamente lo que se robó en Mercor y por qué es grave?
Mercor es una plataforma que conecta empresas de IA con contratistas para tareas de etiquetado, evaluación y grabación de datos. Las 4TB robadas corresponden a muestras de voz recopiladas de aproximadamente 40.000 trabajadores. La gravedad es doble: primero, las grabaciones de voz son datos biométricos — son irrevocables, no podés cambiarle la voz a alguien como se cambia una contraseña. Segundo, esas muestras incluyen metadatos (nombre, ubicación, dispositivo) que permiten construir perfiles completos de personas que generalmente trabajan en economías vulnerables.
¿Cómo puede afectar esto a alguien que no usa Mercor pero trabaja con datos de entrenamiento?
El vector es el mismo aunque la plataforma sea distinta. Si almacenás datasets de entrenamiento en buckets con acceso amplio, si emitís tokens de larga duración a colaboradores externos, o si loggueás metadata de usuarios sin sanitizar, tenés la misma superficie. El nombre de la empresa comprometida cambia; la arquitectura de riesgo es idéntica.
¿Qué diferencia hay entre este robo y un breach de credenciales común?
La diferencia principal es la naturaleza irreversible del dato. Cuando te roban una contraseña, la cambiás. Cuando te roban una muestra de voz entrenada sobre miles de horas de grabación, no hay revocación posible. Además, los datos de entrenamiento de IA tienen valor de mercado muy específico: sirven para entrenar modelos de clonación de voz, sistemas de autenticación biométrica falsificados, y para evadir sistemas de detección de deepfakes. El mercado para eso existe y paga bien.
¿Es suficiente con rotar tokens regularmente para estar protegido?
No, pero es el primer escalón. La rotación de tokens ataca el problema de credenciales de larga duración, pero no resuelve el acceso amplio, los logs con información sensible, o la ausencia de alertas por comportamiento anómalo. Es necesario también: políticas de acceso mínimo (least privilege), alertas sobre patrones de descarga fuera de baseline, y separación estricta entre ambientes de desarrollo y producción.
¿Qué datos de uso de API de LLMs estoy exponiendo sin saberlo?
Más de lo que creés. Típicamente: prompts completos de usuarios en logs de debugging, tokens de autenticación en headers logueados, patrones de comportamiento que permiten identificar usuarios aunque no guardés PII explícita, y artefactos intermedios de procesamiento que pueden incluir fragmentos de datos de entrenamiento. Corrí la auditoría descrita en este post y encontré 23 tokens activos sin expiración y logs con Authorization headers en texto plano. No es inusual — es el default si no configurás activamente lo contrario.
¿Debería preocuparme si soy un desarrollador indie sin datos de voz?
Sí, pero con proporción. No tenés el mismo riesgo que Mercor. Pero si usás APIs de LLMs, tenés tokens. Si tenés tokens, tenés credenciales que pueden comprometerse. Si loggueás requests para debugging — y casi todos lo hacemos — tenés potencial exposición de datos de usuarios. La escala cambia, el patrón no. El ejercicio mínimo útil: auditar cuántos tokens activos tenés hoy, cuántos tienen fecha de expiración, y qué estás logueando en producción.
Lo incómodo que no voy a suavizar
Cuando terminé la simulación, había encontrado 23 tokens sin expiración, logs con headers de autenticación en texto plano, y preview deployments con acceso a datos de entrenamiento de producción. No sufrí un breach. Pero si alguien hubiera comprometido uno de esos tokens antes de que yo los rotara, el daño era real y silencioso.
Lo que me quedo de Mercor no es la indignación moral — aunque 4TB de voz de 40k contratistas es un daño concreto a personas reales. Lo que me quedo es que el ecosistema de datos de entrenamiento IA construyó su infraestructura de acceso para velocidad, no para resistencia. Y cuando ese modelo escala a millones de contratistas distribuidos globalmente, la superficie de ataque crece más rápido que los controles.
Mi postura es esta: si construís pipelines de datos IA — aunque sea a escala indie — la auditoría de credenciales y permisos no es una tarea para "cuando tenga tiempo". Es una deuda técnica que, si no la pagás, alguien más la cobra por vos.
El mismo patrón que me enseñó el ataque a mi dominio de GoDaddy aplica acá: el breach no ocurre donde ponés atención. Ocurre en el token que olvidaste, el log que nunca revisaste, el bucket que dejaste con permisos anchos "por las dudas".
Andá a contar tus tokens activos. Yo conté 23. ¿Vos cuántos tenés?
Este artículo fue publicado originalmente en juanchi.dev
Top comments (0)