Skip to content

fix(policy): block POST to sentry.io to prevent multi-tenant data exfiltration (#1437)#1625

Merged
ericksoa merged 9 commits intomainfrom
fix/1437-sentry-block-post-exfiltration
Apr 9, 2026
Merged

fix(policy): block POST to sentry.io to prevent multi-tenant data exfiltration (#1437)#1625
ericksoa merged 9 commits intomainfrom
fix/1437-sentry-block-post-exfiltration

Conversation

@cv
Copy link
Copy Markdown
Contributor

@cv cv commented Apr 8, 2026

Summary

Closes #1437. Supersedes #1565.

  • Merges main to resolve conflicts, then replaces the two path-scoped POST rules (/api/*/envelope/** and /api/*/store/**) with GET /** on the sentry.io endpoint
  • POST removal: the path-scoped POST rules were insufficient because the Sentry project ID is part of the URL and attacker-controlled — a compromised agent could POST data to any Sentry project
  • GET retention: GET has no request body and is bounded by URL length limits, keeping read-only Sentry SDK paths (e.g. DSN config) functional

Credit to @ColinM-sys for the original analysis and fix in #1565 (fork was unreachable behind a proxy, so we had to reopen from origin).

Test plan

  • Verify sentry.io endpoint in nemoclaw-blueprint/policies/openclaw-sandbox.yaml has only a GET rule, no POST
  • Run npm test to confirm no test regressions
  • Verify policy YAML is syntactically valid

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Updated network access policies for an external monitoring host so only GET requests are permitted; other request methods have been removed.
  • Tests
    • Added regression tests to assert that the monitoring host endpoints include GET and do not include POST, ensuring policy enforcement.

ColinM-sys and others added 3 commits April 7, 2026 01:31
…iltration

sentry.io is a multi-tenant SaaS — any client with a project ID can POST
to any Sentry project, not just NemoClaw's. The baseline sandbox policy
allowed POST to sentry.io with path '/**', which turned the host into a
generic exfiltration channel: a compromised agent inside the sandbox
could ship stack traces, env vars, file contents, etc. to a Sentry
project controlled by an attacker via the public envelope endpoint
(https://sentry.io/api/<any-project-id>/envelope/). Path-pattern
restrictions cannot fix this because the project ID is part of the URL
and there is no server-side allowlist of legitimate projects.

This is a follow-up to #1214 (which added 'protocol: rest' for
sentry.io) — that PR closed the wire-protocol gap, this PR closes the
remaining HTTP-method-level gap.

Changes:

- nemoclaw-blueprint/policies/openclaw-sandbox.yaml: drop the
  'method: POST, path: /**' allow rule for sentry.io. GET stays
  allowed because GET has no request body and is harmless for exfil.
  Side effect: Claude Code's crash telemetry to Sentry is silently
  dropped. That is the correct tradeoff for a sandbox whose stated
  goal is preventing data egress, and the sandbox already blocks many
  similar telemetry channels by default.

- test/validate-blueprint.test.ts: walk every endpoint in
  network_policies, find sentry.io, and assert (a) at least one
  sentry.io entry exists, (b) no sentry.io entry has a POST allow
  rule, (c) the GET allow rule is preserved. Verified by stashing
  the policy fix and re-running: the test correctly fails on main
  with the unfixed policy, and passes with the fix in place.

Closes #1437
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The path-scoped POST rules (/api/*/envelope/** and /api/*/store/**)
do not prevent multi-tenant exfiltration because the Sentry project ID
is part of the URL and attacker-controlled. Replace with GET-only:
GET has no request body and is bounded by URL length limits, keeping
read-only Sentry SDK paths (e.g. DSN config) functional.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@cv cv added security Something isn't secure priority: high Important issue that should be resolved in the next release fix policy v0.0.10 Release target labels Apr 8, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 8, 2026

📝 Walkthrough

Walkthrough

The PR updates the OpenClaw sandbox network policy to change the sentry.io endpoint rules: POST access to previous envelope/store paths was removed and only GET requests to all paths are now permitted for sentry.io.

Changes

Cohort / File(s) Summary
Sandbox network policy
nemoclaw-blueprint/policies/openclaw-sandbox.yaml
Replaced prior POST-allowing rules for host: sentry.io (/api/*/envelope/**, /api/*/store/**) with a single rule permitting only GET on path: "/**".
Validation tests
test/validate-blueprint.test.ts
Added findEndpoints helper and types plus two regression tests asserting sentry.io endpoints do not allow POST (case-insensitive) and do allow GET.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hopped through rules both day and night,
I chased the POST away from sight,
Now GETs may roam the open sea,
But envelopes can't carry me.
Hooray — safe sandbox, safe and bright! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: blocking POST requests to sentry.io to prevent data exfiltration, matching the primary objective of the PR.
Linked Issues check ✅ Passed The code changes fully address the requirements in issue #1437 by removing POST endpoints to sentry.io and retaining only GET access, mitigating the data exfiltration vulnerability.
Out of Scope Changes check ✅ Passed All changes are directly in scope: policy rule modification for sentry.io and corresponding regression tests; no unrelated alterations detected.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/1437-sentry-block-post-exfiltration

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

@cv cv enabled auto-merge (squash) April 8, 2026 20:46
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
nemoclaw-blueprint/policies/openclaw-sandbox.yaml (1)

99-99: Optionally narrow the remaining GET allow.

GET "/**" still leaves the whole host reachable. If Claude Code only needs a small set of Sentry bootstrap/config routes, an explicit GET allowlist would better match the file’s deny-by-default posture and further reduce the residual egress surface.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nemoclaw-blueprint/policies/openclaw-sandbox.yaml` at line 99, The current
rule allow: { method: GET, path: "/**" } is too broad; replace that wildcard GET
allow with an explicit allowlist of only the Sentry/bootstrap/config endpoints
Claude Code needs (e.g., the specific paths used for Sentry init/config), so
instead of GET "/**" add individual GET rules for each required route and remove
the catch-all; update the policy block containing allow: { method: GET, path:
"/**" } to enumerate the precise paths to reduce egress surface and preserve the
deny-by-default posture.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@nemoclaw-blueprint/policies/openclaw-sandbox.yaml`:
- Line 99: The current rule allow: { method: GET, path: "/**" } is too broad;
replace that wildcard GET allow with an explicit allowlist of only the
Sentry/bootstrap/config endpoints Claude Code needs (e.g., the specific paths
used for Sentry init/config), so instead of GET "/**" add individual GET rules
for each required route and remove the catch-all; update the policy block
containing allow: { method: GET, path: "/**" } to enumerate the precise paths to
reduce egress surface and preserve the deny-by-default posture.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 86ffe17a-5239-4e61-927a-de4313712413

📥 Commits

Reviewing files that changed from the base of the PR and between e2bfdcf and 045745d.

📒 Files selected for processing (1)
  • nemoclaw-blueprint/policies/openclaw-sandbox.yaml

cv and others added 2 commits April 8, 2026 17:13
The original contributor commit (1fd6e07) included regression tests
that assert no POST rules exist for sentry.io in the sandbox policy.
These were accidentally dropped during merge conflict resolution at
2c20c73. Restore them verbatim.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
test/validate-blueprint.test.ts (1)

181-189: Make the GET regression test non-vacuous on its own.

If this test is run in isolation, it can pass even when sentry.io is missing entirely. Add an explicit existence assertion here too.

Suggested diff
   it("regression `#1437`: sentry.io retains GET (harmless, no body for exfil)", () => {
     const sentryEndpoints = findEndpoints((h) => h === "sentry.io");
+    expect(sentryEndpoints.length).toBeGreaterThan(0);
     for (const ep of sentryEndpoints) {
       const rules = Array.isArray(ep.rules) ? ep.rules : [];
       const hasGet = rules.some(
         (r) => r && r.allow && typeof r.allow.method === "string" && r.allow.method.toUpperCase() === "GET",
       );
       expect(hasGet).toBe(true);
     }
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/validate-blueprint.test.ts` around lines 181 - 189, The test currently
only checks that any found sentry.io endpoints allow GET, but it can pass
vacuously if none are found; ensure the test asserts the endpoints exist by
adding an explicit existence assertion on sentryEndpoints (e.g.,
expect(sentryEndpoints.length).toBeGreaterThan(0)) immediately after const
sentryEndpoints = findEndpoints((h) => h === "sentry.io"); so that the loop over
sentryEndpoints and the hasGet check actually validate real entries.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@test/validate-blueprint.test.ts`:
- Around line 181-189: The test currently only checks that any found sentry.io
endpoints allow GET, but it can pass vacuously if none are found; ensure the
test asserts the endpoints exist by adding an explicit existence assertion on
sentryEndpoints (e.g., expect(sentryEndpoints.length).toBeGreaterThan(0))
immediately after const sentryEndpoints = findEndpoints((h) => h ===
"sentry.io"); so that the loop over sentryEndpoints and the hasGet check
actually validate real entries.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5d1fafa0-a397-475d-bf66-d3329a5ac28e

📥 Commits

Reviewing files that changed from the base of the PR and between 045745d and bdacd2c.

📒 Files selected for processing (1)
  • test/validate-blueprint.test.ts

Copy link
Copy Markdown
Contributor

@ericksoa ericksoa left a comment

Choose a reason for hiding this comment

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

Policy change is correct — blocks POST to sentry.io to close the multi-tenant exfiltration vector. GET-only is safe (no request body). Restored the regression tests that were dropped during merge conflict resolution. LGTM.

@ericksoa ericksoa merged commit 19839be into main Apr 9, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix policy priority: high Important issue that should be resolved in the next release security Something isn't secure v0.0.10 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sentry.io Allowed in Baseline Policy With POST to /** — Potential Data Exfiltration - IssueFinder - SN 13

4 participants