Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
08f4843
feat(sandbox): add opt-in Cageforge command session boundary
m62624 Sep 22, 2026
41d3515
ci(sandbox): isolate command enforcement checks by native platform
m62624 Sep 22, 2026
f846dcc
fix(test): preserve absolute runtime roots in native probes
m62624 Sep 22, 2026
eec0242
fix(ci): normalize Windows archive paths before extraction
m62624 Sep 22, 2026
5bd86c1
fix(test): restrict macOS runtime roots to macOS fixtures
m62624 Sep 22, 2026
3aba492
build(sandbox): upgrade Cageforge Java to 0.7.0
m62624 Sep 22, 2026
e3cf796
feat(sandbox): manage bounded session pipes and termination
m62624 Sep 22, 2026
d23c2a3
feat(sandbox): add single-use and app-lifetime consent
m62624 Sep 22, 2026
aba1179
test(sandbox): stream native progress and isolate probe classpath
m62624 Sep 23, 2026
69f5847
build(sandbox): upgrade Cageforge Java to 0.7.1
m62624 Sep 23, 2026
4700b2f
test(sandbox): verify explicit file grants for root and descendants
m62624 Sep 23, 2026
ae550ee
fix(test): respect Windows sandbox traversal and ACL cleanup
m62624 Sep 23, 2026
4cc73ba
fix(test): restore Windows sandbox state before fixture cleanup
m62624 Sep 23, 2026
cabab3b
fix(sandbox): allow Cageforge permission escalation
m62624 Sep 23, 2026
ae21165
test(sandbox): verify Cageforge escalation boundary
m62624 Sep 23, 2026
e284e77
test(sandbox): initialize Cageforge before escalation request
m62624 Sep 23, 2026
1b8f53e
test(sandbox): compare escaped capabilities structurally
m62624 Sep 23, 2026
4ba924f
feat(sandbox): own consented command sessions through app shutdown
m62624 Sep 23, 2026
bab763a
feat(sandbox): add desktop command session and consent dialogs
m62624 Sep 23, 2026
d0f6b93
feat(sandbox): review and launch additional command permissions
m62624 Sep 23, 2026
c80d5eb
feat(sandbox): expose opt-in startup and consented MCP command tools
m62624 Sep 23, 2026
a57d5e2
test(sandbox): mark Windows escalation isolation phases
m62624 Sep 23, 2026
ad5a4eb
fix(sandbox): reject unsafe concurrent Windows grants
m62624 Sep 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 152 additions & 0 deletions .github/workflows/cageforge-command-sessions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
name: Cageforge command sessions

on:
push:
branches: [dev]
pull_request:
branches: [dev, main]
paths:
- 'modules/boss-command-sandbox/**'
- 'composeApp/**'
- 'ci/cageforge-command-suite/**'
- 'ci/run-cageforge-command-linux-vm.sh'
- '.github/workflows/cageforge-command-sessions.yml'
- 'gradle/libs.versions.toml'
- 'settings.gradle.kts'
workflow_dispatch:

permissions:
contents: read

concurrency:
group: cageforge-command-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
native-desktop:
name: Command sessions on ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-15, windows-2025]
runs-on: ${{ matrix.os }}
timeout-minutes: 20
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-java@v6.0.0
with:
distribution: temurin
java-version: '17'
- uses: gradle/actions/setup-gradle@v6
- name: Build and check session module
timeout-minutes: 10
run: ./gradlew :boss-command-sandbox:check :boss-command-sandbox:nativeSecurityTestBundle --no-daemon --max-workers=2 --console=plain
- name: Stage self-contained consumer
run: |
set -euo pipefail
runner_temp="$RUNNER_TEMP"
if [[ "$RUNNER_OS" == Windows ]]; then
runner_temp=$(cygpath -u "$runner_temp")
fi
stage=$(mktemp -d "$runner_temp/boss-command-runtime.XXXXXX")
tar -xzf modules/boss-command-sandbox/build/nativeSecurityTest/boss-command-sandbox-tests.tar.gz -C "$stage"
separator=:
classes="$stage/classes"
if [[ "$RUNNER_OS" == Windows ]]; then
classes=$(cygpath -m "$classes")
separator=';'
fi
classpath="$classes"
while IFS= read -r -d '' jar; do
if [[ "$RUNNER_OS" == Windows ]]; then
jar=$(cygpath -m "$jar")
fi
classpath="$classpath$separator$jar"
done < <(find "$stage/lib" -maxdepth 1 -type f -name '*.jar' -print0 | sort -z)
echo "BOSS_NATIVE_CP=$classpath" >> "$GITHUB_ENV"
- name: Explicit Windows setup
timeout-minutes: 2
if: runner.os == 'Windows'
env:
BOSS_CAGEFORGE_SETUP_MARKER: ${{ runner.temp }}/boss-command-setup-owned
run: java -cp "$BOSS_NATIVE_CP" ai.rever.boss.sandbox.CommandWindowsSetup install
- name: Native root and descendant enforcement
timeout-minutes: 3
run: |
set -euo pipefail
java -cp "$BOSS_NATIVE_CP" ai.rever.boss.sandbox.CommandNativeTestRunner \
2>&1 | tee "$RUNNER_TEMP/boss-command-native.log"
- name: Remove owned Windows setup
timeout-minutes: 2
if: always() && runner.os == 'Windows'
env:
BOSS_CAGEFORGE_SETUP_MARKER: ${{ runner.temp }}/boss-command-setup-owned
run: |
if [[ -f "$BOSS_CAGEFORGE_SETUP_MARKER" ]]; then
java -cp "$BOSS_NATIVE_CP" ai.rever.boss.sandbox.CommandWindowsSetup uninstall
fi
- uses: actions/upload-artifact@v7
if: always()
with:
name: command-session-results-${{ matrix.os }}
path: |
modules/boss-command-sandbox/build/test-results/
${{ runner.temp }}/boss-command-native.log

linux-qemu:
name: Command descendants in prepared Linux QEMU
runs-on: ubuntu-24.04
timeout-minutes: 45
env:
CAGEFORGE_VM_IMAGE_SHA256: 6e40c07ae715f744f84af0bec76415cc1987dd115b4b8de437818561f01a3733
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-java@v6.0.0
with:
distribution: temurin
java-version: '17'
- uses: gradle/actions/setup-gradle@v6
- name: Compile libraries and consumer on the host
run: ./gradlew :boss-command-sandbox:check :boss-command-sandbox:nativeSecurityTestBundle --no-daemon --max-workers=2 --console=plain
- name: Install VM tools
run: |
sudo apt-get update
sudo apt-get install --yes genisoimage qemu-system-x86 qemu-utils
test -c /dev/kvm
sudo chmod 0666 /dev/kvm
- uses: actions/cache@v4
id: image
with:
path: ${{ runner.temp }}/noble-server-cloudimg-amd64.img
key: boss-cageforge-noble-${{ env.CAGEFORGE_VM_IMAGE_SHA256 }}
- name: Download pinned guest
if: steps.image.outputs.cache-hit != 'true'
run: |
curl --fail --silent --show-error --location --retry 3 --max-filesize 1073741824 --max-time 900 \
https://cloud-images.ubuntu.com/noble/20260814/noble-server-cloudimg-amd64.img \
--output "$RUNNER_TEMP/noble-server-cloudimg-amd64.img"
- name: Verify guest image and execute prebuilt consumer
env:
CAGEFORGE_VM_ARTIFACTS: ${{ runner.temp }}/boss-command-vm-logs
run: |
set -euo pipefail
image="$RUNNER_TEMP/noble-server-cloudimg-amd64.img"
printf '%s %s\n' "$CAGEFORGE_VM_IMAGE_SHA256" "$image" | sha256sum --check --status
bash ci/run-cageforge-command-linux-vm.sh --image "$image" \
--test-bundle "$GITHUB_WORKSPACE/modules/boss-command-sandbox/build/nativeSecurityTest/boss-command-sandbox-tests.tar.gz" \
2>&1 | tee "$RUNNER_TEMP/boss-command-native.log"
- uses: actions/upload-artifact@v7
if: always()
with:
name: command-session-results-linux
path: |
modules/boss-command-sandbox/build/test-results/
${{ runner.temp }}/boss-command-native.log
${{ runner.temp }}/boss-command-vm-logs/
12 changes: 12 additions & 0 deletions ci/cageforge-command-suite/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -euo pipefail

bundle_root=${CAGEFORGE_NATIVE_TEST_BUNDLE_ROOT:?native test bundle root is required}
classpath_entries=("$bundle_root/classes")
while IFS= read -r -d '' jar; do
classpath_entries+=("$jar")
done < <(find "$bundle_root/lib" -maxdepth 1 -type f -name '*.jar' -print0 | sort -z)
classpath=$(IFS=:; printf '%s' "${classpath_entries[*]}")
test_home=$(mktemp -d /tmp/boss-command-test-home.XXXXXX)
trap 'rmdir "$test_home" 2>/dev/null || true' EXIT
java -Duser.home="$test_home" -cp "$classpath" ai.rever.boss.sandbox.CommandNativeTestRunner
Loading
Loading