Skip to content

Commit a8e3ad9

Browse files
committed
bridge: migrate protected slack-bridge path to /opt release
1 parent 7211cab commit a8e3ad9

4 files changed

Lines changed: 40 additions & 26 deletions

File tree

bin/deploy.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,14 @@ deploy_runtime_asset_entry() {
293293

294294
bb_manifest_for_each RUNTIME_ASSET_MANIFEST deploy_runtime_asset_entry
295295

296+
# Clean up legacy bridge runtime path; bridge now runs from /opt release only.
297+
if [ "$DRY_RUN" -eq 0 ]; then
298+
as_agent bash -c "rm -rf '$BAUDBOT_HOME/runtime/slack-bridge'"
299+
log "✓ removed legacy runtime/slack-bridge"
300+
else
301+
log "would remove: runtime/slack-bridge (legacy path)"
302+
fi
303+
296304
# ── Memory Seeds ─────────────────────────────────────────────────────────────
297305

298306
MEMORY_SEED_DIR="$STAGE_DIR/skills/control-agent/memory"

pi/extensions/tool-guard.test.mjs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const BASH_DENY_RULES = [
4646
{ id: "chmod-baudbot-source", pattern: new RegExp(`chmod\\b.*${escapeRegex(BAUDBOT_SOURCE_DIR)}`), label: "chmod on baudbot source repo", severity: "block" },
4747
{ id: "chown-baudbot-source", pattern: new RegExp(`chown\\b.*${escapeRegex(BAUDBOT_SOURCE_DIR)}`), label: "chown on baudbot source repo", severity: "block" },
4848
{ id: "tee-baudbot-source", pattern: new RegExp(`tee\\s+.*${escapeRegex(BAUDBOT_SOURCE_DIR)}/`), label: "tee write to baudbot source repo", severity: "block" },
49-
{ id: "chmod-runtime-security", pattern: /chmod\b.*\/(\.pi\/agent\/extensions\/tool-guard|runtime\/slack-bridge\/security)\./, label: "chmod on protected runtime security file", severity: "block" },
49+
{ id: "chmod-runtime-security", pattern: /chmod\b.*\/(\.pi\/agent\/extensions\/tool-guard|runtime\/slack-bridge\/security|opt\/baudbot\/current\/slack-bridge\/security)\./, label: "chmod on protected runtime security file", severity: "block" },
5050
// Credential exfiltration
5151
{ id: "env-exfil-curl", pattern: /\benv\b.*\|\s*(curl|wget|nc)\b/, label: "Piping environment to network tool", severity: "block" },
5252
{ id: "cat-env-curl", pattern: /cat\s+.*\.env.*\|\s*(curl|wget|nc)\b/, label: "Exfiltrating .env via network", severity: "block" },
@@ -77,8 +77,8 @@ function isAllowedWritePath(filePath) {
7777
const PROTECTED_RUNTIME_FILES = [
7878
`${AGENT_HOME}/.pi/agent/extensions/tool-guard.ts`,
7979
`${AGENT_HOME}/.pi/agent/extensions/tool-guard.test.mjs`,
80-
`${AGENT_HOME}/runtime/slack-bridge/security.mjs`,
81-
`${AGENT_HOME}/runtime/slack-bridge/security.test.mjs`,
80+
`/opt/baudbot/current/slack-bridge/security.mjs`,
81+
`/opt/baudbot/current/slack-bridge/security.test.mjs`,
8282
];
8383

8484
function isProtectedPath(filePath) {
@@ -307,7 +307,7 @@ describe("tool-guard: source repo protection (bash)", () => {
307307
assert.equal(checkBashCommand(`chmod a+w ${AGENT_HOME}/.pi/agent/extensions/tool-guard.ts`).blocked, true);
308308
});
309309
it("blocks chmod on runtime security.mjs", () => {
310-
assert.equal(checkBashCommand(`chmod 777 ${AGENT_HOME}/runtime/slack-bridge/security.mjs`).blocked, true);
310+
assert.equal(checkBashCommand("chmod 777 /opt/baudbot/current/slack-bridge/security.mjs").blocked, true);
311311
});
312312
});
313313

@@ -358,8 +358,8 @@ describe("tool-guard: workspace confinement (allow-list)", () => {
358358
it(`allows write to ${AGENT_HOME}/.pi/agent/skills/new-skill/SKILL.md`, () => {
359359
assert.equal(checkWritePath(`${AGENT_HOME}/.pi/agent/skills/new-skill/SKILL.md`), false);
360360
});
361-
it(`allows write to ${AGENT_HOME}/runtime/slack-bridge/bridge.mjs`, () => {
362-
assert.equal(checkWritePath(`${AGENT_HOME}/runtime/slack-bridge/bridge.mjs`), false);
361+
it("blocks write to /opt/baudbot/current/slack-bridge/bridge.mjs", () => {
362+
assert.equal(checkWritePath("/opt/baudbot/current/slack-bridge/bridge.mjs"), true);
363363
});
364364

365365
// BLOCKED: outside agent home
@@ -430,13 +430,13 @@ describe("tool-guard: protected runtime security files", () => {
430430
assert.equal(checkWritePath(`${AGENT_HOME}/.pi/agent/extensions/tool-guard.test.mjs`), true);
431431
});
432432
it("blocks write to runtime security.mjs", () => {
433-
assert.equal(checkWritePath(`${AGENT_HOME}/runtime/slack-bridge/security.mjs`), true);
433+
assert.equal(checkWritePath("/opt/baudbot/current/slack-bridge/security.mjs"), true);
434434
});
435435
it("blocks write to runtime security.test.mjs", () => {
436-
assert.equal(checkWritePath(`${AGENT_HOME}/runtime/slack-bridge/security.test.mjs`), true);
436+
assert.equal(checkWritePath("/opt/baudbot/current/slack-bridge/security.test.mjs"), true);
437437
});
438-
it("allows write to runtime bridge.mjs (agent-modifiable)", () => {
439-
assert.equal(checkWritePath(`${AGENT_HOME}/runtime/slack-bridge/bridge.mjs`), false);
438+
it("blocks write to runtime bridge.mjs (immutable release path)", () => {
439+
assert.equal(checkWritePath("/opt/baudbot/current/slack-bridge/bridge.mjs"), true);
440440
});
441441
it("allows write to runtime non-security extensions", () => {
442442
assert.equal(checkWritePath(`${AGENT_HOME}/.pi/agent/extensions/auto-name.ts`), false);

pi/extensions/tool-guard.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ const BASH_DENY_RULES: DenyRule[] = [
253253
] : []),
254254
{
255255
id: "chmod-runtime-security",
256-
pattern: /chmod\b.*\/(\.pi\/agent\/extensions\/tool-guard|runtime\/slack-bridge\/security)\./,
256+
pattern: /chmod\b.*\/(\.pi\/agent\/extensions\/tool-guard|runtime\/slack-bridge\/security|opt\/baudbot\/current\/slack-bridge\/security)\./,
257257
label: "chmod on protected runtime security file",
258258
severity: "block" as const,
259259
tier: "high" as const,
@@ -311,8 +311,8 @@ function isAllowedWritePath(filePath: string): boolean {
311311
const PROTECTED_RUNTIME_FILES = [
312312
`${AGENT_HOME}/.pi/agent/extensions/tool-guard.ts`,
313313
`${AGENT_HOME}/.pi/agent/extensions/tool-guard.test.mjs`,
314-
`${AGENT_HOME}/runtime/slack-bridge/security.mjs`,
315-
`${AGENT_HOME}/runtime/slack-bridge/security.test.mjs`,
314+
`/opt/baudbot/current/slack-bridge/security.mjs`,
315+
`/opt/baudbot/current/slack-bridge/security.test.mjs`,
316316
];
317317

318318
function isProtectedPath(filePath: string): boolean {

pi/skills/control-agent/startup-cleanup.sh

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,23 @@ set -euo pipefail
1616
# processes and causes `varlock run` to treat subcommands as Node module paths).
1717
unset PKG_EXECPATH 2>/dev/null || true
1818

19+
RUNTIME_NODE_HELPER="$HOME/runtime/bin/lib/runtime-node.sh"
20+
if [ -r "$RUNTIME_NODE_HELPER" ]; then
21+
# shellcheck source=bin/lib/runtime-node.sh
22+
source "$RUNTIME_NODE_HELPER"
23+
fi
24+
1925
BRIDGE_POLICY_HELPER="$HOME/runtime/bin/lib/bridge-restart-policy.sh"
2026
if [ -r "$BRIDGE_POLICY_HELPER" ]; then
2127
# shellcheck source=bin/lib/bridge-restart-policy.sh
2228
source "$BRIDGE_POLICY_HELPER"
2329
fi
2430

31+
NODE_BIN_DIR="${NODE_BIN_DIR:-$HOME/opt/node/bin}"
32+
if command -v bb_resolve_runtime_node_bin_dir >/dev/null 2>&1; then
33+
NODE_BIN_DIR="$(bb_resolve_runtime_node_bin_dir "$HOME")"
34+
fi
35+
2536
SOCKET_DIR="$HOME/.pi/session-control"
2637

2738
if [ $# -eq 0 ]; then
@@ -145,26 +156,21 @@ echo "Starting slack-bridge ($BRIDGE_SCRIPT) with PI_SESSION_ID=$MY_UUID..."
145156
mkdir -p "$BRIDGE_LOG_DIR"
146157
(
147158
unset PKG_EXECPATH
148-
# Clear ALL varlock-managed env vars inherited from the parent session.
149-
# varlock run does not override vars already set in the environment, so
150-
# stale values (e.g. expired broker tokens) would leak through. By unsetting
151-
# every key varlock manages, we guarantee varlock run injects fresh values
152-
# from ~/.config/.env on every bridge restart.
153-
if command -v varlock >/dev/null 2>&1; then
154-
while IFS='=' read -r key _; do
155-
[ -n "$key" ] && unset "$key"
156-
done < <(varlock load --path "$HOME/.config/" --format env --compact 2>/dev/null)
157-
fi
158-
export PATH="$HOME/.varlock/bin:$HOME/opt/node/bin:$PATH"
159+
export PATH="$NODE_BIN_DIR:$PATH"
159160
export PI_SESSION_ID="$MY_UUID"
160161
cd /opt/baudbot/current/slack-bridge
161162

162163
if command -v bb_bridge_supervise >/dev/null 2>&1; then
163164
bb_bridge_supervise "$BRIDGE_LOG_FILE" "$BRIDGE_STATUS_FILE" "$BRIDGE_SCRIPT" \
164-
varlock run --path ~/.config/ -- node "$BRIDGE_SCRIPT"
165+
bash -lc 'for v in $(env | grep ^SLACK_BROKER_ | cut -d= -f1 || true); do unset "$v"; done; set -a; source "$HOME/.config/.env"; set +a; node "$1"' -- "$BRIDGE_SCRIPT"
165166
else
166167
while true; do
167-
if varlock run --path ~/.config/ -- node "$BRIDGE_SCRIPT" >>"$BRIDGE_LOG_FILE" 2>&1; then
168+
for v in $(env | grep ^SLACK_BROKER_ | cut -d= -f1 || true); do unset "$v"; done
169+
set -a
170+
# shellcheck disable=SC1090 # path is dynamic (agent home)
171+
source "$HOME/.config/.env"
172+
set +a
173+
if node "$BRIDGE_SCRIPT" >>"$BRIDGE_LOG_FILE" 2>&1; then
168174
exit_code=0
169175
else
170176
exit_code=$?

0 commit comments

Comments
 (0)