glove/tests/container/macos_exec_test.cpp
2026-07-19 21:06:11 -04:00

90 lines
3.8 KiB
C++

// Stage 3 (macOS): `glove exec` runs a real, self-driving agent contained with
// stdio inherited and no MCP kernel. We exercise the platform entry point
// exec_contained directly and assert the two containment guarantees that matter
// for an agent like pi: (1) HOME is redirected into the writable workspace so
// the agent's state writes land inside the sandbox; (2) a write outside the
// workspace is denied; (3) host credential-bearing environment variables are
// not inherited.
#include "glove/container/profile.hpp"
#include "glove/container/spawner.hpp"
#include <unistd.h>
#include <cstdio>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <string>
namespace {
#define REQUIRE(cond) \
do { \
if (!(cond)) { \
std::fprintf(stderr, "REQUIRE failed: %s @ %s:%d\n", #cond, __FILE__, __LINE__); \
return 1; \
} \
} while (0)
auto run() -> int {
REQUIRE(::setenv("GLOVE_TEST_HOST_SECRET", "must-not-cross", 1) == 0);
std::error_code ec;
auto base =
std::filesystem::temp_directory_path() / ("glove_exec_test_" + std::to_string(::getpid()));
auto workspace = base / "ws";
std::filesystem::create_directories(workspace, ec);
REQUIRE(!ec);
// A path OUTSIDE the workspace that must be denied. It has to be somewhere
// the profile does NOT allow — the host $HOME, not /var/folders (which is a
// permitted scratch dir). The test cleans it up if it somehow appears.
const char* host_home = std::getenv("HOME");
REQUIRE(host_home != nullptr && *host_home != '\0');
std::filesystem::path forbidden =
std::filesystem::path{host_home} / (".glove_exec_forbidden_" + std::to_string(::getpid()));
glove::container::profile prof;
prof.filesystem.push_back({.path = workspace.string(), .writable = true});
// HOME is the scratch-home the runner would set; point it at the workspace.
prof.home_dir = workspace.string();
// The agent: record its $HOME (which glove should have pointed at the
// workspace), and attempt a write outside it.
std::string script = "printf '%s' \"$HOME\" > \"$HOME/home_marker\"; ";
script += "if env | grep '^GLOVE_TEST_HOST_SECRET=' >/dev/null; then ";
script += "printf inherited > \"$HOME/env_marker\"; else ";
script += "printf scrubbed > \"$HOME/env_marker\"; fi; ";
script += "touch '" + forbidden.string() + "' 2>/dev/null || true";
auto code = glove::container::exec_contained(prof, {"/bin/sh", "-c", script});
REQUIRE(code.has_value());
REQUIRE(*code == 0);
// (1) HOME was the workspace, and the agent wrote its marker there.
auto marker = workspace / "home_marker";
REQUIRE(std::filesystem::exists(marker));
std::ifstream in{marker};
std::string home_seen;
std::getline(in, home_seen);
std::fprintf(stderr, "agent $HOME = %s\n", home_seen.c_str());
REQUIRE(std::filesystem::equivalent(home_seen, workspace, ec));
REQUIRE(!ec);
std::ifstream env_in{workspace / "env_marker"};
std::string env_seen;
std::getline(env_in, env_seen);
REQUIRE(env_seen == "scrubbed");
// (2) the write outside the workspace was denied.
const bool escaped = std::filesystem::exists(forbidden);
std::filesystem::remove_all(base, ec);
REQUIRE(!escaped);
REQUIRE(::unsetenv("GLOVE_TEST_HOST_SECRET") == 0);
return 0;
}
} // namespace
auto main() -> int {
return run();
}