Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 12 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1542,8 +1542,8 @@ jobs:

- name: Free disk space
run: |
rm -rf .build daemon-bin assistant-bin cli-bin gateway-bin
rm -rf ../../assistant/node_modules ../../cli/node_modules ../../gateway/node_modules
rm -rf .build daemon-bin assistant-bin cli-bin gateway-bin ces-bin
rm -rf ../../assistant/node_modules ../../cli/node_modules ../../gateway/node_modules ../../credential-executor/node_modules
rm -rf ~/Library/Developer/Xcode/DerivedData 2>/dev/null || true
rm -rf ~/Library/Caches/org.swift.swiftpm 2>/dev/null || true
df -h .
Expand Down Expand Up @@ -1877,6 +1877,7 @@ jobs:
ASSISTANT_SRC_DIR="../../assistant"
CLI_SRC_DIR="../../cli"
GATEWAY_SRC_DIR="../../gateway"
CES_SRC_DIR="../../credential-executor"

DAEMON_EXTERNAL_FLAGS=(--external electron --external "chromium-bidi/*")
DAEMON_FLAGS=("${DAEMON_EXTERNAL_FLAGS[@]}")
Expand Down Expand Up @@ -1925,6 +1926,13 @@ jobs:
"$GATEWAY_SRC_DIR/src/index.ts" --outfile gateway-bin/vellum-gateway
chmod +x gateway-bin/vellum-gateway

# Credential-executor (CES)
(cd "$CES_SRC_DIR" && bun install --frozen-lockfile 2>/dev/null || bun install)
mkdir -p ces-bin
bun build --compile --target=bun-darwin-x64 \
"$CES_SRC_DIR/src/main.ts" --outfile ces-bin/credential-executor
chmod +x ces-bin/credential-executor

- name: Build release .app
run: |
IS_STAGING="${{ needs.extract-version.outputs.is_staging }}"
Expand Down Expand Up @@ -1968,8 +1976,8 @@ jobs:

- name: Free disk space
run: |
rm -rf .build daemon-bin assistant-bin cli-bin gateway-bin
rm -rf ../../assistant/node_modules ../../cli/node_modules ../../gateway/node_modules
rm -rf .build daemon-bin assistant-bin cli-bin gateway-bin ces-bin
rm -rf ../../assistant/node_modules ../../cli/node_modules ../../gateway/node_modules ../../credential-executor/node_modules
rm -rf ~/Library/Developer/Xcode/DerivedData 2>/dev/null || true
df -h .

Expand Down
14 changes: 12 additions & 2 deletions assistant/src/credential-execution/executable-discovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/

import { existsSync } from "node:fs";
import { join } from "node:path";
import { dirname, join } from "node:path";

import { getIsContainerized } from "../config/env-registry.js";
import { getLogger } from "../util/logger.js";
Expand Down Expand Up @@ -65,9 +65,19 @@ function getManagedBootstrapSocketPath(): string {
* `getDataDir()` (under `~/.vellum/workspace/data`) was previously included
* but is inside the sandbox write boundary, so a sandboxed tool could plant
* a malicious binary there. Removed to close the sandbox-escape vector.
*
* Search order:
* 1. Alongside the running executable (packaged macOS app:
* `<App>.app/Contents/MacOS/credential-executor`). When running from
* source via `bun run`, `process.execPath` points at the bun binary
* itself, so this path won't exist and the search falls through.
* 2. `<binDir>/credential-executor` — user-installed override (dev flow).
*/
function getLocalBinarySearchPaths(): string[] {
return [join(getBinDir(), "credential-executor")];
return [
join(dirname(process.execPath), "credential-executor"),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate sibling executable lookup to packaged app paths

discoverLocalCes() now always checks join(dirname(process.execPath), "credential-executor") first. Outside the packaged app, process.execPath points to the Bun/Node install directory (for example ~/.bun/bin or /usr/bin), so any unrelated file named credential-executor there will be preferred over ~/.vellum/workspace/bin. In that scenario the daemon can spawn the wrong executable (or untrusted code) and credential operations fail unpredictably; this lookup should be limited to verified app-bundle paths (or verified daemon executable names) before using the sibling binary.

Useful? React with 👍 / 👎.

join(getBinDir(), "credential-executor"),
];
}

// ---------------------------------------------------------------------------
Expand Down
56 changes: 54 additions & 2 deletions clients/macos/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ ASSISTANT_SRC_DIR="$SCRIPT_DIR/../../assistant"
CLI_SRC_DIR="$SCRIPT_DIR/../../cli"
GATEWAY_SRC_DIR="$SCRIPT_DIR/../../gateway"
NATIVE_HOST_SRC_DIR="$SCRIPT_DIR/../chrome-extension/native-host"
CES_SRC_DIR="$SCRIPT_DIR/../../credential-executor"

# Chrome extension allowlist IDs injected into compiled binaries as a fallback
# for packaged runs where repo-relative `meta/browser-extension/...` paths are
Expand Down Expand Up @@ -355,6 +356,7 @@ build_binaries() {
(cd "$ASSISTANT_SRC_DIR" && bun install --frozen-lockfile 2>/dev/null || bun install)
(cd "$CLI_SRC_DIR" && bun install --frozen-lockfile 2>/dev/null || bun install)
(cd "$GATEWAY_SRC_DIR" && bun install --frozen-lockfile 2>/dev/null || bun install)
(cd "$CES_SRC_DIR" && bun install --frozen-lockfile 2>/dev/null || bun install)
if [ -d "$NATIVE_HOST_SRC_DIR/src" ]; then
(cd "$NATIVE_HOST_SRC_DIR" && bun install --frozen-lockfile 2>/dev/null || bun install)
fi
Expand Down Expand Up @@ -409,6 +411,10 @@ build_binaries() {
"$SCRIPT_DIR/gateway-bin" "vellum-gateway" &
pids+=($!)

SKIP_BUN_INSTALL=1 build_bun_binary "$CES_SRC_DIR" "$CES_SRC_DIR/src/main.ts" \
"$SCRIPT_DIR/ces-bin" "credential-executor" &
pids+=($!)

if [ -d "$NATIVE_HOST_SRC_DIR/src" ]; then
SKIP_BUN_INSTALL=1 build_bun_binary "$NATIVE_HOST_SRC_DIR" "$NATIVE_HOST_SRC_DIR/src/index.ts" \
"$SCRIPT_DIR/native-host-bin" "vellum-chrome-native-host" "${native_host_flags[@]}" &
Expand Down Expand Up @@ -552,7 +558,7 @@ case "$CMD" in
clean)
echo "Cleaning..."
rm -rf "$SCRIPT_DIR/dist" "$SCRIPT_DIR/../.build"
rm -rf "$SCRIPT_DIR/daemon-bin" "$SCRIPT_DIR/assistant-bin" "$SCRIPT_DIR/cli-bin" "$SCRIPT_DIR/gateway-bin" "$SCRIPT_DIR/native-host-bin"
rm -rf "$SCRIPT_DIR/daemon-bin" "$SCRIPT_DIR/assistant-bin" "$SCRIPT_DIR/cli-bin" "$SCRIPT_DIR/gateway-bin" "$SCRIPT_DIR/native-host-bin" "$SCRIPT_DIR/ces-bin"
rm -rf "$SPM_MODULE_CACHE"
echo "Done."
exit 0
Expand Down Expand Up @@ -597,7 +603,7 @@ if [ "$CMD" = "release" ] || [ "$CMD" = "release-application" ]; then
# (e.g. arm64 binaries from a previous build being bundled into an x86_64 release).
# Skip when SKIP_BUN_REBUILD=1, since pre-built binaries are intentionally provided.
if [ "${SKIP_BUN_REBUILD:-}" != "1" ]; then
rm -rf "$SCRIPT_DIR/daemon-bin" "$SCRIPT_DIR/assistant-bin" "$SCRIPT_DIR/cli-bin" "$SCRIPT_DIR/gateway-bin" "$SCRIPT_DIR/native-host-bin"
rm -rf "$SCRIPT_DIR/daemon-bin" "$SCRIPT_DIR/assistant-bin" "$SCRIPT_DIR/cli-bin" "$SCRIPT_DIR/gateway-bin" "$SCRIPT_DIR/native-host-bin" "$SCRIPT_DIR/ces-bin"
fi
fi
fi
Expand Down Expand Up @@ -803,6 +809,32 @@ if [ -f "$SCRIPT_DIR/gateway-bin/vellum-gateway" ]; then
fi
fi

# Auto-build credential-executor (CES) binary if missing or stale.
# The compiled binary is bundled alongside the daemon in Contents/MacOS/ so
# the packaged app can locate it without requiring a separate install.
CES_BIN_NEEDS_BUILD=false
if [ "${SKIP_BUN_REBUILD:-}" != "1" ] && [ -d "$CES_SRC_DIR/src" ] && command -v bun &>/dev/null; then
if [ ! -f "$SCRIPT_DIR/ces-bin/credential-executor" ]; then
CES_BIN_NEEDS_BUILD=true
elif [ -n "$(find "$CES_SRC_DIR/src" -name '*.ts' -newer "$SCRIPT_DIR/ces-bin/credential-executor" -print -quit 2>/dev/null)" ]; then
CES_BIN_NEEDS_BUILD=true
elif [ "$CES_SRC_DIR/package.json" -nt "$SCRIPT_DIR/ces-bin/credential-executor" ] || \
[ "$CES_SRC_DIR/bun.lock" -nt "$SCRIPT_DIR/ces-bin/credential-executor" ]; then
CES_BIN_NEEDS_BUILD=true
fi
fi
if [ "$CES_BIN_NEEDS_BUILD" = true ]; then
build_bun_binary "$CES_SRC_DIR" "$CES_SRC_DIR/src/main.ts" \
"$SCRIPT_DIR/ces-bin" "credential-executor"
fi

# Also rebuild if CES binary changed or newly added
if [ -f "$SCRIPT_DIR/ces-bin/credential-executor" ]; then
if [ ! -f "$MACOS_DIR/credential-executor" ] || [ "$SCRIPT_DIR/ces-bin/credential-executor" -nt "$MACOS_DIR/credential-executor" ]; then
NEEDS_REBUILD=true
fi
fi

# Auto-build Chrome native messaging helper binary if missing or stale
# and bun is available. This is the binary Chrome spawns via
# chrome.runtime.connectNative("com.vellum.daemon") — see
Expand Down Expand Up @@ -892,6 +924,18 @@ if [ "$NEEDS_REBUILD" = true ]; then
echo "No gateway binary at $GATEWAY_BIN — skipping (dev mode)"
fi

# Copy bundled credential-executor (CES) binary (if available).
# The daemon locates this via `dirname(process.execPath)` — see
# getLocalBinarySearchPaths() in assistant/src/credential-execution/executable-discovery.ts.
CES_BIN="$SCRIPT_DIR/ces-bin/credential-executor"
if [ -f "$CES_BIN" ]; then
echo "Bundling credential-executor binary..."
cp "$CES_BIN" "$MACOS_DIR/credential-executor"
chmod +x "$MACOS_DIR/credential-executor"
else
echo "No credential-executor binary at $CES_BIN — skipping (dev mode)"
fi

# Copy bundled Chrome native messaging helper binary (if available).
# This is an auxiliary executable under Contents/MacOS/ that Chrome
# spawns via the com.vellum.daemon.json manifest written by
Expand Down Expand Up @@ -1388,6 +1432,13 @@ if [ -f "$MACOS_DIR/vellum-chrome-native-host" ]; then
echo "Chrome native messaging helper binary signed"
fi

# Sign credential-executor (CES) binary
if [ -f "$MACOS_DIR/credential-executor" ]; then
CES_SIGN_FLAGS=(--force --sign "$SIGN_IDENTITY" "${CODESIGN_TS_FLAGS[@]}")
codesign "${CES_SIGN_FLAGS[@]}" "$MACOS_DIR/credential-executor"
echo "credential-executor binary signed"
fi

# Embedding runtime node_modules are no longer bundled (downloaded post-hatch).

# Sign any additional regular files directly under Contents/MacOS.
Expand All @@ -1400,6 +1451,7 @@ if [ -d "$MACOS_DIR" ]; then
! -name "vellum-cli" \
! -name "vellum-gateway" \
! -name "vellum-chrome-native-host" \
! -name "credential-executor" \
-exec codesign "${EXTRA_FILE_SIGN_FLAGS[@]}" {} \;
fi

Expand Down
Loading