Fix sloptrap name
This commit is contained in:
24
README.md
24
README.md
@@ -1,10 +1,10 @@
|
||||
# Sloptrap
|
||||
# sloptrap
|
||||
|
||||
Sloptrap runs the OpenAI Codex CLI inside a container with a predictable and locked-down filesystem view. The launcher script (`sloptrap`) resolves the project manifest, builds the support image directly, and starts Codex with the requested target (defaults to `run`). Hardened parsing blocks container escapes via manifest or ignore directives, verifies the downloaded Codex binary, and keeps the runtime environment minimal.
|
||||
sloptrap runs the OpenAI Codex CLI inside a container with a predictable and locked-down filesystem view. The launcher script (`sloptrap`) resolves the project manifest, builds the support image directly, and starts Codex with the requested target (defaults to `run`). Hardened parsing blocks container escapes via manifest or ignore directives, verifies the downloaded Codex binary, and keeps the runtime environment minimal.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Podman ≥ 4 (Sloptrap refuses to run without it unless you explicitly override `SLOPTRAP_CONTAINER_ENGINE`).
|
||||
- Podman ≥ 4 (sloptrap refuses to run without it unless you explicitly override `SLOPTRAP_CONTAINER_ENGINE`).
|
||||
- GNU `bash`, `curl`, `tar`, `sha256sum`, `realpath` (from GNU coreutils), and `jq` on the host.
|
||||
- Network access to `https://github.com/openai/codex/releases/` for fetching the Codex binary.
|
||||
- Enough local disk space to build the container image and cache Codex under `${HOME}/.codex`.
|
||||
@@ -28,7 +28,7 @@ Sloptrap runs the OpenAI Codex CLI inside a container with a predictable and loc
|
||||
secrets/
|
||||
EOF
|
||||
```
|
||||
3. Run `./sloptrap your-project`. On the first invocation Sloptrap:
|
||||
3. Run `./sloptrap your-project`. On the first invocation sloptrap:
|
||||
- builds `your-project-sloptrap-image` if missing,
|
||||
- verifies the Codex binary hash,
|
||||
- creates `${HOME}/.codex` and runs `login` if credentials are absent.
|
||||
@@ -41,14 +41,14 @@ Use `./sloptrap your-project shell` to enter a troubleshooting shell inside the
|
||||
|
||||
- The project directory mounts at `/workspace`, and `${HOME}/.codex` mounts at `/codex`.
|
||||
- `.sloptrapignore` entries (if present) are overlaid by tmpfs (for directories) or empty bind mounts (for files) so Codex cannot read the masked content. Paths are normalised and must remain inside the project tree; attempting to mask parent directories or symlink escapes fails fast.
|
||||
- Sloptrap launches containers on an isolated network (`bridge` on Docker, `slirp4netns` on Podman) with `--cap-drop=ALL`, `--security-opt no-new-privileges`, a read-only root filesystem, and tmpfs-backed `/tmp`, `/run`, and `/run/lock`. Projects that explicitly set `allow_host_network=true` in their manifest opt into `--network host`.
|
||||
- sloptrap launches containers on an isolated network (`bridge` on Docker, `slirp4netns` on Podman) with `--cap-drop=ALL`, `--security-opt no-new-privileges`, a read-only root filesystem, and tmpfs-backed `/tmp`, `/run`, and `/run/lock`. Projects that explicitly set `allow_host_network=true` in their manifest opt into `--network host`.
|
||||
- The helper Dockerfile is embedded inside `sloptrap`; set `SLOPTRAP_DOCKERFILE_PATH=/path/to/custom/Dockerfile` if you need to supply your own recipe. The default image installs `curl`, `bash`, `ca-certificates`, `libstdc++6`, `git`, `ripgrep`, `xxd`, and `file`, so most debugging helpers are already available without adding `packages_extra`.
|
||||
- The container user matches the host UID/GID (`--userns=keep-id` on Podman or `--user UID:GID` on Docker).
|
||||
- The runtime environment is fixed to HOME/XDG variables pointing at `/codex`; manifest-controlled environment injection is disabled.
|
||||
|
||||
## `.sloptrap` Manifest Reference
|
||||
|
||||
The manifest is optional. When absent, Sloptrap derives:
|
||||
The manifest is optional. When absent, sloptrap derives:
|
||||
- `name = basename(project directory)`
|
||||
- `default_targets = run`
|
||||
- `packages_extra = ""` (none)
|
||||
@@ -63,7 +63,7 @@ Supported keys when the manifest is present:
|
||||
| `packages_extra` | *empty* | Additional Debian packages installed during `docker/podman build`. Tokens must be alphanumeric plus `+.-`. |
|
||||
| `codex_args` | `--sandbox workspace-write` | Passed verbatim to the Codex CLI entrypoint. Tokens are shell-split, so quote values with spaces (e.g., `--profile security-audit`). |
|
||||
| `allow_host_network` | `false` | `true` opts into `--network host`; keep `false` unless the project absolutely requires direct access to host-local services. |
|
||||
`codex_args` are appended after the default sandbox flag, and Sloptrap refuses to run if the resulting `--sandbox` mode is anything other than `workspace-write` or `workspace-read-only`.
|
||||
`codex_args` are appended after the default sandbox flag, and sloptrap refuses to run if the resulting `--sandbox` mode is anything other than `workspace-write` or `workspace-read-only`.
|
||||
|
||||
Values containing `$`, `` ` ``, or newlines are rejected to prevent command injection. Setting illegal keys or malformed values aborts the run before containers start.
|
||||
|
||||
@@ -91,7 +91,7 @@ Behaviour:
|
||||
|
||||
- Missing manifests are treated as default configuration.
|
||||
- `SLOPTRAP_CONTAINER_ENGINE` overrides engine auto-detection.
|
||||
- If `${HOME}/.codex/auth.json` is absent, Sloptrap prepends a login run before executing your targets.
|
||||
- If `${HOME}/.codex/auth.json` is absent, sloptrap prepends a login run before executing your targets.
|
||||
- Exit status mirrors the last target executed; errors in parsing or setup abort early with a message.
|
||||
|
||||
`--print-config` fields include `manifest_present=true|false`, resolved paths, and the sanitised ignore mount roots so you can confirm what will be hidden inside the container.
|
||||
@@ -103,7 +103,7 @@ Behaviour:
|
||||
|
||||
## Built-in Targets
|
||||
|
||||
Targets are supplied after the code directory (or via `default_targets` in the manifest). When omitted, Sloptrap defaults to `run`.
|
||||
Targets are supplied after the code directory (or via `default_targets` in the manifest). When omitted, sloptrap defaults to `run`.
|
||||
|
||||
| Target | Description |
|
||||
| --- | --- |
|
||||
@@ -123,7 +123,7 @@ The launcher executes targets sequentially, so `./sloptrap repo build run` perfo
|
||||
- Container engine: Podman or Docker with identical command lines. Podman uses `--userns=keep-id`; Docker receives the equivalent `--user UID:GID`.
|
||||
- Filesystem view: the project directory mounts at `/workspace`; `${HOME}/.codex` mounts at `/codex`.
|
||||
- Ignore filter: `.sloptrapignore` entries are overlaid with tmpfs directories or empty bind mounts so data remains unavailable to Codex.
|
||||
- Network: the container always runs with `--network host`. Sloptrap does not filter or proxy outbound traffic.
|
||||
- Network: the container always runs with `--network host`. sloptrap does not filter or proxy outbound traffic.
|
||||
- Process context: capabilities are dropped, `no-new-privileges` is set, the root filesystem is read-only, and scratch paths (`/tmp`, `/run`, `/run/lock`) are tmpfs mounts. Resource limits follow the launcher defaults.
|
||||
- Codex configuration: runtime flags come from `codex_args`. Persistent Codex state is stored under `${HOME}/.codex`.
|
||||
|
||||
@@ -133,10 +133,10 @@ The launcher executes targets sequentially, so `./sloptrap repo build run` perfo
|
||||
- **Shared storage**: `/workspace` and `/codex` are the only host mounts. Files written to these locations become visible on the host and to the LLM provider through prompts.
|
||||
- **Environment surface**: the container receives a minimal fixed environment (HOME/XDG paths, `CODEX_HOME`). The manifest no longer allows injecting additional environment variables.
|
||||
- **Process isolation**: the container runs without additional Linux capabilities and with a read-only root filesystem. The container and host still share the same kernel; a kernel-level escape would affect host confidentiality.
|
||||
- **Networking stance**: traffic is unrestricted once it leaves the container. Sloptrap does not enforce an allowlist or DNS policy, and `--network host` is always used because the bundled Codex CLI must reach an upstream LLM provider. If you require an offline or firewalled workflow, Sloptrap is not an appropriate launcher.
|
||||
- **Networking stance**: traffic is unrestricted once it leaves the container. sloptrap does not enforce an allowlist or DNS policy, and `--network host` is always used because the bundled Codex CLI must reach an upstream LLM provider. If you require an offline or firewalled workflow, sloptrap is not an appropriate launcher.
|
||||
- **Persistence**: Codex history and logs accumulate under `${HOME}/.codex`. Sensitive prompts recorded on disk remain on the host after the session. Because `.git/` is ignored inside the container, any historical secrets in Git objects stay outside the LLM context unless explicitly surfaced in the working tree.
|
||||
- **Codex cache hygiene**: the `${HOME}/.codex` mount remains writable by the container and will hold tokens, cached prompts, and other state. Rotate credentials regularly and avoid co-locating unrelated secrets inside that directory.
|
||||
- **Secret scanning**: Sloptrap does not perform secret discovery or redaction; any credentials present in the project remain available to Codex and the upstream provider.
|
||||
- **Secret scanning**: sloptrap does not perform secret discovery or redaction; any credentials present in the project remain available to Codex and the upstream provider.
|
||||
- **Local model exception**: pointing Codex at a local or self-hosted model keeps data within the host network boundary, but the filesystem and environment exposure described above is unchanged.
|
||||
|
||||
These constraints focus on limiting host data exposure to the Codex session while acknowledging that any material introduced into the context window may leave the environment through the upstream API.
|
||||
|
||||
28
sloptrap
28
sloptrap
@@ -101,6 +101,8 @@ MANIFEST_BASENAME=".sloptrap"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
VALID_NAME_REGEX='^[A-Za-z0-9_.-]+$'
|
||||
DEFAULT_CODEX_ARGS=(--sandbox workspace-write)
|
||||
SLOPTRAP_IMAGE_LABEL_KEY="net.sk4nz.sloptrap.managed"
|
||||
SLOPTRAP_IMAGE_LABEL="${SLOPTRAP_IMAGE_LABEL_KEY}=1"
|
||||
|
||||
usage() {
|
||||
print_banner
|
||||
@@ -116,6 +118,12 @@ usage() {
|
||||
comment_line " packages_extra=kubectl helm\n"
|
||||
comment_line " default_targets=run\n"
|
||||
comment_line " codex_args=--sandbox workspace-write\n"
|
||||
info_line "\n"
|
||||
info_line "Example targets:\n"
|
||||
comment_line " run Build if needed, then launch Codex\n"
|
||||
comment_line " shell Drop into an interactive /bin/bash session\n"
|
||||
comment_line " clean Remove the project container/image cache\n"
|
||||
comment_line " prune Remove dangling/unused sloptrap images\n"
|
||||
}
|
||||
|
||||
error() {
|
||||
@@ -212,7 +220,7 @@ FROM ${BASE_IMAGE}
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ARG BASE_PACKAGES="curl bash ca-certificates libstdc++6 ripgrep xxd file"
|
||||
ARG BASE_PACKAGES="curl bash ca-certificates libstdc++6 ripgrep xxd file procps"
|
||||
ARG EXTRA_PACKAGES=""
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends apt-utils ${BASE_PACKAGES} ${EXTRA_PACKAGES} \
|
||||
@@ -785,7 +793,7 @@ prepare_container_runtime() {
|
||||
SLOPTRAP_DOCKERFILE_SOURCE=""
|
||||
fi
|
||||
|
||||
SLOPTRAP_PACKAGES_BASE=$(get_env_default "SLOPTRAP_PACKAGES" "curl bash ca-certificates libstdc++6 git ripgrep xxd file")
|
||||
SLOPTRAP_PACKAGES_BASE=$(get_env_default "SLOPTRAP_PACKAGES" "curl bash ca-certificates libstdc++6 git ripgrep xxd file procps")
|
||||
SLOPTRAP_CODEX_URL=$(get_env_default "SLOPTRAP_CODEX_URL" "https://github.com/openai/codex/releases/latest/download/codex-x86_64-unknown-linux-gnu.tar.gz")
|
||||
SLOPTRAP_CODEX_BIN_NAME=$(get_env_default "SLOPTRAP_CODEX_BIN" "codex")
|
||||
SLOPTRAP_CODEX_HOME_CONT=$(get_env_default "SLOPTRAP_CODEX_HOME_CONT" "/codex")
|
||||
@@ -906,6 +914,7 @@ build_image() {
|
||||
"$CONTAINER_ENGINE" build --quiet
|
||||
-t "$SLOPTRAP_IMAGE_NAME"
|
||||
-f "$SLOPTRAP_DOCKERFILE_PATH"
|
||||
--label "$SLOPTRAP_IMAGE_LABEL"
|
||||
--build-arg "BASE_PACKAGES=$SLOPTRAP_PACKAGES_BASE"
|
||||
--build-arg "CODEX_BIN=$SLOPTRAP_CODEX_BIN_NAME"
|
||||
--build-arg "CODEX_UID=$SLOPTRAP_CODEX_UID"
|
||||
@@ -941,6 +950,7 @@ rebuild_image() {
|
||||
"$CONTAINER_ENGINE" build --no-cache
|
||||
-t "$SLOPTRAP_IMAGE_NAME"
|
||||
-f "$SLOPTRAP_DOCKERFILE_PATH"
|
||||
--label "$SLOPTRAP_IMAGE_LABEL"
|
||||
--build-arg "BASE_PACKAGES=$SLOPTRAP_PACKAGES_BASE"
|
||||
--build-arg "CODEX_BIN=$SLOPTRAP_CODEX_BIN_NAME"
|
||||
--build-arg "CODEX_UID=$SLOPTRAP_CODEX_UID"
|
||||
@@ -1005,6 +1015,17 @@ clean_environment() {
|
||||
rm -rf "$helper_root"
|
||||
}
|
||||
|
||||
prune_sloptrap_images() {
|
||||
if ! $DRY_RUN; then
|
||||
status_line "Pruning unused sloptrap images\n"
|
||||
fi
|
||||
local -a cmd=(
|
||||
"$CONTAINER_ENGINE" image prune --force --all
|
||||
--filter "label=$SLOPTRAP_IMAGE_LABEL"
|
||||
)
|
||||
run_or_print "${cmd[@]}"
|
||||
}
|
||||
|
||||
run_codex() {
|
||||
if ! $DRY_RUN; then
|
||||
status_line "Running %s\n" "$SLOPTRAP_IMAGE_NAME"
|
||||
@@ -1063,6 +1084,9 @@ dispatch_target() {
|
||||
clean)
|
||||
clean_environment
|
||||
;;
|
||||
prune)
|
||||
prune_sloptrap_images
|
||||
;;
|
||||
*)
|
||||
error "unknown target '$target'"
|
||||
;;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Test Scenarios
|
||||
|
||||
This directory contains cases that stress Sloptrap's hardening and deployment flow. Each subdirectory mimics a user repository and focuses on a single class of behaviour. Use `run_tests.sh` to execute the automated checks with stubbed tooling.
|
||||
This directory contains cases that stress sloptrap's hardening and deployment flow. Each subdirectory mimics a user repository and focuses on a single class of behaviour. Use `run_tests.sh` to execute the automated checks with stubbed tooling.
|
||||
|
||||
Current scenarios:
|
||||
|
||||
@@ -9,4 +9,4 @@ Current scenarios:
|
||||
- `symlink_escape/` — confirms symlink targets resolving outside the project are blocked.
|
||||
- `manifest_injection/` — ensures disallowed `make.*` overrides abort parsing.
|
||||
- `helper_symlink/` — ensures `.sloptrap-ignores` cannot be a symlink to directories outside the project.
|
||||
- `secret_mask/` — verifies masked files remain hidden even when Sloptrap remaps the workspace mount.
|
||||
- `secret_mask/` — verifies masked files remain hidden even when sloptrap remaps the workspace mount.
|
||||
|
||||
Reference in New Issue
Block a user