AizuDemy

Tutorial Build AI Code Interpreter Lokal: Isolasi Exec Sandbox Docker & Node.js

Tutorial Build AI Code Interpreter Lokal: Isolasi Exec Sandbox Docker & Node.js
๐ŸŽง
Dengarkan Artikel Ini
Suara AI Otomatis โ€ข 6 mnt baca baca
โšก TL;DR

Poin Kunci Artikel Ini:

  • User mengirimkan permintaan instruksi analisis data atau eksekusi logika ke backend Node.js.
  • Node.js backend mengirimkan payload HTTP POST ke API Ollama pada endpoint /api/generate.
  • Engine Ollama memproses prompt dan mengembalikan respons teks berisi kode JavaScript.
๐Ÿ“‹ Daftar Isi Materi Tutup โ–ด

Latar Belakang: Risiko Remote Code Execution (RCE) Eksekusi Kode LLM

Large Language Model (LLM) seperti Llama 3 atau DeepSeek Coder menghasilkan kode program arbitrer. Eksekusi langsung sintaks mentah LLM pada OS host memicu celah keamanan Remote Code Execution (RCE). Prompt injection memanipulasi output LLM untuk menjalankan perintah berbahaya: penghapusan direktori root, pembacaan variabel lingkungan rahasia, eksekusi reverse shell, atau eksfiltrasi data jaringan internal.

Solusi mutlak: ephemeral execution sandbox. Kode berjalan di dalam container terisolasi ketat. Container spawn saat eksekusi, memproses input, mengembalikan stdout/stderr, lalu hancur. Sistem host tetap terproteksi penuh.

PERINGATAN KEAMANAN: Eksekusi kode LLM langsung pada host OS tanpa sandbox memungkinkan penyerang mengambil alih server melalui prompt injection. Penyerang dapat membaca berkas rahasia seperti .env atau SSH keys, mengeksekusi reverse shell, serta melakukan pivot ke jaringan internal host.

Prinsip Utama Ephemeral Execution Sandbox

Arsitektur keamanan sandbox wajib mematuhi lima pilar utama isolasi sistem:

  • Principle of Least Privilege: Process berjalan tanpa hak root. Akses file system dibatasi hanya pada direktori kerja eksekusi.
  • Network Isolation: Container tidak memiliki akses interface jaringan. Mencegah exfiltration data dan command-and-control (C2) callback.
  • Resource Quotas: Memory, CPU, dan process count dibatasi rigid. Mencegah Denial of Service (DoS) dan fork bomb pada host.
  • Ephemeral Lifecycle: Environment eksekusi bersifat disposable. State dihapus total setelah eksekusi selesai.
  • Syscall Restriction: Kernel System Calls dibatasi via seccomp profile. Memblokir exploit privilege escalation kernel.

Praktek Step-by-Step: Build Sandbox Ephemeral Docker & Node.js

1. Buat Image Docker Sandbox Minim Hak Akses

Buat Dockerfile berbasis distro minimalis. Buat user non-root, tetapkan environment read-only, hapus package manager tidak terpakai.

FROM node:20-alpine
RUN addgroup -S sandboxgroup && adduser -S sandboxuser -G sandboxgroup
WORKDIR /app
USER sandboxuser
CMD ["node", "execution_script.js"]

Build image Docker lokal dengan tag node-sandbox:latest:

docker build -t node-sandbox:latest .

2. Integrasi Node.js Host Controller & API Ollama

Host controller Node.js bertugas menerima prompt, memanggil Ollama API, mengekstrak sintaks kode, menulis file temporer, spawn container Docker, dan mengembalikan hasil eksekusi ke client.

const axios = require('axios');
const { exec } = require('child_process');
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');

async function generateCodeFromOllama(prompt) {
  const res = await axios.post('http://localhost:11434/api/generate', {
    model: 'codellama',
    prompt: prompt,
    stream: false
  });
  return extractCodeFromMarkdown(res.data.response);
}

function extractCodeFromMarkdown(text) {
  const match = text.match(/```(?:js|javascript)?\n([\s\S]*?)\n```/);
  return match ? match[1] : text;
}

function executeInSandbox(codeString) {
  return new Promise((resolve, reject) => {
    const executionId = crypto.randomUUID();
    const tempDir = path.join(__dirname, 'tmp');
    if (!fs.existsSync(tempDir)) fs.mkdirSync(tempDir);
    
    const filePath = path.join(tempDir, `${executionId}.js`);
    fs.writeFileSync(filePath, codeString);

    const dockerCmd = `docker run --rm \
      --network none \
      --memory 256m \
      --cpus 0.5 \
      --pids-limit 64 \
      --read-only \
      --cap-drop ALL \
      --security-opt no-new-privileges:true \
      --user sandboxuser \
      -v ${filePath}:/app/execution_script.js:ro \
      node-sandbox:latest`;

    exec(dockerCmd, { timeout: 10000 }, (error, stdout, stderr) => {
      if (fs.existsSync(filePath)) {
        fs.unlinkSync(filePath);
      }
      
      if (error) {
        if (error.killed) {
          return reject(new Error('Execution Timeout: Proses melebihi batas 10 detik'));
        }
        return resolve({ success: false, output: stderr || error.message });
      }
      resolve({ success: true, output: stdout });
    });
  });
}

3. Multi-Step Execution Sequence

  1. User mengirimkan permintaan instruksi analisis data atau eksekusi logika ke backend Node.js.
  2. Node.js backend mengirimkan payload HTTP POST ke API Ollama pada endpoint /api/generate.
  3. Engine Ollama memproses prompt dan mengembalikan respons teks berisi kode JavaScript.
  4. Parser pada Node.js mengekstrak blok kode dari format markdown.
  5. Backend Node.js membuat berkas temporer unik di dalam direktori kerja dengan izin akses terbatas.
  6. Controller Node.js menjalankan perintah docker run dengan parameter isolasi ketat.
  7. Docker Engine spawn container terisolasi, mengeksekusi kode, dan mengirimkan stream stdout/stderr kembali ke Node.js.
  8. Docker Engine menghancurkan container secara otomatis (--rm) dan Node.js menghapus berkas temporer.

Analisis Mendalam Security Flags Docker Engine

Penggunaan Docker default tidak aman untuk eksekusi untrusted code. Setiap flag pada command docker run memiliki fungsi spesifik mencegah attack vector:

  • --network none: Mematikan seluruh stack jaringan loopback dan eth0 dalam container. Mencegah reverse shell dan SSRF.
  • --memory 256m: Membatasi penggunaan RAM maksimal 256 Megabyte. Mematikan proses jika terjadi memory leak atau OOM attack.
  • --cpus 0.5: Membatasi alokasi CPU maksimal 50% dari satu core. Mencegah High CPU Utilization / DoS pada host system.
  • --pids-limit 64: Membatasi jumlah maksimum proses simultan dalam container. Mitigasi total serangan Fork Bomb.
  • --read-only: Mount root filesystem container sebagai read-only. Mencegah penulisan malware atau modifikasi binary node.
  • --cap-drop ALL: Menghapus seluruh Linux Capabilities (misal: CAP_NET_ADMIN, CAP_SYS_ADMIN, CAP_SYS_PTRACE).
  • --security-opt no-new-privileges:true: Mencegah child process mendapatkan privilege escalation via setuid atau setgid binary.
  • --user sandboxuser: Memaksa container berjalan di bawah UID non-root yang didefinisikan pada Dockerfile.

Mitigasi Serangan & Configuration Profile

1. Custom Seccomp Profile

Seccomp (Secure Computing Mode) memfilter syscall Linux ke kernel. Buat file seccomp-strict.json untuk memblokir syscall berbahaya seperti ptrace, unshare, syslog, atau reboot.

{
  "defaultAction": "SCMP_ACT_ERRNO",
  "architectures": [
    "SCMP_ARCH_X86_64",
    "SCMP_ARCH_X86",
    "SCMP_ARCH_AARCH64"
  ],
  "syscalls": [
    {
      "names": [
        "read", "write", "exit", "exit_group", "futex",
        "mmap", "mprotect", "munmap", "brk", "fstat",
        "execve", "getpid", "rt_sigaction", "rt_sigprocmask"
      ],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}

Terapkan profile seccomp saat spawn container via CLI flag:

docker run --rm --security-opt seccomp=./seccomp-strict.json node-sandbox:latest

2. Timeout Handling & Escalation Strategy

Kode buatan LLM berisiko memicu infinite loop (misal: while(true){}). Penanganan timeout dilakukan pada dua layer simultan: Node.js child_process.exec timeout options dan Docker Engine --stop-timeout flag.

const dockerCmd = `docker run --rm --stop-timeout 5 node-sandbox:latest`;

Jika batas waktu 10 detik terlampaui, Node.js mengirimkan sinyal SIGKILL ke proses Docker CLI, menghentikan eksekusi container secara paksa.

3. Cleanup Container Gantung & Temporary Files

Proses host yang mengalami crash abnormal dapat meninggalkan container mati atau berkas temporer tersisa. Jalankan background worker di server host untuk pembersihan berkala.

docker container prune --force --filter "until=30m"

Gunakan blok try...finally pada controller Node.js untuk menjamin penghapusan berkas script temporer pada disk host:

try {
  await executeInSandbox(code);
} finally {
  if (fs.existsSync(filePath)) {
    fs.unlinkSync(filePath);
  }
}

Blueprint Arsitektur Produksi & Checklist Ringkas

Arsitektur aman AI Code Interpreter lokal wajib memenuhi kriteria isolasi penuh berikut:

  • Network Isolation: Flag --network none terpasang. Container terisolasi dari LAN dan Internet.
  • Resource Limits: Memory 256MB, CPU 0.5 core, PIDs limit 64 terkonfigurasi. Host terlindung dari DoS.
  • Read-Only System: Flag --read-only aktif. Malware tidak dapat menulis ke filesystem container.
  • Non-Root User: User non-root aktif via Dockerfile dan parameter --user. no-new-privileges aktif.
  • Syscall Restriction: Custom Seccomp profile terpasang. System calls berbahaya diblokir kernel.
  • Ephemeral Lifecycle: Parameter --rm aktif. Container hancur langsung setelah process exit.

Terapkan seluruh arsitektur pertahanan berlapis di atas. System AI Code Interpreter lokal berjalan aman, responsif, dan terproteksi dari potensi eksploitasi RCE.

๐Ÿ“– Artikel Terkait