Skip to content

feat(agentsh): add agentsh execution-layer security Dev Container Feature#62

Open
pofallon wants to merge 7 commits into
mainfrom
001-agentsh-feature
Open

feat(agentsh): add agentsh execution-layer security Dev Container Feature#62
pofallon wants to merge 7 commits into
mainfrom
001-agentsh-feature

Conversation

@pofallon
Copy link
Copy Markdown
Contributor

@pofallon pofallon commented Jun 2, 2026

Summary

Adds a new public agentsh Dev Container Feature (ghcr.io/get2knowio/devcontainer-features/agentsh) that installs agentsh execution-layer security: shell shims, a default project policy, a non-overridable security floor, workspace policy overlays, and policy-based approvals served over the agentsh REST API.

Key design points

  • installShellShims (default true) — gates replacing /bin/sh+/bin/bash with the agentsh shim. The Dev Container test harness bootstraps containers through /bin/sh, so it can't start a shimmed default container; CI sets this false and real mediation is validated separately.
  • Single authoritative config — agentsh reads /etc/agentsh/config.yaml (its default --config). External REST API uses X-API-Key auth with a root-level api_keys.yaml list shape. All of this was validated against the real agentsh 0.20.2 binary.
  • glibc + musl.deb and musl-tarball install paths. Alpine works via a POSIX install.sh bootstrap that installs bash before the Bash installer (install-main.sh) runs.
  • Approvals — policy decision: approve rules create pending approvals served over /api/v1/approvals and resolved by an optional notifier sidecar; no outbound webhook (agentsh has none). Unresolved approvals fail secure (deny) after approvalTimeoutSeconds.

Testing

Because agentsh intentionally changes /bin/sh, agentsh needs a special CI path:

  • Harness scenarios (installShellShims=false): default, external-rest-api, approval-timeout, malformed-overlay, missing-floor, ubuntu, debian, alpine.
  • Docker integration probes (outside the harness, Landlock-capable kernel): shim_integration_test (real /bin/sh+/bin/bash mediation via /bin/sh.real), overlay_test (overlay selection + self-protection floor), rest_auth_test (REST API key auth → 401/200/401).
  • shellcheck, policy-merge smoke test, JSON, and YAML checks.

All scenarios and probes pass; shellcheck is clean.

Notes

  • agentsh is intentionally excluded from the autogenerated devcontainer features test matrix (documented in the workflow and CONTRIBUTING.md).
  • This branch also includes pre-existing doc updates for other features (README tool lists, .gitignore) and the Spec Kit scaffolding used to drive the feature.

🤖 Generated with Claude Code

pofallon and others added 7 commits June 2, 2026 08:11
…ture

Adds a new `agentsh` feature that installs agentsh execution-layer security with
shell shims, a default policy, a non-overridable security floor, policy overlays,
and policy-based approvals served asynchronously over the agentsh REST API.

Highlights:
- installShellShims option (default true) gates /bin/sh + /bin/bash mediation;
  CI sets it false so the Dev Container test harness can bootstrap containers.
- Single authoritative /etc/agentsh/config.yaml (agentsh's default --config);
  external REST API with X-API-Key auth and a root-level api_keys.yaml list shape,
  validated against the real agentsh 0.20.2 binary.
- glibc (.deb) and musl (tarball) install paths; Alpine support via a POSIX
  bootstrap that installs bash before the Bash installer runs.
- Approvals are served over the REST API (/api/v1/approvals) and resolved by an
  optional notifier sidecar; no outbound webhook (agentsh has none).
- Dedicated Docker integration tests for real shell-shim mediation, policy
  overlay selection + self-protection, and REST API key auth, run outside the
  Dev Container harness (which mediates /bin/sh for bootstrap).

Validated: 8 harness scenarios + 3 Docker integration probes pass; shellcheck
clean; policy-merge, JSON, and YAML checks pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The devcontainers/action validate-only step failed with `ENOENT: scandir ''`
because no features base path was provided. Point it at ./src (matching the
publish step in release.yaml).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Dev Container Feature schema requires `mounts` entries to be Mount objects
(`type`+`target` required), not the devcontainer.json-style string form. This
was masked until the validate workflow's base-path was fixed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Dev Container Feature options only support boolean and string types, not number.
Change approvalTimeoutSeconds and restPort to string ("300"/"18080"); install.sh
already validates them as positive-integer strings. Validated against the
official devContainerFeature schema. Update option-table docs accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The upstream CodeRabbit install script prints "Installation complete"
and verifies the binary, but then exits with code 2. Under `set -e`
that aborted the entire ai-clis feature build. Tolerate the exit code
and verify the binary landed instead, matching the warning-on-failure
pattern already used for Claude Code and Specify CLI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The rolling mcr.microsoft.com/devcontainers/base:ubuntu tag floated to a
non-LTS interim release ("resolute") whose base image ships without
gnupg/gpgv, breaking apt signature verification and the upstream node
feature in the test-global job. Pin to the LTS tag base:ubuntu-24.04
across all feature test scenarios and the autogenerated --base-image
matrix so CI is stable against the moving tag. base:debian and the
example devcontainer configs are left unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
After pinning the base to ubuntu-24.04, the global scenario's apt failure
moved on from missing gnupg to the legacy node:1 feature tripping apt's
_apt sandbox temp-file bug during apt-get update on the amd64 runner (the
base ubuntu repos report 'not signed'). Our own features run apt on the
same base and pass, so the issue is node:1's old apt helper. Bump to the
current node:2 major, which carries the patched upstream apt helper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant