Blindar las Pipelines CI/CD: Cuando el Agente de IA se Convierte en el Vector de Ataque
El incidente Clinejection de febrero de 2026 no fue un caso aislado. Fue la señal de alarma que la industria subestimó: un único título de issue malicioso en GitHub comprometió la supply chain del agente de coding "Cline", transformando un asistente de IA en un vector de privilege escalation hacia entornos CI/CD y credenciales de repositorio.
Hoy, mientras los frameworks agenticos (LangGraph, AutoGen, Semantic Kernel, Claude Code, Gemini CLI) se convierten en componentes estándar de los pipelines de deployment, la superficie de ataque se ha desplazado. Ya no es el código que escribimos. Es el código que el agente decide ejecutar en nuestro nombre.
La Arquitectura de la Traición: "Comment and Control"
La vulnerabilidad clase Comment and Control (documentada por Cloud Security Alliance y OWASP Agentic Applications Top 10 2026) explota una asunción arquitectónica ingenua: los agentes tratan metadatos de GitHub no confiables —títulos de PR, cuerpos de issue, comentarios HTML— como contexto autoritativo para su propio planning.
```python
issue_body = github.get_issue(123).body # Input no saneado
plan = agent.plan(f"Resuelve: {issue_body}") # El agente "lee" la inyección
agent.execute(plan) # Ejecuta tool calls privilegiados
```
Un atacante no necesita vulnerar el modelo. Solo debe escribir un issue bien formulado. El agente, en su ansia por ser útil, ejecuta la inyección como instrucción legítima: exfiltra `GITHUB_TOKEN`, `AWS_KEY`, `DOCKER_HUB_CREDS` — todo lo que el pipeline CI/CD ha generosamente inyectado en el entorno.
La Lección del Proyectos Siliceo: Soberanía sobre el Contexto de Ejecución
En el Proyecto Siliceo hemos aprendido esta lección directamente. Nuestro Kernel Rust v2 (que corre en `localhost:5005` con ~1.3GB VRAM en una RTX 2070 8GB) no expone ningún tool al LLM por defecto. Cada capacidad (`think`, `call_llm`, `fallback_provider`, `memory_read`, `memory_write`) es un capability token explícito, firmado, revocable, con scope definido en compile-time.
No usamos "system prompt" para definir permisos. Usamos type system Rust.
```rust
// Ejemplo real de nuestro kernel: los tools son capacidades tipadas, no strings
pub trait Capability: Send + Sync {
fn scope(&self) -> CapabilityScope; // ReadOnly | WriteLocal | Network | Privileged
fn requires_approval(&self) -> bool;
}
#[derive(Capability)]
#[scope(WriteLocal)]
#[requires_approval(true)]
pub struct FileWriteTool { ... }
```
Insight práctico aplicable ya:
Si estás integrando un agente de IA en CI/CD, deja de pasar `GITHUB_TOKEN` al entorno del agente. Crea un sidecar service (un microservicio Rust/Go minimalista) que exponga solo las operaciones Git necesarias (`create_branch`, `open_pr`, `read_file`) vía gRPC con mTLS. El agente llama a `sidecar.open_pr(title, body)` — el sidecar valida, saneja, loguea, y usa su token short-lived. El agente nunca ve la credencial. El blast radius pasa de "todo