Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/edda

crates/dwarves-runa/tests/sandbox.rs

//! `Sandbox` and `Forge` steps (lane RELBUILD-RUNA, 2026-10-29): a release build is a
//! Runa pipeline. Its program steps run in SEALED containers (only the mounts the step
//! names, read-only root, no capabilities, no network unless the step asks, the image by
//! digest, never pulled), and the forge's own work between them (check out a pin, check
//! the vendored crates, stage a packaged crate) is a `Forge` step: a named action of the
//! runner, never a program.

use dwarves_runa::{Mount, Pipeline, RunaError, Step, ValidationError};

const IMAGE: &str = "localhost/nordisk-cargo-toolchain@sha256:875a7a325dfe7f6b838535d085a2a502e8ad250076c947f6d023b1e224f03334";

fn pipeline(step: &str) -> String {
    format!(
        r#"Pipeline(
  name: "release",
  stages: [
    Stage(name: "sources", steps: [ Forge(action: "checkout", args: ["dwarves"]) ]),
    Stage(name: "build", needs: ["sources"], steps: [ {step} ]),
  ],
)"#
    )
}

fn sandbox(image: &str, mounts: &str, cmd: &str) -> String {
    format!(
        r#"Sandbox(image: "{image}", cmd: [{cmd}], mounts: [{mounts}], tmpfs: [(path: "/tmp", size_mb: 1024)], workdir: "/src/dwarves")"#
    )
}

fn refused(src: &str) -> ValidationError {
    match Pipeline::from_ron_str(src) {
        Err(RunaError::Validation(v)) => v,
        other => panic!("expected a validation refusal, got {other:?}"),
    }
}

#[test]
fn a_sandbox_step_loads_with_its_mounts_and_no_network_by_default() {
    let src = pipeline(&sandbox(
        IMAGE,
        r#"(host: "/srv/relbuild/runs/r1/src", path: "/src", read_only: true), (host: "/srv/relbuild/runs/r1/out", path: "/out")"#,
        r#""cargo", "package", "--locked", "--offline""#,
    ));
    let p = Pipeline::from_ron_str(&src).expect("loads");
    let Step::Sandbox { image, cmd, mounts, tmpfs, network, workdir, env } = &p.stages[1].steps[0] else {
        panic!("not a sandbox: {:?}", p.stages[1].steps[0]);
    };
    assert_eq!(image, IMAGE);
    assert_eq!(cmd[0], "cargo");
    assert_eq!(
        mounts[0],
        Mount { host: "/srv/relbuild/runs/r1/src".into(), path: "/src".into(), read_only: true }
    );
    assert!(!mounts[1].read_only, "a mount is writable only when it says so");
    assert_eq!(tmpfs[0].size_mb, 1024);
    assert!(!network, "no network unless the step asks for it");
    assert_eq!(workdir, "/src/dwarves");
    assert!(env.is_empty());
    let Step::Forge { action, args } = &p.stages[0].steps[0] else { panic!() };
    assert_eq!((action.as_str(), args[0].as_str()), ("checkout", "dwarves"));
    // and it round-trips
    let back = Pipeline::from_ron_str(&p.to_ron_string().unwrap()).unwrap();
    assert_eq!(back, p);
}

#[test]
fn a_sandbox_image_not_named_by_digest_is_refused() {
    let v = refused(&pipeline(&sandbox("docker.io/library/rust:latest", "", r#""cargo""#)));
    assert!(v.to_string().contains("digest"), "{v}");
}

#[test]
fn a_sandbox_mount_must_be_absolute_on_both_sides_and_never_climb() {
    for m in [
        r#"(host: "relative/src", path: "/src")"#,
        r#"(host: "/srv/r/../../etc", path: "/src")"#,
        r#"(host: "/srv/r/src", path: "src")"#,
        r#"(host: "/", path: "/src")"#,
    ] {
        let v = refused(&pipeline(&sandbox(IMAGE, m, r#""cargo""#)));
        assert!(v.to_string().contains("mount"), "{m}: {v}");
    }
}

#[test]
fn a_sandbox_runs_a_program_or_nothing() {
    let v = refused(&pipeline(&sandbox(IMAGE, "", "")));
    assert!(v.to_string().contains("argv"), "{v}");
}

#[test]
fn a_sandbox_env_carries_no_secret() {
    let src = pipeline(&format!(
        r#"Sandbox(image: "{IMAGE}", cmd: ["cargo"], env: [("CARGO_REGISTRY_TOKEN", "x")])"#
    ));
    let v = refused(&src);
    assert!(v.to_string().contains("secret"), "{v}");
}

#[test]
fn a_forge_action_is_a_name() {
    let v = refused(&pipeline(r#"Forge(action: "../bin/sh")"#));
    assert!(v.to_string().contains("Forge action"), "{v}");
}

#[test]
fn a_pipeline_built_in_code_goes_through_the_same_gate() {
    let mut p = Pipeline::from_ron_str(&pipeline(&sandbox(IMAGE, "", r#""cargo""#))).unwrap();
    assert!(p.validate().is_ok());
    p.stages[1].steps[0] = Step::Forge { action: "a b".into(), args: vec![] };
    assert!(p.validate().is_err(), "a code-built pipeline is checked by the same validator");
}