Skip to content

fix(security-scan): handle SecretRef gateway auth credentials#674

Open
NePav wants to merge 1 commit into
builderz-labs:mainfrom
NePav:fix/security-scan-secretref-typeguard
Open

fix(security-scan): handle SecretRef gateway auth credentials#674
NePav wants to merge 1 commit into
builderz-labs:mainfrom
NePav:fix/security-scan-secretref-typeguard

Conversation

@NePav
Copy link
Copy Markdown

@NePav NePav commented May 12, 2026

Summary

Fixes a crash in runSecurityScan when gateway.auth.token or gateway.auth.password is a SecretRef object (e.g. { source: 'vault', ref: 'op://...' }, { source: 'file', path: '/path/to/token' }) rather than a plain string. The current code calls .trim() directly on these values, which throws:

TypeError: ((intermediate value) ?? "").trim is not a function
    at runSecurityScan (src/lib/security-scan.ts:312)

This makes both GET /api/security-audit and POST /api/security-scan return HTTP 500 for any install using SecretRef-based gateway auth — a common pattern with vault integrations on OpenClaw 2026.5+. The /debug page surfaces it as "Security scan error" in the logs, and the Settings panel's "Run security scan" button silently fails.

Repro

~/.openclaw/openclaw.json snippet that triggers it:

{
  "gateway": {
    "auth": {
      "mode": "token",
      "token": { "source": "file", "path": "/Users/me/.openclaw/secrets/gateway-token" }
    }
  }
}

Click "Run security scan" in Settings → 500. Server logs show the TypeError above.

Fix

Introduces a small hasCredential() helper in the gateway_auth check that treats:

  • string → trim and check length (original behavior, no change)
  • non-null object (SecretRef) → credential is configured; actual resolution happens at runtime by OpenClaw

If both branches fail (undefined / null), behavior is identical to before.

const hasCredential = (value: unknown): boolean => {
  if (typeof value === 'string') return value.trim().length > 0
  return value != null
}
const tokenOk = gwAuth?.mode === 'token' && hasCredential(gwAuth?.token)
const passwordOk = gwAuth?.mode === 'password' && hasCredential(gwAuth?.password)

Test plan

  • pnpm typecheck clean
  • pnpm vitest run src/lib/__tests__/security-scan — 4/4 pass (existing tests still green; no behavior change for the string path they cover)
  • Manual: with SecretRef-typed gateway.auth.token, GET /api/security-audit now returns 200 with gateway_auth: pass instead of 500
  • Manual: with plain-string gateway.auth.token, scan still returns the same pass/fail as before
  • Manual: with gateway.auth.token = '', scan still returns gateway_auth: fail as before
  • Manual: with no gateway.auth at all, scan still returns gateway_auth: fail as before

Notes

  • This does not validate that the SecretRef itself resolves to a non-empty string — that check would require live resolution and belongs in a separate runtime check. The intent of the gateway_auth security item is "is auth configured at all", which a SecretRef satisfies.
  • I'm happy to add a dedicated unit test for the gateway_auth check covering string / SecretRef / undefined / empty string cases if preferred — let me know.

The gateway_auth check in runSecurityScan called .trim() directly on
gateway.auth.token / gateway.auth.password values. These fields may be
plain strings OR SecretRef objects ({source:"vault", ref:"op://..."},
{source:"file", path:"..."}, etc.), in which case .trim is not a function
and the entire scan crashes with:

  TypeError: ((intermediate value) ?? "").trim is not a function

This made /api/security-audit and /api/security-scan return 500 for any
install using SecretRef-based gateway auth (a common pattern with vault
integrations).

Fix introduces a small hasCredential() helper that treats:
- string: trim and check length (original behavior)
- non-null object (SecretRef): credential is configured; resolution
  happens at runtime by OpenClaw

Verified with pnpm typecheck and existing security-scan unit tests.

Reproduces with gateway.auth.token = { source: "file", path: "/path/to/token" }
or any other SecretRef shape.
@NePav NePav requested a review from 0xNyk as a code owner May 12, 2026 14:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant