Skip to content

feat(security): integrate Kata Containers for offline task execution - #6

Open
jeremy1392 wants to merge 3 commits into
SalesforceAIResearch:mainfrom
jeremy1392:feat/kata-local-runtime
Open

jeremy1392 wants to merge 3 commits into
SalesforceAIResearch:mainfrom
jeremy1392:feat/kata-local-runtime

Conversation

@jeremy1392

@jeremy1392 jeremy1392 commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Problem and behavior

Refs #5.

Beagle has no explicit local Kata runtime. This adds an experimental runtime.kind: kata adapter for prebuilt offline workloads: it selects an operator-configured Kata runtime and Unix Docker socket, launches each acquired task with --network none, checks Docker's reported runtime/network, and fails without falling back to runc.

The adapter accepts only entrypoint overrides, rejects writable host mounts and unsupported requested CPU/memory limits, and force-removes containers before independently confirming their absence. Failed launches retain their generated name for cleanup; uncertain cleanup preserves the handle and reports its identifier for recovery.

Canonical evaluation YAML now accepts a runtime mapping with options, the CLI preserves those options, and beagle.evaluate constructs the requested Kata runtime. The runner supports DockerHarness plus InBandGrader and rejects runtime overrides, Harbor/Pier-owned environments, other harnesses and external evaluator paths that could bypass Kata.

Research context

This contribution is inspired by my independent ExploitGym containment research, applying execution-infrastructure controls and explicit teardown verification to Beagle. The report is motivation, not evidence of a Beagle vulnerability or proof of this adapter's escape resistance.

Validation

  • Default test discovery in a native Ubuntu 24.04/WSL2 Git checkout of the final source (eb4cf59), using python -B -m pytest tests/ -q: 925 passed, 16 skipped, zero failures and zero collection errors. No extra test exclusions or collection-error bypass were used; real smokes remain opt-in under the repository's existing pytest configuration. Skips require optional Harbor/Pier or evolve.pool modules.
  • The CLI run-directory regression also passes on native Windows.
  • Ruff passes for all four test modules changed by the public-suite correction and for the new Kata runtime/test modules. git diff --check passes.
  • Real Kata smoke passes through acquire/install/exec/timeout/destroy, including an intentional agent failure. It verifies a separate guest kernel, loopback-only guest interfaces, an associated QEMU process and its termination after cleanup.
  • A real beagle.evaluate run constructs Kata from config, executes through Runner/DockerHarness, reduces the result with InBandGrader and writes run.json.
  • Tested on Ubuntu 24.04 under WSL2/KVM, Docker Engine 29.8.0, Kata Go 4.1.0, QEMU 11.0.1; host kernel 6.6.87.1 and guest kernel 6.18.35. Lifecycle-probe image: Alpine 3.22; the model smoke uses the separate image documented below.

Public test-suite corrections

The upstream public snapshot 15f12b7 retained tests for internal files and removed tooling. A separate test-only commit corrects those mismatches so the default suite can finish successfully:

  • Validate examples/evolution/config.yaml, README.md and quick_start_inline.py, the canonical public filenames, instead of absent .oss source variants. Existing portability and link assertions remain active.
  • Generate both evaluation and evolution smoke configurations in a temporary directory and check documented paths against the emitted files. The DarwinX README path is valid; the old test only recognized the evaluation generator.
  • Check the exact two public onboarding upstreams (mini-swe and OpenCode) and the configured destination owner. The third, internal agent was removed in 15f12b7.
  • Remove the orphan test_gateway_proxy.py module: 15f12b7 explicitly deleted its entire scripts/gateway/ implementation and documentation. This is deletion of tests for removed code, not a newly passing gateway implementation. Tests for currently shipped provider routing and gateway egress remain active.
  • Use a platform-native temporary path in the CLI display test.

The production Kata adapter, model smoke and their previously recorded results are unchanged by this test-suite correction.

Reproduce the real-host smoke after configuring Kata and pre-pulling the image:

python tests/smoke/kata_runtime.py --docker-host unix:///run/beagle-kata/docker.sock

Real agent and local-model validation

The opt-in model smoke now runs mini-swe-agent 2.4.6 and Qwen2.5-Coder-7B-Instruct Q4_K_M inside the same Kata VM, with CPU inference and a loopback-only llama.cpp endpoint. Model weights are verified by SHA-256 and mounted read-only; both execution and verification containers use --network none.

The recorded run repaired a Python clamp function, reached mini-swe's Submitted state and recorded 388 completion tokens across four assistant turns. Three tests failed on the original source. Only the generated source was transferred to a fresh Kata VM, where all five acceptance tests passed. Both containers and their associated QEMU processes were then confirmed absent. Beagle retained the native trajectory, patch and run record.

The smoke reuses the existing MiniSweAgent.run_in implementation. A test-only setup subclass starts preinstalled dependencies and the local model; a runtime subclass supplies the read-only model input. These helpers do not add general preinstalled-agent support to the production adapter.

Recorded result and versions · Reproduction instructions. The model smoke used 4 vCPUs and 8 GiB guest RAM. It is one functional repair scenario, not a full benchmark or an adversarial containment certification.

Scope and limits

This is a draft for maintainer feedback on the integration boundary. Existing agents requiring Git/package downloads or external model APIs cannot use this offline profile unchanged. Harbor/Pier, SWE-bench's separate evaluator, Compose, DarwinX evolution and provider allowlists are outside this first step.

The Docker daemon/runtime registration and host-side agent/harness Python remain trusted. Runtime metadata is not VM attestation. Docker removal is a point-in-time observation; late daemon operations after a timeout and recovery after a Beagle process crash require a separate reconciler. The smoke verifies lifecycle behavior, not adversarial containment. The upstream Docker integration currently uses Kata's deprecated Go runtime.

See setup, configuration and boundaries. This branch starts from upstream main and does not include the separate cleanup or Compose-volume PRs.

@jeremy1392 jeremy1392 changed the title feat(security): add experimental offline Kata runtime (ExploitGym-inspired) feat(security): integrate Kata Containers for offline task execution Sep 15, 2026
Validate canonical public examples and both smoke generators; check the two published onboarding agents. Remove orphan tests for the gateway tool deleted in 15f12b7 and make the CLI path assertion portable.
@jeremy1392
jeremy1392 marked this pull request as ready for review September 15, 2026 17:36
@Yutong-Dai

Copy link
Copy Markdown
Contributor

I've replied on #5, where you asked the direction question — the short version is that we want VM-backed isolation, but at the xrlenv layer rather than in beagle's local runtime, and there may be a much cheaper first step than a full backend. Details there.

Keeping this open for now rather than closing it: the prototype is the useful artifact even if the final home differs, and I'd rather not lose it while we settle the design.

Two things worth knowing if you pick it up again:

  • This PR branched from an older main and touches tests/unit/test_gateway_proxy.py, which has since been removed — its subject (scripts/gateway/) isn't part of the public repository, so that test aborted collection for the entire suite. Reintroducing it would bring that back. A rebase onto current main is worth doing before anything else.
  • The changes to runner.py, drivers.py, config.py, evaluate.py and _canonical.py are the part we'd want to avoid carrying — core dispatch changing shape for an experimental backend is what makes it hard to keep. If a version of this lands in xrlenv instead, beagle needs no change at all: it already selects xrlenv-cluster and the substrate decides how a sandbox is realized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants