Repository navigation
Reject bundled agent runtimes from app artifacts #6971
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
austinywang
wants to merge
16
commits into
main
from
issue-5674-bundled-bun-1-3-14-segfaults-use-after-free-i
Closed
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
24eb5a0
Add bundled provider runtime regression
5de86b8
Reject bundled agent runtimes in app artifacts
1689c36
Address bundled runtime guard review
eb4e3af
Tighten bundled runtime guard coverage
0c00cf2
Scan all bundled bin entries for runtimes
d390c2a
Merge remote-tracking branch 'origin/main' into issue-5674-bundled-bu…
4bde1f3
Allow bundled codex wrapper
aadb6ac
Merge remote-tracking branch 'origin/main' into issue-5674-bundled-bu…
austinywang f32fd0e
Merge remote-tracking branch 'origin/main' into issue-5674-bundled-bu…
austinywang cae3e65
Run nightly bundled runtime guard unconditionally
austinywang fb93e35
Verify bundled grok wrapper identity
austinywang 71c11a0
Match nightly runtime guard app condition
austinywang d95667c
Merge remote-tracking branch 'origin/main' into issue-5674-bundled-bu…
austinywang 7ad1300
Merge remote-tracking branch 'origin/main' into issue-5674-bundled-bu…
austinywang 481c60a
Add Bun signature SIGPIPE regression
austinywang 4086767
Handle Bun signature scan SIGPIPE
austinywang File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| EXPECTED_GROK_WRAPPER="$SCRIPT_DIR/../Resources/bin/grok" | ||
|
|
||
| usage() { | ||
| cat <<'EOF' | ||
| Usage: scripts/verify-no-bundled-agent-runtimes.sh <cmux.app> | ||
|
|
||
| Verifies that a built cmux app bundle does not ship provider executables or a | ||
| Bun standalone runtime in Contents/Resources/bin. | ||
| EOF | ||
| } | ||
|
|
||
| if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then | ||
| usage | ||
| exit 0 | ||
| fi | ||
|
|
||
| if [ "$#" -ne 1 ]; then | ||
| usage >&2 | ||
| exit 2 | ||
| fi | ||
|
|
||
| APP_PATH="$1" | ||
| BIN_DIR="$APP_PATH/Contents/Resources/bin" | ||
|
|
||
| if [ ! -d "$APP_PATH" ]; then | ||
| echo "error: app bundle not found at $APP_PATH" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| if [ ! -d "$BIN_DIR" ]; then | ||
| echo "error: bundled bin directory not found at $BIN_DIR" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| is_allowed_binary_name() { | ||
| case "$1" in | ||
| # `grok` is allowed only when it matches cmux's checked-in wrapper script; | ||
| # it still goes through the Bun-standalone signature scan below. | ||
| cmux|ghostty|cmux-claude-wrapper|cmux-codex-wrapper|grok|open|start-cmux-profiling|submit-cmux-profile) | ||
| return 0 | ||
| ;; | ||
| *) | ||
| return 1 | ||
| ;; | ||
| esac | ||
| } | ||
|
|
||
| looks_like_bun_standalone() { | ||
| local path="$1" | ||
|
austinywang marked this conversation as resolved.
|
||
| strings -a "$path" 2>/dev/null | grep -E '(/\$bunfs/|StandaloneExecutable|Bun v[0-9]+\.[0-9]+\.[0-9]+)' >/dev/null | ||
| } | ||
|
|
||
| is_checked_in_grok_wrapper() { | ||
| local path="$1" | ||
| [ -f "$EXPECTED_GROK_WRAPPER" ] && cmp -s "$EXPECTED_GROK_WRAPPER" "$path" | ||
| } | ||
|
|
||
| relative_to_app() { | ||
| local path="$1" | ||
| printf '%s\n' "${path#"$APP_PATH"/}" | ||
| } | ||
|
|
||
| violations=() | ||
|
|
||
| while IFS= read -r -d '' file; do | ||
| name="$(basename "$file")" | ||
| if ! is_allowed_binary_name "$name"; then | ||
| violations+=("unexpected bundled bin entry: $(relative_to_app "$file")") | ||
| continue | ||
| fi | ||
| if [ ! -x "$file" ] && [ ! -L "$file" ]; then | ||
| violations+=("allowed bin entry is not executable: $(relative_to_app "$file")") | ||
| fi | ||
| if [ "$name" = "grok" ] && ! is_checked_in_grok_wrapper "$file"; then | ||
| violations+=("grok wrapper does not match checked-in cmux wrapper: $(relative_to_app "$file")") | ||
| fi | ||
| if looks_like_bun_standalone "$file"; then | ||
| violations+=("Bun standalone runtime signature: $(relative_to_app "$file")") | ||
| fi | ||
| done < <(find "$BIN_DIR" \( -type f -o -type l \) -print0) | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| if [ "${#violations[@]}" -gt 0 ]; then | ||
| echo "error: cmux app bundle contains forbidden bundled provider runtimes:" >&2 | ||
| printf ' %s\n' "${violations[@]}" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "verified no bundled provider runtimes: $APP_PATH" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,152 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" | ||
| VERIFY_SCRIPT="$ROOT_DIR/scripts/verify-no-bundled-agent-runtimes.sh" | ||
|
|
||
| if [ ! -x "$VERIFY_SCRIPT" ]; then | ||
| echo "FAIL: missing bundled provider runtime verifier at $VERIFY_SCRIPT" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/cmux-bundled-runtime-guard.XXXXXX")" | ||
| trap 'rm -rf "$TMP_DIR"' EXIT | ||
|
|
||
| make_app() { | ||
| local app_path="$1" | ||
| mkdir -p "$app_path/Contents/Resources/bin" | ||
| } | ||
|
|
||
| write_executable() { | ||
| local path="$1" | ||
| local body="$2" | ||
| mkdir -p "$(dirname "$path")" | ||
| printf '%s\n' "$body" > "$path" | ||
| chmod 0755 "$path" | ||
| } | ||
|
|
||
| copy_grok_wrapper() { | ||
| local path="$1" | ||
| mkdir -p "$(dirname "$path")" | ||
| install -m 0755 "$ROOT_DIR/Resources/bin/grok" "$path" | ||
| } | ||
|
|
||
| GOOD_APP="$TMP_DIR/good/cmux.app" | ||
| make_app "$GOOD_APP" | ||
| write_executable "$GOOD_APP/Contents/Resources/bin/cmux" "#!/bin/sh" | ||
| write_executable "$GOOD_APP/Contents/Resources/bin/ghostty" "#!/bin/sh" | ||
| write_executable "$GOOD_APP/Contents/Resources/bin/cmux-claude-wrapper" "#!/bin/sh" | ||
| write_executable "$GOOD_APP/Contents/Resources/bin/cmux-codex-wrapper" "#!/bin/sh" | ||
| copy_grok_wrapper "$GOOD_APP/Contents/Resources/bin/grok" | ||
| write_executable "$GOOD_APP/Contents/Resources/bin/open" "#!/bin/sh" | ||
| write_executable "$GOOD_APP/Contents/Resources/bin/start-cmux-profiling" "#!/bin/sh" | ||
| write_executable "$GOOD_APP/Contents/Resources/bin/submit-cmux-profile" "#!/bin/sh" | ||
| "$VERIFY_SCRIPT" "$GOOD_APP" | ||
|
austinywang marked this conversation as resolved.
austinywang marked this conversation as resolved.
|
||
|
|
||
| BAD_GROK_APP="$TMP_DIR/bad-grok-wrapper/cmux.app" | ||
| make_app "$BAD_GROK_APP" | ||
| write_executable "$BAD_GROK_APP/Contents/Resources/bin/cmux" "#!/bin/sh" | ||
| write_executable "$BAD_GROK_APP/Contents/Resources/bin/grok" "#!/bin/sh" | ||
| if "$VERIFY_SCRIPT" "$BAD_GROK_APP" >"$TMP_DIR/grok-wrapper.out" 2>&1; then | ||
| echo "FAIL: verifier allowed a non-cmux grok wrapper" >&2 | ||
| exit 1 | ||
| fi | ||
| if ! grep -Fq "grok wrapper does not match checked-in cmux wrapper: Contents/Resources/bin/grok" "$TMP_DIR/grok-wrapper.out"; then | ||
| echo "FAIL: grok wrapper rejection did not name the offending path" >&2 | ||
| cat "$TMP_DIR/grok-wrapper.out" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| for forbidden in claude opencode codex pi bun bunx; do | ||
| BAD_APP="$TMP_DIR/bad-$forbidden/cmux.app" | ||
| make_app "$BAD_APP" | ||
| write_executable "$BAD_APP/Contents/Resources/bin/cmux" "#!/bin/sh" | ||
| write_executable "$BAD_APP/Contents/Resources/bin/$forbidden" "#!/bin/sh" | ||
| OUTPUT="$TMP_DIR/$forbidden.out" | ||
| if "$VERIFY_SCRIPT" "$BAD_APP" >"$OUTPUT" 2>&1; then | ||
| echo "FAIL: verifier allowed bundled $forbidden executable" >&2 | ||
| exit 1 | ||
| fi | ||
| if ! grep -Fq "Contents/Resources/bin/$forbidden" "$OUTPUT"; then | ||
| echo "FAIL: verifier rejection for $forbidden did not name the offending path" >&2 | ||
| cat "$OUTPUT" >&2 | ||
| exit 1 | ||
| fi | ||
| done | ||
|
austinywang marked this conversation as resolved.
austinywang marked this conversation as resolved.
|
||
|
|
||
| NONEXEC_FORBIDDEN_APP="$TMP_DIR/bad-nonexec-bun/cmux.app" | ||
| make_app "$NONEXEC_FORBIDDEN_APP" | ||
| write_executable "$NONEXEC_FORBIDDEN_APP/Contents/Resources/bin/cmux" "#!/bin/sh" | ||
| printf '%s\n' 'Bun v1.3.14 StandaloneExecutable /$bunfs/root' > "$NONEXEC_FORBIDDEN_APP/Contents/Resources/bin/bun" | ||
| chmod 0644 "$NONEXEC_FORBIDDEN_APP/Contents/Resources/bin/bun" | ||
| if "$VERIFY_SCRIPT" "$NONEXEC_FORBIDDEN_APP" >"$TMP_DIR/nonexec-bun.out" 2>&1; then | ||
| echo "FAIL: verifier allowed a non-executable bundled bun file" >&2 | ||
| exit 1 | ||
| fi | ||
| if ! grep -Fq "unexpected bundled bin entry: Contents/Resources/bin/bun" "$TMP_DIR/nonexec-bun.out"; then | ||
| echo "FAIL: non-executable bun rejection did not name the offending path" >&2 | ||
| cat "$TMP_DIR/nonexec-bun.out" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| NONEXEC_ALLOWED_APP="$TMP_DIR/bad-nonexec-allowed/cmux.app" | ||
| make_app "$NONEXEC_ALLOWED_APP" | ||
| printf '%s\n' '#!/bin/sh' > "$NONEXEC_ALLOWED_APP/Contents/Resources/bin/cmux" | ||
| chmod 0644 "$NONEXEC_ALLOWED_APP/Contents/Resources/bin/cmux" | ||
| if "$VERIFY_SCRIPT" "$NONEXEC_ALLOWED_APP" >"$TMP_DIR/nonexec-allowed.out" 2>&1; then | ||
| echo "FAIL: verifier allowed a non-executable allowlisted bin entry" >&2 | ||
| exit 1 | ||
| fi | ||
| if ! grep -Fq "allowed bin entry is not executable: Contents/Resources/bin/cmux" "$TMP_DIR/nonexec-allowed.out"; then | ||
| echo "FAIL: non-executable allowlisted rejection did not name the offending path" >&2 | ||
| cat "$TMP_DIR/nonexec-allowed.out" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| SYMLINK_APP="$TMP_DIR/bad-symlink/cmux.app" | ||
| make_app "$SYMLINK_APP" | ||
| write_executable "$SYMLINK_APP/Contents/Resources/bin/cmux" "#!/bin/sh" | ||
| ln -s cmux "$SYMLINK_APP/Contents/Resources/bin/claude" | ||
| if "$VERIFY_SCRIPT" "$SYMLINK_APP" >"$TMP_DIR/symlink.out" 2>&1; then | ||
| echo "FAIL: verifier allowed a symlinked bundled claude executable" >&2 | ||
| exit 1 | ||
| fi | ||
| if ! grep -Fq "Contents/Resources/bin/claude" "$TMP_DIR/symlink.out"; then | ||
| echo "FAIL: symlink rejection did not name the offending path" >&2 | ||
| cat "$TMP_DIR/symlink.out" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| BUN_SIGNATURE_APP="$TMP_DIR/bad-bun-signature/cmux.app" | ||
| make_app "$BUN_SIGNATURE_APP" | ||
| write_executable "$BUN_SIGNATURE_APP/Contents/Resources/bin/cmux" '#!/bin/sh | ||
| printf "%s\n" "Bun v1.3.14 StandaloneExecutable /$bunfs/root"' | ||
| if "$VERIFY_SCRIPT" "$BUN_SIGNATURE_APP" >"$TMP_DIR/bun-signature.out" 2>&1; then | ||
| echo "FAIL: verifier allowed an allowlisted executable with a Bun standalone signature" >&2 | ||
| exit 1 | ||
| fi | ||
| if ! grep -Fq "Bun standalone runtime signature: Contents/Resources/bin/cmux" "$TMP_DIR/bun-signature.out"; then | ||
| echo "FAIL: Bun signature rejection did not name the offending path" >&2 | ||
| cat "$TMP_DIR/bun-signature.out" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| LARGE_BUN_SIGNATURE_APP="$TMP_DIR/bad-large-bun-signature/cmux.app" | ||
| make_app "$LARGE_BUN_SIGNATURE_APP" | ||
| { | ||
| printf '%s\n' '#!/bin/sh' | ||
| printf '%s\n' 'Bun v1.3.14 StandaloneExecutable /$bunfs/root' | ||
| awk 'BEGIN { for (i = 0; i < 5000; i++) print "cmux padding line after the early Bun signature" }' | ||
| } > "$LARGE_BUN_SIGNATURE_APP/Contents/Resources/bin/cmux" | ||
| chmod 0755 "$LARGE_BUN_SIGNATURE_APP/Contents/Resources/bin/cmux" | ||
| if "$VERIFY_SCRIPT" "$LARGE_BUN_SIGNATURE_APP" >"$TMP_DIR/large-bun-signature.out" 2>&1; then | ||
| echo "FAIL: verifier allowed a large allowlisted executable with an early Bun standalone signature" >&2 | ||
| exit 1 | ||
| fi | ||
| if ! grep -Fq "Bun standalone runtime signature: Contents/Resources/bin/cmux" "$TMP_DIR/large-bun-signature.out"; then | ||
| echo "FAIL: large Bun signature rejection did not name the offending path" >&2 | ||
| cat "$TMP_DIR/large-bun-signature.out" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "PASS: bundled provider runtime guard rejects stale provider and Bun executables" | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.