Skip to content

fix(security): guard ClawHub downloads against redirect SSRF - #70334

Closed
zapabob wants to merge 3 commits into
NousResearch:mainfrom
zapabob:fix/clawhub-download-ssrf
Closed

fix(security): guard ClawHub downloads against redirect SSRF#70334
zapabob wants to merge 3 commits into
NousResearch:mainfrom
zapabob:fix/clawhub-download-ssrf

Conversation

@zapabob

@zapabob zapabob commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Salvage: fix(security): cap ClawHub ZIP downloads #57571 caps ClawHub ZIP download size but still used raw httpx.get(..., follow_redirects=True), so a CDN 302 could reach private/link-local addresses.
  • Route ZIP download and ClawHub _get_json through _guarded_http_get (SSRF + hop re-validation).
  • Member-path validation and size limits are unchanged.

Test plan

  • pytest tests/tools/test_skills_hub_clawhub_ssrf.py (2 passed)

Salvage NousResearch#57571 size-cap work: route ZIP/API fetches through
_guarded_http_get so CDN redirects cannot reach private targets.

Co-authored-by: Cursor <cursoragent@cursor.com>
@alt-glitch alt-glitch added type/security Security vulnerability or hardening tool/skills Skills system (list, view, manage) P3 Low — cosmetic, nice to have needs-repro Bug needs reproduction steps sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data labels Jul 23, 2026
Co-authored-by: Cursor <cursoragent@cursor.com>

@teknium1 teknium1 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.

Thanks for tracing the ClawHub ZIP redirect path. The premise is confirmed on current main: tools/skills_hub.py:2666-2670 still uses httpx.get(..., follow_redirects=True), while the existing guard at tools/skills_hub.py:302-338 validates redirect targets and uses the connect-time-safe client at tools/skills_hub.py:294-299.

Problems

  • tests/tools/test_skills_hub_clawhub_ssrf.py:10 mocks _guarded_http_get; it verifies delegation but not the security guarantee that a 302 to a private URL is rejected before a second connection.
  • Current main pruned 205 lines from tests/tools/test_skills_hub_clawhub.py in 39975613b1, including regions this PR modifies, so those legacy-test hunks need reconciliation during salvage.

Suggested changes

  • Add a focused redirect test that exercises _guarded_http_get through _download_zip and asserts the private Location is never requested.
  • Preserve the production fix and migrate relevant coverage into the new focused test file rather than retaining obsolete legacy-test edits.

This is an automated hermes-sweeper review.


def test_download_zip_uses_guarded_http_get():
src = ClawHubSource()
with patch("tools.skills_hub._guarded_http_get", return_value=None) as mock_get:

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.

Mocking _guarded_http_get only proves delegation. Add a regression that lets the guard handle a 302 Location to a private URL and verifies _ssrf_safe_http_get is never called for that private target.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 30, 2026
@Adolanium

Copy link
Copy Markdown
Contributor

This is a slice of #63920, not a leftover.

#63920 already routes ClawHub zip / catalog / JSON helpers through _guarded_http_get (and the other hub GETs). Open since Jul 13. This PR is the ClawHub-only cut from Jul 23, with #70330 / #70336 / #70343 doing the same for browse.sh, skills.sh, and GitHub.

"Not merged yet" is not the same as "ClawHub is unguarded." Please don't land this as the ClawHub fix over #63920.

zapabob added a commit to zapabob/hermes-agent-windows that referenced this pull request Aug 20, 2026
## Summary
- Move LobeHub index/agent fetches onto `_guarded_http_get` (SSRF + redirect hop checks).
- Sanitize `agent_id` to reject path traversal / scheme-bearing identifiers.
- Add unit tests for sanitization and guarded-fetch wiring.

## Salvage / credit
Skills Hub SSRF campaign siblings (NousResearch#70334 ClawHub, NousResearch#70336 skills.sh, NousResearch#70343 GitHub hub) — LobeHub still used raw `httpx.get`.
@zapabob

zapabob commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

Closing this overlapping ClawHub slice in favor of consolidated survivor #70343.

Its guarded ZIP download and private-redirect regression are preserved in #70343, now rebased onto official main d3e124601f54ad36f0115dc499e7620aa951d625 at head c46337e817a20826f9c459eccc019380c0d4ff63. The consolidated focused suite has 48 passing tests and Ruff/diff checks pass.

@zapabob zapabob closed this Aug 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-repro Bug needs reproduction steps P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data tool/skills Skills system (list, view, manage) type/security Security vulnerability or hardening

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants