Skip to content

fix(sandbox): resolve Slack Socket Mode invalid_auth startup crash (#2085)#2151

Merged
cv merged 10 commits into
NVIDIA:mainfrom
Dongni-Yang:fix/slack-socket-mode-2085
Apr 21, 2026
Merged

fix(sandbox): resolve Slack Socket Mode invalid_auth startup crash (#2085)#2151
cv merged 10 commits into
NVIDIA:mainfrom
Dongni-Yang:fix/slack-socket-mode-2085

Conversation

@Dongni-Yang

@Dongni-Yang Dongni-Yang commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Slack Socket Mode crashed on boot with invalid_auth due to three wiring gaps:

  1. onboard.tsopenshell sandbox create never forwarded SLACK_BOT_TOKEN/SLACK_APP_TOKEN as --env positional args, so the container env received nothing (or stale placeholder strings) instead of real token values.

  2. nemoclaw-start.sh — even with tokens in the container env, the baked openshell:resolve:env:* placeholders in openclaw.json were never resolved before OpenClaw read the file. Bolt validates appToken starts with xapp- in-process before any network call, so the L7 proxy never gets a chance to intercept — Bolt rejects the placeholder string immediately with invalid_auth.

  3. setupMessagingChannels() — interactive onboarding only prompted for SLACK_BOT_TOKEN (ch.envKey) and never for SLACK_APP_TOKEN (ch.appTokenEnvKey), so fresh interactive setups left the app token unconfigured, meaning gap 1's --env injection had nothing to forward.

This PR fixes all three gaps:

  • onboard.ts injects both tokens as --env KEY=VALUE positional args at sandbox-create time (same pattern as BRAVE_API_KEY).
  • setupMessagingChannels() now prompts for SLACK_APP_TOKEN after SLACK_BOT_TOKEN, using the existing appTokenHelp/appTokenLabel fields in KNOWN_CHANNELS.slack. Skips the channel if the app token is omitted (Socket Mode requires both).
  • nemoclaw-start.sh adds apply_slack_token_override, which runs as root before chattr +i locks openclaw.json. It substitutes the openshell:resolve:env:* placeholders with real token values read from the container env, then unsets the env vars before the first gosu sandbox child so tokens never reach sandbox or gateway processes. In the non-root fallback path, startup now fails fast with a clear error when SLACK_BOT_TOKEN is set (placeholder resolution requires root; Bolt would crash anyway).

Together these changes make the full resolution path deterministic and independent of OpenShell#894.

This PR also fixes a pre-existing bug in apply_model_override: NEMOCLAW_CONTEXT_WINDOW, NEMOCLAW_MAX_TOKENS, and NEMOCLAW_REASONING are baked into the image ENV and are always non-empty, so the function's guard always fired — but the code then read $NEMOCLAW_MODEL_OVERRIDE without a :- fallback, aborting the entrypoint under set -euo pipefail whenever only a context-window or reasoning override was set. Fixed by using ${NEMOCLAW_MODEL_OVERRIDE:-}.

Related Issue

Fixes #2085

How the fixes work together

Step What happens
User runs nemoclaw onboard interactively setupMessagingChannels() prompts for SLACK_BOT_TOKEN then SLACK_APP_TOKEN; both saved to credentials
openshell sandbox create is called onboard.ts passes --env SLACK_BOT_TOKEN=xoxb-… and --env SLACK_APP_TOKEN=xapp-… as positional args; tokens land in the container env
Container entrypoint runs as root apply_slack_token_override validates prefixes, patches openclaw.json placeholders in-place, recomputes sha256 hash
Before first gosu sandbox child unset SLACK_BOT_TOKEN SLACK_APP_TOKEN removes tokens from process env
OpenClaw reads openclaw.json Bolt sees real xoxb-/xapp- values, in-process validation passes, Socket Mode connects

Security properties

  • Tokens are set only as openshell sandbox create positional args (never in the subprocess spawn env, governed by buildSubprocessEnv()'s allowlist).
  • apply_slack_token_override is root-only, refuses symlinks, validates token prefixes (xoxb-/xapp-), and recomputes the integrity hash.
  • Tokens are unset before the first gosu sandbox child (not just before gateway start), so no sandbox-side process can inherit them from the env.
  • Non-root path fails fast with a clear error when SLACK_BOT_TOKEN is set, rather than silently starting with unresolved placeholders.

Changes

  • src/lib/onboard.ts: after the BRAVE_API_KEY block, push SLACK_BOT_TOKEN and (when present) SLACK_APP_TOKEN as --env positional args in openshell sandbox create. In setupMessagingChannels(), add prompt block for ch.appTokenEnvKey (parallel to serverIdEnvKey handling for Discord), so fresh interactive Slack onboarding captures both tokens.
  • test/onboard.test.ts: add SLACK_APP_TOKEN to child-script env; assert both tokens appear in the create command string; assert neither leaks into the spawn env.
  • scripts/nemoclaw-start.sh: add apply_slack_token_override (root-only, symlink-guarded, prefix-validated, hash-recomputed); call it in both paths; move unset SLACK_BOT_TOKEN SLACK_APP_TOKEN to before first gosu sandbox child; add non-root fail-fast when SLACK_BOT_TOKEN is set; apply shfmt/Prettier formatting. Also fix pre-existing unbound variable in apply_model_override: use ${NEMOCLAW_MODEL_OVERRIDE:-} so set -euo pipefail does not abort the entrypoint when NEMOCLAW_CONTEXT_WINDOW/NEMOCLAW_REASONING is set but NEMOCLAW_MODEL_OVERRIDE is not.
  • test/nemoclaw-start.test.ts: add describe block (11 tests) covering function definition, call order in both paths, no-op/root-only/symlink guards, prefix validation, missing-app-token warning, hash recompute, placeholder resolution, pre-gosu env scrub, and non-root fail-fast.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Verification

  • npx prek run --all-files passes
  • npm test passes (onboard: 129/129; nemoclaw-start: 85/85; plugin: 354/354)
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for user-facing behavior changes
  • make docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

AI Disclosure

  • AI-assisted — tool: Claude Code

Signed-off-by: Dongni Yang dongniy@nvidia.com

@Dongni-Yang Dongni-Yang self-assigned this Apr 21, 2026
@coderabbitai

coderabbitai Bot commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds conditional injection of Slack bot/app tokens into sandbox creation env and a startup routine that, on sandbox boot, validates and patches /sandbox/.openclaw/openclaw.json by resolving openshell:resolve:env: Slack placeholders to real tokens; tests updated to assert new injection and startup behavior.

Changes

Cohort / File(s) Summary
Sandbox creation
src/lib/onboard.ts
Populate envArgs for openshell sandbox create with SLACK_BOT_TOKEN when present and add SLACK_APP_TOKEN only when both bot and app tokens exist, placing these env assignments alongside existing CHAT_UI/BRAVE handling.
Sandbox startup token resolution
scripts/nemoclaw-start.sh
Add apply_slack_token_override() and invoke it in both non-root and root flows (after CORS override, before export); it validates xoxb-/xapp- prefixes, refuses symlinked config/hash, rewrites openclaw.json by replacing openshell:resolve:env: Slack placeholders with real tokens, recomputes config-hash, and in root mode unsets SLACK env vars before spawning child gosu sandbox. Minor formatting and control-flow-preserving tweaks included.
Onboard tests
test/onboard.test.ts
Update sandbox-creation tests to set SLACK_APP_TOKEN in the parent process, expect both SLACK_BOT_TOKEN and SLACK_APP_TOKEN to appear in the openshell sandbox create --env assignments, and strengthen spawn-env assertions to ensure Slack app token is not present in createCommand.env.
Startup script tests
test/nemoclaw-start.test.ts
Add tests asserting apply_slack_token_override presence and ordering (after apply_cors_override, before export_gateway_token) in both root/non-root paths; validate early-return when SLACK_BOT_TOKEN unset, root-only enforcement, symlink defenses, token-prefix checks, recompute of config-hash, placeholder resolution for both botToken and appToken, unsetting of SLACK env in root mode, and non-root fail-fast when tokens remain set. Minor matcher/formatting adjustments.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Onboard as "onboard (src/lib/onboard.ts)"
    participant SandboxEntrypoint as "sandbox entrypoint (scripts/nemoclaw-start.sh)"
    participant FS as "/sandbox/.openclaw/openclaw.json"
    participant ConfigHash as "config-hash (sha256)"
    participant Gateway as "gateway process"

    User->>Onboard: run sandbox create (includes --env SLACK_BOT_TOKEN / SLACK_APP_TOKEN when available)
    Onboard->>SandboxEntrypoint: start sandbox
    SandboxEntrypoint->>SandboxEntrypoint: apply_cors_override()
    SandboxEntrypoint->>SandboxEntrypoint: apply_slack_token_override()
    SandboxEntrypoint->>FS: read openclaw.json
    SandboxEntrypoint->>FS: replace openshell:resolve:env:... with real SLACK tokens
    SandboxEntrypoint->>ConfigHash: recompute/write config-hash
    SandboxEntrypoint->>SandboxEntrypoint: unset SLACK_BOT_TOKEN SLACK_APP_TOKEN (root)
    SandboxEntrypoint->>Gateway: start gateway with patched config
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I found the markers in the sand,
Swapped in keys with careful hand,
Rehashed the hash, then closed the gate,
Hid the tokens, sealed their fate,
Gateway springs up — no more bait. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR successfully addresses all coding objectives from issue #2085: appToken is now included in the baked config, placeholders are resolved via root-controlled injection and substitution, tokens are injected into sandbox creation, and tokens are unset before child processes to prevent exposure.
Out of Scope Changes check ✅ Passed Changes are in-scope: token injection and validation in onboard.ts/nemoclaw-start.sh, fix for unbound NEMOCLAW_MODEL_OVERRIDE variable, and corresponding test updates. All changes directly support issue #2085 objectives with no unrelated refactoring.
Title check ✅ Passed The PR title accurately describes the main security fix—resolving Slack Socket Mode invalid_auth startup crash by properly handling token injection and placeholder resolution across onboard.ts and nemoclaw-start.sh.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

…2085)

SLACK_BOT_TOKEN and SLACK_APP_TOKEN were stored as openshell provider
credentials but never forwarded as --env to the sandbox create command.
The baked openclaw.json uses openshell:resolve:env: placeholders for
both tokens; without the real values in the container env those
placeholders stay unresolved and Bolt Socket Mode crashes on boot with
invalid_auth.

Mirrors the existing BRAVE_API_KEY pattern: real token values are
injected as positional --env args (visible in the command string) while
remaining absent from the openshell subprocess spawn env, which is
governed by the separate blockedSandboxEnvNames allowlist.

Fixes NVIDIA#2085

Signed-off-by: Dongni Yang <dongniy@nvidia.com>
@Dongni-Yang Dongni-Yang force-pushed the fix/slack-socket-mode-2085 branch from aed6536 to 816efb7 Compare April 21, 2026 08:33
…artup

Add apply_slack_token_override to nemoclaw-start.sh (after apply_cors_override,
before chattr +i) using the same root-only, symlink-guarded, hash-recomputed
pattern as apply_model_override. The function substitutes openshell:resolve:env:
placeholders in openclaw.json directly, so Bolt's in-process appToken validation
(xapp- prefix check) passes before any network connection is opened — without
waiting for the L7 proxy.

Both SLACK_BOT_TOKEN and SLACK_APP_TOKEN are unset from the process env after
patching in the root path so tokens are not visible to the gateway or sandbox
user processes. Token format (xoxb-/xapp-) is validated before patching.

Signed-off-by: Dongni Yang <dongniy@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/nemoclaw-start.sh`:
- Line 935: The script currently calls apply_slack_token_override in a non-root
branch where that function is a no-op, allowing unresolved Slack placeholders to
slip through; update the startup logic so that before entering the non-root
fallback you detect Slack configuration (e.g., presence of SLACK_BOT_TOKEN or
unresolved openshell:resolve:env:* placeholders) and if the process is non-root
(id -u != 0) fail fast with a clear error and exit, or alternatively move the
placeholder resolution earlier so apply_slack_token_override runs while running
as root; reference apply_slack_token_override and the SLACK_BOT_TOKEN
placeholder checks when implementing this change.
- Around line 1074-1076: The Slack tokens are being unset too late (after
sandbox processes are already spawned); move the unset of SLACK_BOT_TOKEN and
SLACK_APP_TOKEN to immediately after apply_slack_token_override() so no
subsequent gosu sandbox child inherits them, or alternatively ensure every gosu
sandbox invocation clears them (e.g., prefix gosu calls with an explicit
environment scrub for SLACK_BOT_TOKEN/SLACK_APP_TOKEN or use env -u for those
vars before calling gosu); update the script locations around
apply_slack_token_override(), the gosu sandbox bash -c invocations and the exec
gosu "${NEMOCLAW_CMD[@]}" usages to apply the scrub consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 557aef15-1a63-4504-b978-1e769943e09f

📥 Commits

Reviewing files that changed from the base of the PR and between 816efb7 and b32f8af.

📒 Files selected for processing (2)
  • scripts/nemoclaw-start.sh
  • test/nemoclaw-start.test.ts
✅ Files skipped from review due to trivial changes (1)
  • test/nemoclaw-start.test.ts

Comment thread scripts/nemoclaw-start.sh
Comment thread scripts/nemoclaw-start.sh Outdated
…A#2085)

- Move `unset SLACK_BOT_TOKEN SLACK_APP_TOKEN` to before the first
  `gosu sandbox` child in the root path, so sandbox-side processes
  cannot inherit real token values
- Add fail-fast in the non-root path: exit 1 with a clear error when
  SLACK_BOT_TOKEN is set but placeholder resolution needs root
- Apply shfmt and Prettier formatting (case-statement indentation,
  line-continuation style) to pass CI pre-push hook

Signed-off-by: Dongni Yang <dongniy@nvidia.com>
Signed-off-by: Dongni Yang <dongniy@nvidia.com>
…under set -u

NEMOCLAW_CONTEXT_WINDOW, NEMOCLAW_MAX_TOKENS, and NEMOCLAW_REASONING are baked
into the image ENV and are always non-empty, so apply_model_override's guard
always fires. The previous `local model_override="$NEMOCLAW_MODEL_OVERRIDE"`
would abort the entrypoint under set -euo pipefail whenever an operator did not
pass NEMOCLAW_MODEL_OVERRIDE — causing apply_slack_token_override to never run.

Signed-off-by: Dongni Yang <dongniy@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/onboard.ts`:
- Around line 3656-3665: The interactive Slack onboarding never captures
SLACK_APP_TOKEN because setupMessagingChannels() only prompts/saves ch.envKey
(which becomes SLACK_BOT_TOKEN) and the existing env forwarding block only adds
SLACK_APP_TOKEN when it already exists in tokensByEnvKey; modify onboarding to
also prompt/save the app token key (SLACK_APP_TOKEN) during
setupMessagingChannels() and ensure tokensByEnvKey is populated with that key so
the envArgs push (using formatEnvAssignment and envArgs) will include
SLACK_APP_TOKEN even for fresh installs; update setupMessagingChannels(), the
ch.envKey handling, and any token-save logic to persist both SLACK_BOT_TOKEN and
SLACK_APP_TOKEN.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 9ed77f40-0a2d-4414-adc8-8d63386a657b

📥 Commits

Reviewing files that changed from the base of the PR and between 5659948 and 0a178d9.

📒 Files selected for processing (3)
  • scripts/nemoclaw-start.sh
  • src/lib/onboard.ts
  • test/nemoclaw-start.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • test/nemoclaw-start.test.ts
  • scripts/nemoclaw-start.sh

Comment thread src/lib/onboard.ts
Dongni-Yang and others added 4 commits April 21, 2026 19:09
…etup (NVIDIA#2085)

setupMessagingChannels() only prompted for ch.envKey (SLACK_BOT_TOKEN)
but never for ch.appTokenEnvKey (SLACK_APP_TOKEN). A fresh interactive
Slack onboard left the app token unconfigured, so the --env injection
added in the previous commit had nothing to forward.

Follows the same pattern as serverIdEnvKey handling (Discord guild ID)
and uses the appTokenHelp / appTokenLabel already defined in
KNOWN_CHANNELS.slack. Skips the channel if the app token is omitted
since Socket Mode requires both tokens.

Signed-off-by: Dongni Yang <dongniy@nvidia.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Dongni Yang <dongniy@nvidia.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Dongni Yang <dongniy@nvidia.com>
@Dongni-Yang Dongni-Yang changed the title fix(onboard): inject Slack tokens as --env in sandbox create fix(sandbox): resolve Slack Socket Mode invalid_auth startup crash (#2085) Apr 21, 2026
@ericksoa

Copy link
Copy Markdown
Contributor

Hey @Dongni-Yang — nice work on this one. The three-part fix is well-structured, the security properties are solid, and the tests are thorough. A few thoughts:

One thing to address

Partial resolution when SLACK_APP_TOKEN is missing — If someone sets SLACK_BOT_TOKEN but not SLACK_APP_TOKEN (e.g., a manual deployment outside the interactive onboard flow), apply_slack_token_override will resolve botToken to the real value but leave appToken as the unresolved openshell:resolve:env:SLACK_APP_TOKEN placeholder — with no warning. Bolt will still crash, and the operator won't have a clear signal about why.

Could you add a warning in apply_slack_token_override when the bot token is present but the app token is empty? Something like:

if [ -z "${SLACK_APP_TOKEN:-}" ]; then
  printf '[channels] Warning: SLACK_BOT_TOKEN is set but SLACK_APP_TOKEN is missing — Socket Mode requires both tokens\n' >&2
fi

That way non-interactive deployments get a clear hint before Bolt fails.

A couple of nits (feel free to address while you're in there)

  • json.dump(cfg, f, indent=2) will reformat the entire openclaw.json with Python's serialization style. Functionally fine (hash is recomputed), just worth being aware of if any downstream tooling diffs the config textually.
  • The non-root path calls apply_slack_token_override (no-op) then immediately checks SLACK_BOT_TOKEN to fail fast. You could fold that into the function itself (return non-zero when non-root and token is set) to keep the logic in one place — but the current approach with comments is clear enough, so no strong feelings here.

Thanks again for the thorough fix and test coverage!

@wscurran wscurran added NemoClaw CLI integration: slack Slack integration or channel behavior labels Apr 21, 2026
Add warning in apply_slack_token_override when the bot token is present
but the app token is absent so non-interactive deployments get a clear
signal before Bolt crashes with invalid_auth.

Resolves merge conflict in test/nemoclaw-start.test.ts with upstream/main:
keep NEMOCLAW_REASONING assertion and adopt upstream's shfmt-aware regex
for the return-0 guard check.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Dongni Yang <dongniy@nvidia.com>
@Dongni-Yang

Copy link
Copy Markdown
Contributor Author

Hey @Dongni-Yang — nice work on this one. The three-part fix is well-structured, the security properties are solid, and the tests are thorough. A few thoughts:

One thing to address

Partial resolution when SLACK_APP_TOKEN is missing — If someone sets SLACK_BOT_TOKEN but not SLACK_APP_TOKEN (e.g., a manual deployment outside the interactive onboard flow), apply_slack_token_override will resolve botToken to the real value but leave appToken as the unresolved openshell:resolve:env:SLACK_APP_TOKEN placeholder — with no warning. Bolt will still crash, and the operator won't have a clear signal about why.

Could you add a warning in apply_slack_token_override when the bot token is present but the app token is empty? Something like:

if [ -z "${SLACK_APP_TOKEN:-}" ]; then
  printf '[channels] Warning: SLACK_BOT_TOKEN is set but SLACK_APP_TOKEN is missing — Socket Mode requires both tokens\n' >&2
fi

That way non-interactive deployments get a clear hint before Bolt fails.

A couple of nits (feel free to address while you're in there)

  • json.dump(cfg, f, indent=2) will reformat the entire openclaw.json with Python's serialization style. Functionally fine (hash is recomputed), just worth being aware of if any downstream tooling diffs the config textually.
  • The non-root path calls apply_slack_token_override (no-op) then immediately checks SLACK_BOT_TOKEN to fail fast. You could fold that into the function itself (return non-zero when non-root and token is set) to keep the logic in one place — but the current approach with comments is clear enough, so no strong feelings here.

Thanks again for the thorough fix and test coverage!

Thanks for the thorough review!

Required change addressed — added the SLACK_APP_TOKEN missing warning to apply_slack_token_override (commit 7c19ffa). When SLACK_BOT_TOKEN is present but SLACK_APP_TOKEN is absent, the function now emits:

[channels] Warning: SLACK_BOT_TOKEN is set but SLACK_APP_TOKEN is missing — Socket Mode requires both tokens
A test for this path is included (85/85 pass).

Nits — will address both in a follow-up PR today:

json.dump reformatting → switch to regex-based substitution to preserve original openclaw.json formatting
non-root fail-fast → fold into apply_slack_token_override to keep the logic in one place

@Dongni-Yang Dongni-Yang requested a review from cv April 21, 2026 21:56
@cv cv merged commit 5a41bb3 into NVIDIA:main Apr 21, 2026
17 checks passed
@cv cv added the v0.0.22 label Apr 21, 2026
ericksoa pushed a commit that referenced this pull request Apr 22, 2026
## Summary

Two optional nits deferred from PR #2151 review:

- **Regex substitution** — replace `json.load` + `json.dump(cfg, f,
indent=2)` in `apply_slack_token_override` with `re.sub` targeting only
the two `openshell:resolve:env:SLACK_*` placeholder values in-place,
preserving original `openclaw.json` formatting
- **Fold non-root fail-fast into function** — when non-root and
`SLACK_BOT_TOKEN` is set, `apply_slack_token_override` now returns 1
directly (instead of returning 0 and relying on a separate post-call
guard at the call site); `set -euo pipefail` propagates the `return 1`
to a script exit with the same code and message as before

## Test plan

- [ ] `npx vitest run test/nemoclaw-start.test.ts` — 85/85 pass
- [ ] Two tests updated: "only applies override in root mode" (now also
asserts `return 1` on non-root+token path) and "fails fast when
SLACK_BOT_TOKEN is set in non-root mode" (now checks function body,
asserts no separate call-site guard)
- [ ] `shfmt -i 2 -ci -bn -l scripts/nemoclaw-start.sh` — no output
(clean)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Enhanced Slack token configuration validation to immediately fail with
specific error messages when attempting to use bot tokens in non-root
mode.

* **Tests**
* Updated tests to verify the new fail-fast security behavior for Slack
token overrides.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-by: Dongni Yang <dongniy@nvidia.com>

---------

Signed-off-by: Dongni Yang <dongniy@nvidia.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@wscurran wscurran added area: cli Command line interface, flags, terminal UX, or output bug-fix PR fixes a bug or regression and removed NemoClaw CLI labels Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: cli Command line interface, flags, terminal UX, or output bug-fix PR fixes a bug or regression integration: slack Slack integration or channel behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Slack Socket Mode crashes on boot with invalid_auth — appToken missing from baked openclaw.json; placeholder resolution also broken

4 participants