Mengizinkan LLM atau autonomous agent memicu tool execution di backend membuka risiko keamanan baru: prompt injection yang berujung pada privilege escalation dan kebocoran credential eksternal. Ketika agent diberi akses ke integrasi pihak ketiga (misalnya GitHub API, database, atau penyedia cloud), memberikan long-lived token dengan izin luas merupakan kesalahan fatal.

Untuk membatasi blast radius dari manipulasi model AI, arsitektur backend harus menerapkan zero-trust pada interface tool. Artikel ini membahas hardening sistem melalui tiga lapisan: validasi skema input deterministik, pertukaran credential menjadi ephemeral token berbasis scope minimal, dan validasi runtime policy melalui middleware terisolasi.

Vektor Serangan pada Tool Execution Agent

Saat agent mengorkestrasi kode atau tugas otomasi software engineering, payload tool tidak boleh dianggap tepercaya. Dua ancaman utama meliputi:

  • Privilege Escalation: Prompt injection memanipulasi model untuk memanggil skill berizin tinggi (misalnya: mengubah izin deployment dari read-only menjadi admin write).
  • Secret Exposure: Agent meneruskan credential global atau master API key ke context window model atau log eksekusi saat integrasi eksternal gagal.

Solusinya adalah memperlakukan agent sebagai client untrusted dan membatasi eksekusi menggunakan ephemeral downscoped tokens.

Arsitektur Hardening: Token Downscoping & Policy Enforcement

Pola paling aman mengandalkan backend broker. Model hanya menerima run-scoped context ID. Ketika agent memutuskan memanggil tool, ia mengirim permintaan ke backend controller. Backend menukar identitas agent menjadi ephemeral token dengan TTL sangat singkat (misalnya 60 detik) yang hanya memiliki scope untuk resource target.

Agent Request -> Backend Execution Gateway -> Policy Engine -> Ephemeral Token Minting -> Tool Runner

Implementasi: Validasi Skema & Middleware Otorisasi

Contoh berikut menggunakan TypeScript dan Node.js (Express) dengan validasi runtime menggunakan Zod dan penegakan policy berbasis scope.

1. Validasi Input Skema Ketat

Cegah manipulasi parameter dengan memvalidasi payload sebelum menyentuh logic eksekusi tool.

import { z } from 'zod';

export const DeployToolSchema = z.object({
  environment: z.enum(['staging', 'production']),
  commitSha: z.string().regex(/^[0-9a-f]{40}$/, 'Invalid git commit SHA'),
  targetService: z.string().min(1).max(64),
  dryRun: z.boolean().default(false),
}).strict(); // Tolak field asing yang disuntikkan via LLM

export type DeployToolInput = z.infer<typeof DeployToolSchema>;

2. Middleware Autentikasi & Policy Enforcement

Middleware ini memvalidasi token sesi agen, mengecek izin tool terhadap context user/task, dan menginjeksi downstream token khusus (downscoped credentials) ke handler eksekusi.

import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';

interface AgentTokenPayload {
  agentId: string;
  runId: string;
  allowedSkills: string[];
}

export function enforceSkillPolicy(requiredSkill: string) {
  return async (req: Request, res: Response, next: NextFunction) => {
    const authHeader = req.headers.authorization;
    if (!authHeader?.startsWith('Bearer ')) {
      return res.status(401).json({ error: 'Missing or malformed authorization header' });
    }

    const token = authHeader.split(' ')[1];
    const secret = process.env.AGENT_SIGNING_KEY;
    if (!secret) throw new Error('AGENT_SIGNING_KEY not configured');

    try {
      const decoded = jwt.verify(token, secret, {
        algorithms: ['HS256'],
        clockTolerance: 5,
      }) as AgentTokenPayload;

      // Least Privilege Check
      if (!decoded.allowedSkills.includes(requiredSkill)) {
        return res.status(403).json({
          error: 'Access denied: agent run lacks permission for this skill',
          skill: requiredSkill,
        });
      }

      // Mint ephemeral downstream token khusus skill ini (TTL: 60 detik)
      const ephemeralDownstreamSecret = jwt.sign(
        {
          sub: decoded.agentId,
          runId: decoded.runId,
          scope: requiredSkill,
        },
        process.env.INTERNAL_TOOL_SECRET!,
        { expiresIn: '60s' }
      );

      // Teruskan credential ephemeral ke context handler
      res.locals.agentContext = {
        agentId: decoded.agentId,
        runId: decoded.runId,
        ephemeralToken: ephemeralDownstreamSecret,
      };

      next();
    } catch (err) {
      return res.status(401).json({ error: 'Invalid or expired agent token' });
    }
  };
}

3. Route Handler dengan Eksekusi Terisolasi

import { Router } from 'express';
import { DeployToolSchema } from './schemas';
import { enforceSkillPolicy } from './middleware';

const router = Router();

router.post(
  '/api/v1/skills/deploy',
  enforceSkillPolicy('skills:deploy:staging'),
  async (req, res) => {
    // 1. Validasi input deterministik
    const parseResult = DeployToolSchema.safeParse(req.body);
    if (!parseResult.success) {
      return res.status(400).json({
        error: 'Validation failed',
        details: parseResult.error.flatten(),
      });
    }

    const { ephemeralToken, runId } = res.locals.agentContext;
    const validatedPayload = parseResult.data;

    // 2. Eksekusi tool menggunakan ephemeral token, bukan global API key
    try {
      const result = await executeDeploymentWorker(validatedPayload, ephemeralToken);
      return res.status(200).json({ status: 'queued', runId, result });
    } catch (error: any) {
      // 3. Sanitasi output error agar credential downstream tidak bocor ke context LLM
      return res.status(500).json({
        error: 'Deployment execution failed',
        message: error.message || 'Internal executor error',
      });
    }
  }
);

async function executeDeploymentWorker(payload: any, token: string) {
  // worker memvalidasi token scoped dan mengeksekusi integrasi
  return { deploymentId: 'dep-98213' };
}

export default router;

Trade-offs dan Pertimbangan Runtime

  • Latency vs. Security: Minting token ephemeral dan validasi Zod menambahkan overhead latensi sekitar 5–15ms per invocation. Ini sepadan untuk mencegah kebocoran credentials jangka panjang.
  • State vs. Stateless: Menggunakan asymmetric signing (misalnya RS256 atau Ed25519) lebih baik daripada symmetric HS256 jika tool runners terdistribusi di infrastructure berbeda tanpa akses ke private key utama.
  • Output Sanitization: Selalu sanitasi return value dan error stack trace. Jika third-party API mengembalikan HTTP 401/403 yang menyertakan header authorization di body debug, hapus sebelum payload dikirim kembali ke agent context.