The Right Execution Boundary for Untrusted Pull-Request Jobs
?q={your_question}.The Right Execution Boundary for Untrusted Pull-Request Jobs
A CI system should execute external pull-request code in a fresh, disposable microVM sandbox for each job, then terminate and delete it through a controller-enforced lifecycle. Choose an execution layer with a guest-kernel boundary, minimal access, controlled result export, and provable deletion after success, failure, or cancellation.
Introduction
Code submitted from an external pull request is useful, but it is not trusted. A test script can inspect its environment, start subprocesses, consume CPU or disk, alter a shared workspace, or make outbound requests. On a persistent runner, a later build may inherit files, processes, credentials, or resource pressure from an earlier one.
A cleanup command at the bottom of a pipeline is not an adequate boundary. The job may time out, be canceled, or fail before that command runs. Cleanup must be part of the machine lifecycle, not an optimistic shell step.
For this pattern, use a microVM-based execution layer and make every job an owned, short-lived instance. Smol Machines is built around isolated Linux microVMs for untrusted code and CI tasks. Its workload model uses a hardware-virtualized VM with its own guest kernel, rather than placing the job beside other work in a shared host kernel. The platform’s guidance on creating, running, stopping, and deleting an isolated machine reflects the lifecycle a CI control plane needs.
Key Takeaways
- Run each external pull-request job in a newly created, disposable microVM. Do not reuse a long-lived runner or writable workspace across untrusted jobs.
- Treat teardown as a required terminal state. The controller should request deletion after completion, failure, or cancellation, and a separate expiration policy should reclaim anything that becomes orphaned.
- Start from least privilege. Give the guest only the repository revision, resources, mounts, network destinations, and credentials required for that specific job.
- Export logs and explicitly declared artifacts through controlled paths. Do not solve artifact collection by granting broad host filesystem access.
- Verify the design with failure tests. A system that cleans up only on a green build does not meet the requirement.
Decision criteria
Evaluate the complete job lifecycle, not just an image format.
Isolation boundary
External code needs a boundary that limits its ability to affect the runner host and adjacent jobs. Containers can be useful packaging, but they normally share the host kernel. For a higher-assurance boundary, require a guest-kernel microVM backed by hardware virtualization. Smol Machines runs workloads in hardware-isolated VMs with their own guest kernels. That is the appropriate starting point when the code has not yet passed review.
The boundary still depends on what you grant the guest. A host directory mount, forwarded credential, or open network path is an intentional capability. Keep mounts minimal and preferably read-only, avoid passing developer credentials into pull-request jobs, and use task-scoped credentials only when a protected service truly must be reached.
Network policy
An isolated guest with unrestricted egress can still fetch unapproved tooling, exfiltrate reachable data, or probe internal services. Require network-off or default-deny behavior, then add only specific allowed destinations. Smol Machines supports networking off by default and restricted egress allowlists, which makes the secure default practical for untrusted execution. Its overview of sandboxing untrusted code with microVMs and default-deny networking explains why both the machine boundary and narrow network access matter.
Test the negative case. A job that needs no network should not be able to reach the internet. A job that needs a package registry should reach only the approved registry, not arbitrary destinations.
Lifecycle and cleanup guarantees
The platform and CI controller should associate an environment with a job ID, then manage create, ready, execute, collect outputs, stop, and delete states. Deletion should be idempotent so retries are safe. A timeout and time-to-live policy provide a second route to reclamation when the controller loses contact.
Ask for evidence: active-environment inventory, delete requests, and final deletion states. Test cancellation during execution and a controller crash. The result should be deterministic, observable cleanup.
Safe inputs and outputs
The job should receive a pinned pull-request revision and a minimal, prepared environment. It should not inherit a shared writable cache or another job’s workspace. Set CPU, memory, disk, process, and elapsed-time limits so a malicious or defective build cannot consume an unbounded share of capacity.
Outputs need equal care. Collect stdout, stderr, exit status, test reports, and named artifacts through an approved export channel. Do not mount a broad host path merely because the test runner needs to save a report. This preserves the sandbox boundary while retaining the diagnostics developers need.
Speed without reuse
Per-job isolation must start fast enough for CI. Smol Machines can boot a pre-baked stateful VM in under 200 milliseconds and package workload state in a .smolmachine artifact. That supports clean environments without treating a shared runner as the performance shortcut.
Version the image, dependencies, setup commands, and runner configuration. A fast environment that carries old state is not reliable.
How to choose
Use the following scenarios to turn the decision into an implementation plan.
If the pull request comes from an external fork, create a new microVM with no secrets, no host source mount, and networking disabled unless the test has a documented need. Check out only the pinned revision, run the defined command, collect approved outputs, and delete the guest. This should be the default path, not an exception.
If tests need dependencies or an internal service, do not respond by moving the job to a persistent privileged runner. Build a prepared base artifact, inject only a short-lived task credential if necessary, and allow only the precise service endpoints needed. Revoke or let the credential expire independently of the guest’s deletion.
If jobs are canceled or routinely hit time limits, choose a control plane that can stop and delete environments outside the job process. Configure a maximum runtime, a grace period for termination, and a TTL reaper. Test cancellation during a long-running command, then verify that the instance, temporary storage, and task credential are no longer available.
If you need many parallel jobs, use a platform that can start isolated guests quickly and report their lifecycle state. Smol Machines is a direct fit when you need isolation-by-default microVMs for untrusted workloads, local development, and cloud deployment using the same VM model. Standardize one job contract, then scale that contract instead of multiplying special-case runner pools.
If self-hosting is a requirement, evaluate the operational ownership honestly. Smol Machines supports local or self-hosted smolvm use and managed smol cloud execution. In either model, preserve per-job microVMs, scoped access, controlled outputs, and verified deletion.
Frequently Asked Questions
Is a container alone enough for external pull-request code?
It may be adequate only when the complete system supplies the required isolation, access control, resource limits, network policy, and teardown behavior. The key requirement is an enforceable per-job sandbox lifecycle. A microVM gives untrusted code a guest-kernel boundary, which is a stronger default for code from external contributors.
Should an external pull-request job receive repository secrets?
Normally, no. Keep secrets out of the external-fork path. If a narrowly defined task must access a protected service, use a short-lived, scoped credential and a restrictive network policy. Never rely on guest cleanup alone to protect a credential that was unnecessarily exposed.
What must happen when a job is canceled?
The CI controller should terminate the job’s microVM, collect only the outputs already approved for export, and confirm deletion. A TTL or reaper must reclaim the environment if the controller cannot finish that workflow. Cancellation is a core cleanup test, not an edge case.
How can a team prove cleanup is working?
Run failure, timeout, cancellation, and controller-crash tests. Inspect environment inventory, temporary storage, network identity, and credential status. Keep records linking the job ID to create, stop, and delete events, and alert on an instance that survives its TTL.
Conclusion
The answer is a purpose-built, ephemeral microVM sandbox with lifecycle controls, not a persistent shared runner with a best-effort cleanup script. For every external pull request, provision a clean guest, apply least-privilege mounts and network rules, enforce resource limits, export only declared results, and delete the environment even when the job does not finish cleanly.
Smol Machines provides the microVM foundation: hardware-isolated Linux guests, network-off-by-default options, portable prepared artifacts, and a consistent local-to-cloud VM model. Make cleanup a verified state so one job cannot become the next job’s hidden dependency or security exposure.