Skip to content

Harden MCP loopback request validation#66665

Merged
drobison00 merged 5 commits into
openclaw:mainfrom
eleqtrizit:fix/mcp-loopback-guards
Apr 14, 2026
Merged

Harden MCP loopback request validation#66665
drobison00 merged 5 commits into
openclaw:mainfrom
eleqtrizit:fix/mcp-loopback-guards

Conversation

@eleqtrizit

Copy link
Copy Markdown
Contributor

Summary

  • harden the local MCP loopback request gate before tool dispatch
  • keep existing local MCP workflows working while tightening browser-facing behavior

Changes

  • switch the loopback bearer comparison to safeEqualSecret instead of a plain string equality check
  • reject cross-site and non-loopback browser-origin requests before auth handling
  • add regression coverage for cross-origin rejection and loopback-origin acceptance paths

Validation

  • Ran pnpm test src/gateway/origin-check.test.ts
  • Ran pnpm test src/gateway/mcp-http.test.ts
  • Ran local agentic review with claude -p "/review" and added the suggested edge-case tests

Notes

  • Left x-openclaw-sender-is-owner behavior unchanged in this patch to avoid breaking current local MCP client flows
  • The repo-wide pre-commit pnpm check path is currently blocked by an unrelated existing import cycle in extensions/openai/*; the scoped gateway tests above passed for this change

@openclaw-barnacle openclaw-barnacle Bot added gateway Gateway runtime size: S maintainer Maintainer-authored PR labels Apr 14, 2026
@greptile-apps

greptile-apps Bot commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR hardens the MCP loopback request gate with two targeted changes: a browser-origin rejection layer (rejectsBrowserLoopbackRequest) that blocks cross-site and non-loopback Origin headers before auth handling, and a switch to safeEqualSecret (SHA-256 + timingSafeEqual) for the bearer token comparison. Four regression tests cover the new rejection and acceptance paths.

  • USER.md (P2): A work-log artifact from the automated security-review workflow was committed to the repo root and should be removed — its content belongs in the PR description, not in git history.

Confidence Score: 5/5

  • Safe to merge after removing USER.md from the commit.
  • All security logic changes are correct: the origin check flow handles all relevant header combinations (cross-site short-circuit, origin-only path, no-origin pass-through for native clients), placement before the auth check is intentional, and safeEqualSecret is a sound constant-time upgrade. The only finding is a P2 hygiene issue (work-log artifact committed to the repo root), which does not affect runtime behavior.
  • USER.md — should be dropped from the commit entirely before merging.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: USER.md
Line: 1-22

Comment:
**Work-log artifact should not be committed to the repo**

`USER.md` is an internal coordination/work-log created by the automated security-review workflow. Committing it to the repository root permanently records agentic session metadata (agent names, in-scope/out-of-scope decisions, explicit callouts of what was deliberately *not* fixed) into the public git history. This information is already captured in the PR description where it belongs. The file should be removed before merging.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(mcp): harden loopback request guards" | Re-trigger Greptile

Comment thread USER.md Outdated

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

Copy link
Copy Markdown

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: dfa8d31430

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/gateway/mcp-http.request.ts Outdated
@eleqtrizit eleqtrizit force-pushed the fix/mcp-loopback-guards branch from 3702396 to 7d975b0 Compare April 14, 2026 16:29
@drobison00 drobison00 force-pushed the fix/mcp-loopback-guards branch from 7d975b0 to 9233101 Compare April 14, 2026 20:03

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

Copy link
Copy Markdown

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: 9233101561

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/gateway/mcp-http.request.ts Outdated
eleqtrizit and others added 5 commits April 14, 2026 14:15
Out of scope for the MCP loopback hardening — keep this PR
focused on the loopback request gate and the bearer-comparison
fix. The pre-commit worklog guard can land separately if
maintainers want it.
The previous Sec-Fetch-Site early-return rejected legit local
browser callers like a UI hosted on http://localhost:<ui-port>
talking to MCP on http://127.0.0.1:<mcp-port> — browsers report
that host mismatch as cross-site even though both ends are
loopback. checkBrowserOrigin already authorizes those via its
local-loopback matcher (loopback peer + loopback Origin host),
so route every Origin-bearing request through that helper and
let it decide. Native MCP clients (no Origin header) continue to
short-circuit through to the bearer check unchanged.

Adds a regression test asserting that
  origin: http://localhost:43123, sec-fetch-site: cross-site
from a loopback peer is accepted with a valid bearer.
@drobison00 drobison00 force-pushed the fix/mcp-loopback-guards branch from 1d2c32c to 805186b Compare April 14, 2026 20:17
@drobison00 drobison00 merged commit 62430d9 into openclaw:main Apr 14, 2026
38 of 42 checks passed
kvnkho pushed a commit to kvnkho/openclaw that referenced this pull request Apr 17, 2026
* fix(mcp): harden loopback request guards

* fix(commit): block staged user log

* Revert pre-commit USER.md guard from this PR

Out of scope for the MCP loopback hardening — keep this PR
focused on the loopback request gate and the bearer-comparison
fix. The pre-commit worklog guard can land separately if
maintainers want it.

* changelog: note MCP loopback constant-time + Origin guard (openclaw#66665)

* fix(mcp): allow loopback flows that browsers flag as cross-site

The previous Sec-Fetch-Site early-return rejected legit local
browser callers like a UI hosted on http://localhost:<ui-port>
talking to MCP on http://127.0.0.1:<mcp-port> — browsers report
that host mismatch as cross-site even though both ends are
loopback. checkBrowserOrigin already authorizes those via its
local-loopback matcher (loopback peer + loopback Origin host),
so route every Origin-bearing request through that helper and
let it decide. Native MCP clients (no Origin header) continue to
short-circuit through to the bearer check unchanged.

Adds a regression test asserting that
  origin: http://localhost:43123, sec-fetch-site: cross-site
from a loopback peer is accepted with a valid bearer.

---------

Co-authored-by: Devin Robison <drobison@nvidia.com>
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
* fix(mcp): harden loopback request guards

* fix(commit): block staged user log

* Revert pre-commit USER.md guard from this PR

Out of scope for the MCP loopback hardening — keep this PR
focused on the loopback request gate and the bearer-comparison
fix. The pre-commit worklog guard can land separately if
maintainers want it.

* changelog: note MCP loopback constant-time + Origin guard (openclaw#66665)

* fix(mcp): allow loopback flows that browsers flag as cross-site

The previous Sec-Fetch-Site early-return rejected legit local
browser callers like a UI hosted on http://localhost:<ui-port>
talking to MCP on http://127.0.0.1:<mcp-port> — browsers report
that host mismatch as cross-site even though both ends are
loopback. checkBrowserOrigin already authorizes those via its
local-loopback matcher (loopback peer + loopback Origin host),
so route every Origin-bearing request through that helper and
let it decide. Native MCP clients (no Origin header) continue to
short-circuit through to the bearer check unchanged.

Adds a regression test asserting that
  origin: http://localhost:43123, sec-fetch-site: cross-site
from a loopback peer is accepted with a valid bearer.

---------

Co-authored-by: Devin Robison <drobison@nvidia.com>
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
* fix(mcp): harden loopback request guards

* fix(commit): block staged user log

* Revert pre-commit USER.md guard from this PR

Out of scope for the MCP loopback hardening — keep this PR
focused on the loopback request gate and the bearer-comparison
fix. The pre-commit worklog guard can land separately if
maintainers want it.

* changelog: note MCP loopback constant-time + Origin guard (openclaw#66665)

* fix(mcp): allow loopback flows that browsers flag as cross-site

The previous Sec-Fetch-Site early-return rejected legit local
browser callers like a UI hosted on http://localhost:<ui-port>
talking to MCP on http://127.0.0.1:<mcp-port> — browsers report
that host mismatch as cross-site even though both ends are
loopback. checkBrowserOrigin already authorizes those via its
local-loopback matcher (loopback peer + loopback Origin host),
so route every Origin-bearing request through that helper and
let it decide. Native MCP clients (no Origin header) continue to
short-circuit through to the bearer check unchanged.

Adds a regression test asserting that
  origin: http://localhost:43123, sec-fetch-site: cross-site
from a loopback peer is accepted with a valid bearer.

---------

Co-authored-by: Devin Robison <drobison@nvidia.com>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
* fix(mcp): harden loopback request guards

* fix(commit): block staged user log

* Revert pre-commit USER.md guard from this PR

Out of scope for the MCP loopback hardening — keep this PR
focused on the loopback request gate and the bearer-comparison
fix. The pre-commit worklog guard can land separately if
maintainers want it.

* changelog: note MCP loopback constant-time + Origin guard (openclaw#66665)

* fix(mcp): allow loopback flows that browsers flag as cross-site

The previous Sec-Fetch-Site early-return rejected legit local
browser callers like a UI hosted on http://localhost:<ui-port>
talking to MCP on http://127.0.0.1:<mcp-port> — browsers report
that host mismatch as cross-site even though both ends are
loopback. checkBrowserOrigin already authorizes those via its
local-loopback matcher (loopback peer + loopback Origin host),
so route every Origin-bearing request through that helper and
let it decide. Native MCP clients (no Origin header) continue to
short-circuit through to the bearer check unchanged.

Adds a regression test asserting that
  origin: http://localhost:43123, sec-fetch-site: cross-site
from a loopback peer is accepted with a valid bearer.

---------

Co-authored-by: Devin Robison <drobison@nvidia.com>
globalcaos pushed a commit to globalcaos/tinkerclaw that referenced this pull request May 13, 2026
* fix(mcp): harden loopback request guards

* fix(commit): block staged user log

* Revert pre-commit USER.md guard from this PR

Out of scope for the MCP loopback hardening — keep this PR
focused on the loopback request gate and the bearer-comparison
fix. The pre-commit worklog guard can land separately if
maintainers want it.

* changelog: note MCP loopback constant-time + Origin guard (openclaw#66665)

* fix(mcp): allow loopback flows that browsers flag as cross-site

The previous Sec-Fetch-Site early-return rejected legit local
browser callers like a UI hosted on http://localhost:<ui-port>
talking to MCP on http://127.0.0.1:<mcp-port> — browsers report
that host mismatch as cross-site even though both ends are
loopback. checkBrowserOrigin already authorizes those via its
local-loopback matcher (loopback peer + loopback Origin host),
so route every Origin-bearing request through that helper and
let it decide. Native MCP clients (no Origin header) continue to
short-circuit through to the bearer check unchanged.

Adds a regression test asserting that
  origin: http://localhost:43123, sec-fetch-site: cross-site
from a loopback peer is accepted with a valid bearer.

---------

Co-authored-by: Devin Robison <drobison@nvidia.com>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
* fix(mcp): harden loopback request guards

* fix(commit): block staged user log

* Revert pre-commit USER.md guard from this PR

Out of scope for the MCP loopback hardening — keep this PR
focused on the loopback request gate and the bearer-comparison
fix. The pre-commit worklog guard can land separately if
maintainers want it.

* changelog: note MCP loopback constant-time + Origin guard (openclaw#66665)

* fix(mcp): allow loopback flows that browsers flag as cross-site

The previous Sec-Fetch-Site early-return rejected legit local
browser callers like a UI hosted on http://localhost:<ui-port>
talking to MCP on http://127.0.0.1:<mcp-port> — browsers report
that host mismatch as cross-site even though both ends are
loopback. checkBrowserOrigin already authorizes those via its
local-loopback matcher (loopback peer + loopback Origin host),
so route every Origin-bearing request through that helper and
let it decide. Native MCP clients (no Origin header) continue to
short-circuit through to the bearer check unchanged.

Adds a regression test asserting that
  origin: http://localhost:43123, sec-fetch-site: cross-site
from a loopback peer is accepted with a valid bearer.

---------

Co-authored-by: Devin Robison <drobison@nvidia.com>
jameslcowan pushed a commit to jameslcowan/openclaw that referenced this pull request Jun 2, 2026
* fix(mcp): harden loopback request guards

* fix(commit): block staged user log

* Revert pre-commit USER.md guard from this PR

Out of scope for the MCP loopback hardening — keep this PR
focused on the loopback request gate and the bearer-comparison
fix. The pre-commit worklog guard can land separately if
maintainers want it.

* changelog: note MCP loopback constant-time + Origin guard (openclaw#66665)

* fix(mcp): allow loopback flows that browsers flag as cross-site

The previous Sec-Fetch-Site early-return rejected legit local
browser callers like a UI hosted on http://localhost:<ui-port>
talking to MCP on http://127.0.0.1:<mcp-port> — browsers report
that host mismatch as cross-site even though both ends are
loopback. checkBrowserOrigin already authorizes those via its
local-loopback matcher (loopback peer + loopback Origin host),
so route every Origin-bearing request through that helper and
let it decide. Native MCP clients (no Origin header) continue to
short-circuit through to the bearer check unchanged.

Adds a regression test asserting that
  origin: http://localhost:43123, sec-fetch-site: cross-site
from a loopback peer is accepted with a valid bearer.

---------

Co-authored-by: Devin Robison <drobison@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime maintainer Maintainer-authored PR size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants