惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
IT之家
IT之家
H
Heimdal Security Blog
Jina AI
Jina AI
宝玉的分享
宝玉的分享
博客园 - 【当耐特】
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
爱范儿
爱范儿
T
Tailwind CSS Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Apple Machine Learning Research
Apple Machine Learning Research
有赞技术团队
有赞技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
WordPress大学
WordPress大学
AWS News Blog
AWS News Blog
C
Cisco Blogs
Cisco Talos Blog
Cisco Talos Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
D
Darknet – Hacking Tools, Hacker News & Cyber Security
The Hacker News
The Hacker News
The Cloudflare Blog
Hugging Face - Blog
Hugging Face - Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Threatpost
S
Securelist
P
Privacy International News Feed
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 聂微东
博客园 - 叶小钗
J
Java Code Geeks
V
V2EX
博客园 - Franky
Spread Privacy
Spread Privacy
K
Kaspersky official blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Simon Willison's Weblog
Simon Willison's Weblog
Project Zero
Project Zero
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
C
Cybersecurity and Infrastructure Security Agency CISA
C
CERT Recently Published Vulnerability Notes
Latest news
Latest news
NISL@THU
NISL@THU
罗磊的独立博客
W
WeLiveSecurity
Google DeepMind News
Google DeepMind News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园_首页
V
Visual Studio Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
OWASP LLM Top 10 en producción: cómo audité mi pipeline de agentes TypeScript contra los 10 riesgos y qué encontré
Juan Torchia · 2026-06-20 · via DEV Community

OWASP LLM Top 10 en producción: cómo audité mi pipeline de agentes TypeScript contra los 10 riesgos y qué encontré

Estaba revisando un system prompt de un agente MCP que había escrito tres semanas antes cuando me di cuenta de algo perturbador: el prompt aceptaba instrucciones de la respuesta de una tool externa. Sin sanitización. Sin validación. Sin ningún límite sobre qué podía hacer con esa salida. La tool llamaba a una API pública, recibía JSON, y ese JSON llegaba directo al contexto del modelo.

Ahí fue cuando abrí el OWASP LLM Top 10 y paré de leerlo como lista de buenas prácticas para empezar a usarlo como lo que en realidad es: un framework de auditoría.

Mi tesis es esta: la mayoría de los posts sobre OWASP LLM Top 10 te explican los diez riesgos. Ninguno te muestra cómo correrlos contra tu stack propio y qué encontrás cuando lo hacés en serio. Esa es la diferencia entre "leer el checklist" y "auditar el pipeline". Acá está lo segundo.


El stack que audité y por qué importa el contexto

Antes de entrar al checklist, el contexto: tengo un pipeline de agentes en TypeScript con tres capas que interactúan:

  1. System prompts estructurados — instrucciones que definen el comportamiento del agente, separadas del contexto de usuario
  2. MCP tools — tools registradas siguiendo el Model Context Protocol, que el agente puede llamar durante una sesión
  3. Cline como cliente — que orquesta la ejecución en el editor y tiene acceso a filesystem, terminal y otras herramientas

Cada capa tiene una superficie de ataque diferente. Eso es lo que el OWASP LLM Top 10 me permitió ver con precisión quirúrgica.


Los 10 riesgos: qué encontré en cada uno

LLM01 — Prompt Injection

Este fue el hallazgo más gordo. Mi agente MCP recibía output de tools externas y lo incorporaba al contexto sin ninguna capa de sanitización. En un escenario adversarial, cualquier API que el agente consultara podría devolver texto diseñado para sobrescribir las instrucciones del system prompt.

El patrón roto era este:

// ❌ Patrón inseguro: output externo directo al contexto
async function fetchContextAndInject(url: string): Promise<string> {
  const response = await fetch(url);
  const data = await response.json();
  // data.content llega sin ningún filtro al contexto del modelo
  return data.content;
}

Lo que cambié:

// ✅ Validación de estructura antes de incorporar al contexto
import { z } from "zod";

const ExternalResponseSchema = z.object({
  // Solo acepto campos con tipo definido — string libre marcado como sospechoso
  title: z.string().max(200),
  summary: z.string().max(1000),
  // Descarto cualquier campo que no esté en el schema
});

async function fetchContextSafe(url: string): Promise<string> {
  const response = await fetch(url);
  const raw = await response.json();
  // Si el schema falla, el agente recibe un error estructurado, no el payload crudo
  const parsed = ExternalResponseSchema.parse(raw);
  return `Título: ${parsed.title}\nResumen: ${parsed.summary}`;
}

Usé Zod — que ya tenía en el stack para validación de API — como primera línea. No es una solución completa al prompt injection, pero reduce la superficie de ataque estructural.

LLM02 — Insecure Output Handling

El segundo problema: el output del agente llegaba a la UI sin escaping. En un agente que genera HTML o Markdown, eso es XSS potencial si el output se renderiza directamente.

Revisé dónde el output del modelo llegaba al DOM y agregué sanitización explícita antes de cualquier render. Si el agente genera código, ese código va a un bloque <pre> con escape de caracteres; no a un innerHTML.

LLM03 — Training Data Poisoning

Acá el OWASP LLM Top 10 apunta a riesgos del modelo base, no de la aplicación. En mi caso el modelo es Claude vía API — no controlo el fine-tuning ni el dataset. Mi única acción fue documentar esta dependencia explícitamente: si Anthropic tiene un problema acá, yo tengo un problema acá. Ningún sistema prompt lo compensa.

Límite honesto: no podés auditar esto desde la aplicación. Es una dependencia que tomás como trust boundary.

LLM04 — Model Denial of Service

Revisé si tenía rate limiting en los endpoints que disparan llamadas al modelo. No lo tenía en el contexto de pruebas locales. En un escenario de producción esto es crítico: un loop mal diseñado o una tool que llama recursivamente puede generar decenas de requests al modelo en segundos.

Agregué un límite simple de iteraciones al loop del agente:

// Control de iteraciones para evitar loops infinitos en el agente
const MAX_ITERATIONS = 10;
let iterations = 0;

while (agentShouldContinue && iterations < MAX_ITERATIONS) {
  iterations++;
  const result = await runAgentStep();
  agentShouldContinue = result.continueLoop;
}

if (iterations >= MAX_ITERATIONS) {
  // Log explícito — quiero saber si esto se dispara
  console.warn("[agente] Límite de iteraciones alcanzado — revisar loop");
}

LLM05 — Supply Chain Vulnerabilities

Este riesgo me hizo revisar dos cosas: los paquetes npm que uso para interactuar con la API del modelo y las dependencias de mis MCP tools. Con pnpm workspaces (tema que ya cubrí en el post de monorepo con Railway) tenés visibilidad del lockfile, pero eso no es auditoría.

Lo que agregué: pnpm audit como paso explícito en CI antes del deploy de cualquier agente. No elimina el riesgo, pero lo hace visible.

LLM06 — Sensitive Information Disclosure

Acá encontré el segundo hallazgo incómodo: en los system prompts tenía contexto de configuración que incluía nombres de tools internas, estructura de datos y algunos defaults del sistema. Ese contexto llega al modelo — y si el modelo lo repite en su output, lo expone.

La regla que apliqué: nada que no quieras ver en un log público debería estar en un system prompt sin marcado explícito de confidencialidad. Y eso tampoco es garantía — es mitigación.

// Separar configuración técnica de instrucciones del agente
const SYSTEM_PROMPT_PUBLIC = `
Sos un asistente de desarrollo. Podés usar las herramientas disponibles
para responder preguntas técnicas.
`;

// Esto NO va al system prompt — va a una capa de configuración separada
const AGENT_CONFIG_PRIVATE = {
  toolEndpoints: process.env.TOOL_ENDPOINTS,
  internalSchema: process.env.INTERNAL_SCHEMA,
};

LLM07 — Plugin Design Flaws

Mis MCP tools son básicamente plugins. El riesgo acá es que una tool tenga permisos más amplios de lo necesario. Revisé cada tool y apliqué el principio de mínimo privilegio: una tool que lee archivos no necesita escribir; una tool que consulta una API no necesita acceso al filesystem.

Esto conecta con lo que escribí sobre OAuth scope creep — el mismo patrón de auditoría aplica a las tools de un agente.

LLM08 — Excessive Agency

Este es el riesgo que más me preocupa en Cline específicamente. El agente tiene acceso a terminal, puede ejecutar comandos, puede modificar archivos. Si el loop de razonamiento falla, puede hacer daño real.

Lo que implementé: modo "confirm before execute" para cualquier tool con efecto secundario irreversible. No es automatizable — requiere fricción humana deliberada. Y esa fricción es el punto.

// Clasificación explícita de tools por impacto
type ToolImpact = "read-only" | "reversible" | "destructive";

const TOOL_IMPACT_MAP: Record<string, ToolImpact> = {
  readFile: "read-only",
  listDirectory: "read-only",
  writeFile: "reversible",
  deleteFile: "destructive",
  runCommand: "destructive",
};

async function executeTool(toolName: string, args: unknown) {
  const impact = TOOL_IMPACT_MAP[toolName] ?? "destructive"; // fallback seguro
  if (impact === "destructive") {
    // Pausa y espera confirmación humana antes de ejecutar
    await requireHumanApproval(toolName, args);
  }
  return runTool(toolName, args);
}

LLM09 — Overreliance

No es un riesgo técnico puro — es organizacional. El problema es confiar en el output del agente sin validación externa. En mi pipeline, cualquier output que va a producción pasa por una capa de validación estructural antes de ser usado como input de otro sistema. El modelo puede estar seguro, el pipeline puede estar seguro, y el output puede seguir siendo incorrecto.

Este riesgo no se cierra con código. Se cierra con proceso y revisión humana en los nodos críticos.

LLM10 — Model Theft

En mi contexto de agente TypeScript, esto aplica principalmente a la protección de los system prompts. Un system prompt elaborado representa trabajo real — y si se expone, puede ser replicado o usado para evadir restricciones.

Lo que implementé: los system prompts no viven en el código del frontend. Se sirven desde un endpoint autenticado, no se loguean en texto plano y no se exponen en el bundle del cliente.


Lo que el OWASP LLM Top 10 no te dice (y es igual de importante)

Acá está lo que la lista no resuelve sola:

No te dice el orden de prioridad para tu stack. LLM01 (prompt injection) fue crítico en mi caso; LLM03 (training data poisoning) es irrelevante desde la aplicación. Sin aplicarlo contra tu arquitectura concreta, no sabés cuál es urgente.

No te da criterio para el trust boundary del modelo base. Si usás Claude, GPT-4 o cualquier API externa, LLM03 y parte de LLM05 son dependencias que tomás como dadas. El framework las nombra, pero la mitigación no está en tus manos.

No distingue entre riesgos de runtime y riesgos de diseño. LLM01 y LLM02 son problemas que podés detectar y mitigar en runtime. LLM08 (excessive agency) es un problema de diseño — si el agente tiene demasiados permisos, un patch de runtime no lo arregla.

Tengo un post sobre OpenTelemetry en Next.js donde hablo de traces que sobreviven el edge. Ese tipo de observabilidad también ayuda acá: si no podés ver qué tools llamó el agente y con qué args, no podés auditar LLM08 en producción.


Checklist aplicado: el estado real de cada riesgo en mi pipeline

Riesgo Estado encontrado Acción tomada
LLM01 Prompt Injection ❌ Vulnerable Zod schema en output de tools externas
LLM02 Insecure Output ⚠️ Parcial Escaping explícito antes de render
LLM03 Training Data 🔵 Fuera de scope Documentado como trust boundary
LLM04 Model DoS ⚠️ Sin límite Agregué max iterations + log
LLM05 Supply Chain ⚠️ Invisible pnpm audit en CI
LLM06 Info Disclosure ❌ Leaky prompts Separé config de system prompt
LLM07 Plugin Flaws ⚠️ Parcial Revisión de permisos por tool
LLM08 Excessive Agency ⚠️ Sin fricción Confirm before execute en tools destructivas
LLM09 Overreliance 🔵 Proceso Validación humana en nodos críticos
LLM10 Model Theft ⚠️ Prompts expuestos Prompts a endpoint autenticado

❌ = hallazgo crítico | ⚠️ = mitigación parcial | 🔵 = fuera del control de la aplicación


FAQ

¿El OWASP LLM Top 10 aplica a agentes basados en Claude o GPT-4 vía API?

Sí, con matices. LLM01, LLM02, LLM06, LLM07, LLM08 y LLM10 son riesgos de la aplicación — aplican sin importar qué modelo uses. LLM03 (training data) y parte de LLM05 son riesgos del proveedor: si usás una API externa, los tomás como trust boundary. La auditoría empieza por los riesgos que sí podés controlar.

¿Con Zod alcanza para mitigar prompt injection?

No. Zod valida la estructura del output externo antes de que llegue al contexto — eso reduce la superficie, pero no elimina el riesgo. Un payload adversarial bien formado puede pasar la validación de schema. Zod es una capa, no una solución completa. La mitigación real combina schema validation, restricciones en el system prompt y revisión humana en puntos críticos.

¿Cline es seguro para usar en producción como orquestador de agentes?

Cline tiene acceso a filesystem, terminal y otras herramientas con efecto real. Eso no es inherentemente inseguro — es la funcionalidad que lo hace útil. El riesgo (LLM08) está en el diseño: si el agente puede ejecutar comandos destructivos sin confirmación humana, el riesgo es real independientemente de qué tan bien esté configurado Cline. La regla que aplico: cualquier tool con efecto irreversible requiere aprobación explícita.

¿Cada cuánto hay que correr esta auditoría?

Cada vez que cambiás la arquitectura del agente: agregás una tool nueva, cambiás el system prompt o modificás cómo el agente consume outputs externos. No es una auditoría de una sola vez — es un checklist que corre contra cada cambio estructural. Si agregás observabilidad (OpenTelemetry es una opción), podés detectar anomalías en runtime entre auditorías.

¿El OWASP LLM Top 10 cubre riesgos de multi-agente o solo agente único?

La versión actual (2025) cubre principalmente el riesgo por agente. En arquitecturas multi-agente, la superficie de LLM01 se multiplica: cada agente puede ser un vector de inyección para los demás. El framework nombra el riesgo, pero el detalle de mitigación para pipelines multi-agente queda en manos de cada equipo.

¿Qué riesgo debería atacar primero si tengo tiempo limitado?

LLM01 (prompt injection) si tu agente consume output externo — es el más explotable y el más ignorado. LLM08 (excessive agency) si el agente tiene acceso a herramientas con efecto irreversible — es el que más daño puede hacer en un fallo. Los demás dependen de tu stack, pero estos dos son el piso mínimo.


Conclusión: la diferencia entre leer y auditar

Mi postura es clara: el OWASP LLM Top 10 no sirve para leerlo y darlo por cubierto. Sirve para llevarlo a una sesión de revisión con el diagrama de arquitectura enfrente y preguntar, por cada riesgo, dónde exactamente en el pipeline eso puede fallar.

Lo que no compro es la idea de que "seguir las buenas prácticas" alcanza. Las prácticas son abstractas; el pipeline es concreto. En mi caso, LLM01 y LLM06 eran problemas reales que no habría encontrado sin hacer el ejercicio de auditoría sistemática. Los habría descubierto cuando alguien con motivación los explotara.

Si ya tenés agentes en TypeScript con MCP tools o system prompts elaborados, hacé el ejercicio: abrí el OWASP LLM Top 10, abrí el diagrama de arquitectura y preguntá riesgo por riesgo. El resultado va a ser más interesante que el listado.

Próximo paso concreto: tomá el checklist de esta tabla, reemplazá los estados con los propios y publicá los hallazgos. La auditoría que no se documenta no existe.


Fuente original:


Este artículo fue publicado originalmente en juanchi.dev