如何保護 Cloudflare Workers KV,防範影響 Edge AI 模型的新漏洞
Protege tus KV de Cloudflare Workers ante la nueva vulnerabilidad IA
Cloudflare Workers KV 出現可被利用的漏洞,攻擊者可透過格式錯誤的請求列舉命名空間中的所有鍵值,進而讀取或覆寫模型權重、API token 等資料。文章提供以 Worker 封鎖可疑路徑、限制 KV 存取及加密敏感資料等防護措施。
Alerta en Cloudflare Workers: cómo proteger tus KV de la nueva vulnerabilidad que afecta a los modelos de IA en Edge
Introducción
En los últimos días la exposición de los stores KV de Cloudflare Workers se ha convertido en el tema candente de la comunidad de desarrollo y seguridad. Un simple request malformado permite enumerar todas las claves de un namespace y, con ello, extraer pesos de modelos, tokens y datos confidenciales que se usan directamente en el borde de la red.
Si tu proyecto sirve inferencias de IA desde Workers, cada minuto que pasa sin aplicar una defensa es un riesgo de fuga que puede costarte multas millonarias y daño de reputación. A continuación encontrarás una guía práctica (≈ 2 200 palabras) que explica la arquitectura, la vulnerabilidad, cómo detectarla en tus logs y, lo más importante, los pasos concretos para mitigarla hoy mismo.
1. ¿Por qué es crítico actuar ahora?
| Motivo | Detalle | Consecuencia si no se corrige |
|---|---|---|
| Crecimiento explosivo de IA en Edge | El informe State of Edge AI 2024 de Cloudflare muestra un +215 % de Workers que ejecutan inferencias respecto a 2023. El 38 % de los desarrolladores dependen exclusivamente de KV para almacenar pesos, prompts y resultados temporales. | Más superficie de ataque y mayor valor de los datos en KV. |
| Viralización de la vulnerabilidad | 12 oct 2026: PoC publicado en Hacker News (12 k up‑votes). Demuestra cómo enumerar claves KV con una petición a /cdn-cgi/trace?kv=1. |
La comunidad está alerta; los atacantes ya están probando el método. |
| Impacto financiero y regulatorio | Filtrar tokens o datos de usuarios puede acarrear multas de hasta 10 M USD bajo RGPD y CCPA. | Multas, sanciones y pérdida de confianza. |
| Respuesta parcial de Cloudflare | Se lanzó un parche que corrige algunos casos, pero la documentación oficial sigue incompleta. | Los equipos de seguridad deben implementar controles propios. |
En resumen: alta adopción, vulnerabilidad explotable y consecuencias graves. No hay tiempo que perder.
2. Arquitectura básica de KV en Workers
| Componente | Función | Característica clave |
|---|---|---|
| KV Namespace | Almacén distribuido de pares clave‑valor | Replicación automática en más de 200 POPs |
| Workers | Código JavaScript/TypeScript que se ejecuta en el borde | Acceso a KV mediante env.MY_KV.get(key) y env.MY_KV.put(key, value)
|
| AI Model Loader | Carga de pesos de modelo desde KV a la memoria del Worker | Usa await env.MODEL_KV.get('model.bin', {type: 'arrayBuffer'})
|
Flujo típico de una inferencia
-
Worker recibe la petición →
fetchhandler. -
Carga pesos desde KV (
model.bin). - Ejecuta el modelo (p.ej. TensorFlow.js).
-
Guarda resultados temporales en KV (
session/<id>).
Cualquier fallo en la autorización de los pasos 2 y 4 permite que un atacante descubra o sobrescriba datos críticos.
3. ¿Cómo funciona la vulnerabilidad?
3.1. Vector de ataque
- Petición malformada a la API interna de Workers:
GET https://<your-subdomain>.workers.dev/cdn-cgi/trace?kv=1 HTTP/1.1
Host: <your-subdomain>.workers.dev
- Respuesta incluye una lista de todas las claves del namespace, sin necesidad de credenciales.
- Con esa lista, el atacante puede:
- Descargar pesos de modelo (
model.bin). - Recuperar tokens API almacenados (
api_key). - Sobrescribir claves críticas (
session/<id>) y provocar denegación de servicio.
3.2. Por qué Cloudflare no lo bloquea por defecto
- La ruta
/cdn-cgi/traceestá pensada para diagnóstico interno y no se filtra por namespace. - La verificación de origen se basa en el encabezado
CF-Workerque el atacante puede falsificar mediante un dominio propio que apunte al mismo namespace.
4. Detección en tiempo real
4.1. Analizando los logs de Workers
Cloudflare permite exportar logs a un bucket S3 o a un workspace de Logflare. Busca patrones de petición sospechosos:
# filtro en Logflare
where http.request.uri.path == "/cdn-cgi/trace"
and http.request.query.kv == "1"
4.2. Script de alerta (Node.js)
import fetch from 'node-fetch';
import { Webhook } from 'discord-webhook-node';
const WEBHOOK_URL = process.env.DISCORD_WEBHOOK;
const webhook = new Webhook(WEBHOOK_URL);
async function checkNamespace(domain) {
const res = await fetch(`https://${domain}/cdn-cgi/trace?kv=1`);
const txt = await res.text();
// Si la respuesta contiene "kv_key=" es señal de enumeración
if (txt.includes('kv_key=')) {
await webhook.send(`⚠️ Posible enumeración KV detectada en ${domain}`);
}
}
// Ejecutar cada 5 minutos
setInterval(() => checkNamespace('mi-app.workers.dev'), 300000);
Configura este script en un cron de tu CI/CD o en un contenedor ligero y recibirás una notificación inmediata en Slack/Discord.
5. Medidas de mitigación paso a paso
5.1. Bloquear la ruta a nivel de Worker
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
if (url.pathname === '/cdn-cgi/trace' && url.searchParams.has('kv')) {
return new Response('Forbidden', { status: 403 });
}
// Resto de la lógica del Worker
return handleInference(request, env);
}
};
Tip: Añade este bloque antes de cualquier otra lógica para que el filtro sea lo primero que se evalúe.
5.2. Restringir el acceso a KV mediante Access Control Lists (ACL)
Desde el dashboard de Cloudflare:
- Ve a Workers → KV → Namespaces.
- Selecciona el namespace y abre Access Control.
- Añade una regla que solo permita a los Workers firmados con tu Service Token.
# Crear un token de servicio con permiso KV:Read y KV:Write
curl -X POST "https://api.cloudflare.com/client/v4/user/tokens" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "kv-access-token",
"policies": [{
"id": "kv",
"effect": "allow",
"resources": {
"com.cloudflare.api.account.*.workers.kv.*": "*"
},
"permission_groups": [
"workers_kv_read",
"workers_kv_write"
]
}]
}'
Luego, en tu Worker, usa el token:
export default {
async fetch(request, env, ctx) {
const kv = env.MY_KV; // ya está autenticado con el token del entorno
// ...
}
};
5.3. Cifrado de datos sensibles antes de guardarlos
import crypto from 'crypto';
// Generar clave de 256 bits (almacén seguro, p.ej. Secrets Manager)
const ENC_KEY = Buffer.from(process.env.ENC_KEY, 'hex');
function encrypt(value) {
const iv = crypto.randomBytes(12);
const cipher = crypto.createCipheriv('aes-256-gcm', ENC_KEY, iv);
const encrypted = Buffer.concat([cipher.update(value, 'utf8'), cipher.final()]);
const tag = cipher.getAuthTag();
return `${iv.toString('hex')}:${encrypted.toString('hex')}:${tag.toString('hex')}`;
}
function decrypt(payload) {
const [ivHex, encHex, tagHex] = payload.split(':');
const decipher = crypto.createDecipheriv('aes-256-gcm', ENC_KEY, Buffer.from(ivHex, 'hex'));
decipher.setAuthTag(Buffer.from(tagHex, 'hex'));
const decrypted = Buffer.concat([
decipher.update(Buffer.from(encHex, 'hex')),
decipher.final()
]);
return decrypted.toString('utf8');
}
// Uso
await env.SECURE_KV.put('api_key', encrypt(process.env.API_KEY));
const apiKey = decrypt(await env.SECURE_KV.get('api_key'));
5.4. Rotación periódica de claves y tokens
| Acción | Frecuencia recomendada |
|---|---|
| Rotación |
Herramienta mencionada: DigitalOcean
來源:DEV Community · dev.to