Skip to content

Gateway: add safer password-file input for gateway run#39067

Merged
vincentkoc merged 6 commits intoopenclaw:mainfrom
vincentkoc:vincentkoc-code/gateway-password-file
Mar 8, 2026
Merged

Gateway: add safer password-file input for gateway run#39067
vincentkoc merged 6 commits intoopenclaw:mainfrom
vincentkoc:vincentkoc-code/gateway-password-file

Conversation

@vincentkoc
Copy link
Copy Markdown
Member

Summary

  • Problem: openclaw gateway run --password <secret> exposes the gateway password in local process listings.
  • Why it matters: operators already have safer env/config SecretRef paths, but the foreground gateway CLI still encouraged an inline secret path.
  • What changed: added openclaw gateway run --password-file, warn on inline --password, and updated gateway CLI docs/changelog to prefer env or file-backed password input.
  • What did NOT change (scope boundary): gateway auth semantics, token handling, and remote RPC client credential flows.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

  • openclaw gateway run now accepts --password-file <path>.
  • Inline --password still works, but now prints a warning that it can leak through process listings.
  • Gateway CLI docs now recommend OPENCLAW_GATEWAY_PASSWORD, --password-file, or SecretRef-backed config for password auth.

Security Impact (required)

  • New permissions/capabilities? (Yes/No): No
  • Secrets/tokens handling changed? (Yes/No): Yes
  • New/changed network calls? (Yes/No): No
  • Command/tool execution surface changed? (Yes/No): No
  • Data access scope changed? (Yes/No): No
  • If any Yes, explain risk + mitigation:
    Password input for gateway run now has a file-backed path and inline password usage emits a warning. This reduces accidental secret exposure in local process listings without changing gateway auth policy.

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local pnpm worktree
  • Model/provider: n/a
  • Integration/channel (if any): n/a
  • Relevant config (redacted): none required

Steps

  1. Run openclaw gateway run --auth password --password-file /tmp/gateway-password.txt --allow-unconfigured.
  2. Verify the gateway start path receives the file-backed password.
  3. Run openclaw gateway run --auth password --password secret --allow-unconfigured and verify the warning is printed.

Expected

  • File-backed passwords are accepted without exposing the secret in argv.
  • Inline passwords still work but warn.

Actual

  • Matches expected in the new CLI regression tests.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: pnpm test src/cli/gateway-cli/run.option-collisions.test.ts
  • Edge cases checked: --password-file happy path, inline --password warning, --password + --password-file collision error
  • What you did not verify: full repo lint/test/build sweep; only the targeted gateway CLI regression test ran in this worktree

Compatibility / Migration

  • Backward compatible? (Yes/No): Yes
  • Config/env changes? (Yes/No): No
  • Migration needed? (Yes/No): No
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: stop using --password-file and fall back to OPENCLAW_GATEWAY_PASSWORD or prior inline --password behavior
  • Files/config to restore: src/cli/gateway-cli/run.ts
  • Known bad symptoms reviewers should watch for: gateway run rejecting valid password-file input or failing to warn on inline --password

Risks and Mitigations

  • Risk: The new option could conflict with parent/child commander option inheritance.
    • Mitigation: added regression coverage in src/cli/gateway-cli/run.option-collisions.test.ts.

@vincentkoc vincentkoc self-assigned this Mar 7, 2026
@openclaw-barnacle openclaw-barnacle bot added docs Improvements or additions to documentation cli CLI command changes size: S maintainer Maintainer-authored PR labels Mar 7, 2026
@vincentkoc vincentkoc marked this pull request as ready for review March 7, 2026 17:52
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 7, 2026

Greptile Summary

This PR adds a --password-file <path> option to openclaw gateway run as a safer alternative to the existing inline --password flag, which exposes secrets in local process listings. Using --password still works but now emits a warning on stderr; supplying both flags simultaneously is rejected with a clear error. Documentation and the changelog are updated accordingly.

Changes:

  • src/cli/gateway-cli/run.ts: new resolveGatewayPasswordOption helper handles the mutual-exclusion check, delegates file reads to the existing readSecretFromFile utility, and fires the deprecation warning when --password is used directly.
  • src/cli/gateway-cli/run.option-collisions.test.ts: three new regression tests cover the file-backed happy path, the inline-password warning, and the collision error.
  • docs/cli/gateway.md / docs/cli/index.md: --password-file documented; inline-password risk noted; env/file-backed input recommended.
  • CHANGELOG.md: entry added.

Issues found:

  • The two new tests that create temp directories via fs.mkdtemp do not clean them up after the test, which can accumulate stale files over repeated CI runs.
  • The collision error goes through String(err) on an Error object, producing "Error: Use either..." with a redundant prefix that is inconsistent with other error strings emitted in the same function.

Confidence Score: 4/5

  • This PR is safe to merge; the security improvement is well-scoped, backwards-compatible, and covered by targeted regression tests.
  • The implementation is straightforward and correctly delegates file reading to an existing utility. All three key scenarios (file path, inline warning, collision) are regression-tested. The only gaps are non-critical: missing temp-file cleanup in tests and a minor inconsistency in how the collision error message is prefixed.
  • No files require special attention; src/cli/gateway-cli/run.ts is the primary changed file and its logic is correct.

Last reviewed commit: 6713793

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@aisle-research-bot
Copy link
Copy Markdown

aisle-research-bot bot commented Mar 8, 2026

🔒 Aisle Security Analysis

We found 1 potential security issue(s) in this PR:

# Severity Title
1 🔵 Low Secret file reader lacks permission/symlink/size safeguards for --password-file

1. 🔵 Secret file reader lacks permission/symlink/size safeguards for --password-file

Property Value
Severity Low
CWE CWE-732
Location src/acp/secret-file.ts:4-21

Description

The new --password-file option reads the gateway password via readSecretFromFile(), which performs an unrestricted synchronous file read without basic secret-file safety checks.

Impacts:

  • Weak file permission handling: the password file may be group/world-readable and the CLI will still accept it, increasing the risk that other local users can read the gateway password.
  • Symlink/hardlink ambiguity: the function does not check for symlinks or ensure it is reading a regular file, so the resolved path could point somewhere unexpected.
  • Potential memory DoS: fs.readFileSync() reads the entire file into memory with no size cap.

Vulnerable code:

raw = fs.readFileSync(resolvedPath, "utf8");
const secret = raw.trim();

While the CLI is local, this still matters in shared-host or managed-install scenarios where secret files may be provisioned with overly-permissive modes, or where the CLI could be executed with attacker-influenced paths.

Recommendation

Harden secret-file loading:

  • Reject non-regular files and symlinks.
  • Enforce safe permissions (POSIX): require 0600 (or at least no group/other bits), and optionally require the file be owned by the current user.
  • Enforce a small maximum size (e.g., 4–64 KiB) and read via a file descriptor to avoid TOCTOU between stat and read.
  • Avoid over-detailed error messages if you consider full paths sensitive (optional).

Example (POSIX-aware) approach:

import fs from "node:fs";

const MAX_SECRET_BYTES = 64 * 1024;

export function readSecretFromFile(filePath: string, label: string): string {
  const resolvedPath = resolveUserPath(filePath.trim());
  if (!resolvedPath) throw new Error(`${label} file path is empty.`);// Open first, then fstat to minimize TOCTOU.
  const fd = fs.openSync(resolvedPath, fs.constants.O_RDONLY);
  try {
    const st = fs.fstatSync(fd);
    if (!st.isFile()) throw new Error(`${label} file must be a regular file.`);
    if (st.size > MAX_SECRET_BYTES) throw new Error(`${label} file is too large.`);// POSIX permission/ownership checks (skip on platforms without getuid).
    if (typeof process.getuid === "function") {
      if ((st.mode & 0o077) !== 0) {
        throw new Error(`${label} file permissions are too permissive (require 0600).`);
      }
      if (st.uid !== process.getuid()) {
        throw new Error(`${label} file must be owned by the current user.`);
      }
    }

    const buf = Buffer.allocUnsafe(Math.min(st.size, MAX_SECRET_BYTES));
    const bytesRead = fs.readSync(fd, buf, 0, buf.length, 0);
    const raw = buf.subarray(0, bytesRead).toString("utf8").replace(/^\uFEFF/, "");
    const secret = raw.trim();
    if (!secret) throw new Error(`${label} file is empty.`);
    return secret;
  } finally {
    fs.closeSync(fd);
  }
}

Analyzed PR: #39067 at commit a516ca5

Last updated on: 2026-03-08T02:25:21Z

Latest run failed. Keeping previous successful results. Trace ID: 019ccb3ba321ef2c3bdd00d68204d5ee.

Last updated on: 2026-03-08T02:25:37Z

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d56b80ca79

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@vincentkoc vincentkoc merged commit 4062aa5 into openclaw:main Mar 8, 2026
29 of 35 checks passed
@vincentkoc vincentkoc deleted the vincentkoc-code/gateway-password-file branch March 8, 2026 02:21
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 899cddc356

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +20 to +21
if (stat.isSymbolicLink()) {
throw new Error(`${label} file at ${resolvedPath} must not be a symlink.`);
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 Allow symlink-backed secret files

Hard-failing on stat.isSymbolicLink() breaks file-based auth in environments where mounted secrets are intentionally symlinked (for example, Kubernetes projected secrets where each key path points into ..data). Because readSecretFromFile is shared by gateway run and ACP secret-file flags, those flows now exit even though the secret payload is otherwise readable; this is a behavior regression from the previous implementation that accepted the path and read it.

Useful? React with 👍 / 👎.

openperf pushed a commit to openperf/moltbot that referenced this pull request Mar 8, 2026
* CLI: add gateway password-file option

* Docs: document safer gateway password input

* Update src/cli/gateway-cli/run.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Tests: clean up gateway password temp dirs

* CLI: restore gateway password warning flow

* Security: harden secret file reads

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
mcaxtr pushed a commit to mcaxtr/openclaw that referenced this pull request Mar 8, 2026
* CLI: add gateway password-file option

* Docs: document safer gateway password input

* Update src/cli/gateway-cli/run.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Tests: clean up gateway password temp dirs

* CLI: restore gateway password warning flow

* Security: harden secret file reads

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Saitop pushed a commit to NomiciAI/openclaw that referenced this pull request Mar 8, 2026
* CLI: add gateway password-file option

* Docs: document safer gateway password input

* Update src/cli/gateway-cli/run.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Tests: clean up gateway password temp dirs

* CLI: restore gateway password warning flow

* Security: harden secret file reads

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
GordonSH-oss pushed a commit to GordonSH-oss/openclaw that referenced this pull request Mar 9, 2026
* CLI: add gateway password-file option

* Docs: document safer gateway password input

* Update src/cli/gateway-cli/run.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Tests: clean up gateway password temp dirs

* CLI: restore gateway password warning flow

* Security: harden secret file reads

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
jenawant pushed a commit to jenawant/openclaw that referenced this pull request Mar 10, 2026
* CLI: add gateway password-file option

* Docs: document safer gateway password input

* Update src/cli/gateway-cli/run.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Tests: clean up gateway password temp dirs

* CLI: restore gateway password warning flow

* Security: harden secret file reads

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
dhoman pushed a commit to dhoman/chrono-claw that referenced this pull request Mar 11, 2026
* CLI: add gateway password-file option

* Docs: document safer gateway password input

* Update src/cli/gateway-cli/run.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Tests: clean up gateway password temp dirs

* CLI: restore gateway password warning flow

* Security: harden secret file reads

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
senw-developers pushed a commit to senw-developers/va-openclaw that referenced this pull request Mar 17, 2026
* CLI: add gateway password-file option

* Docs: document safer gateway password input

* Update src/cli/gateway-cli/run.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Tests: clean up gateway password temp dirs

* CLI: restore gateway password warning flow

* Security: harden secret file reads

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
V-Gutierrez pushed a commit to V-Gutierrez/openclaw-vendor that referenced this pull request Mar 17, 2026
* CLI: add gateway password-file option

* Docs: document safer gateway password input

* Update src/cli/gateway-cli/run.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Tests: clean up gateway password temp dirs

* CLI: restore gateway password warning flow

* Security: harden secret file reads

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 22, 2026
* CLI: add gateway password-file option

* Docs: document safer gateway password input

* Update src/cli/gateway-cli/run.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Tests: clean up gateway password temp dirs

* CLI: restore gateway password warning flow

* Security: harden secret file reads

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
(cherry picked from commit 4062aa5)
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 22, 2026
* CLI: add gateway password-file option

* Docs: document safer gateway password input

* Update src/cli/gateway-cli/run.ts

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Tests: clean up gateway password temp dirs

* CLI: restore gateway password warning flow

* Security: harden secret file reads

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
(cherry picked from commit 4062aa5)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli CLI command changes docs Improvements or additions to documentation maintainer Maintainer-authored PR size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security]: Gateway password visible in process arguments (ps aux)

1 participant