Skip to content

security: fix SSRF NameError, timing-safe OAuth, atomic credential perms#198

Closed
eesb99 wants to merge 4 commits intoCraftOS-dev:mainfrom
eesb99:security/fix-critical-vulnerabilities
Closed

security: fix SSRF NameError, timing-safe OAuth, atomic credential perms#198
eesb99 wants to merge 4 commits intoCraftOS-dev:mainfrom
eesb99:security/fix-critical-vulnerabilities

Conversation

@eesb99
Copy link
Copy Markdown
Contributor

@eesb99 eesb99 commented Apr 15, 2026

Summary

Commit 1: Fix bugs in existing security code

  • Fix socket.gaierror -> _socket.gaierror reference bug that silently disabled SSRF protection when DNS resolution failed
  • Use hmac.compare_digest() for OAuth state comparison to prevent timing side-channel attacks
  • Use os.open() with 0o600 mode for atomic credential file permissions instead of write-then-chmod race

Commit 2: Close architectural bypass vectors

  • SSRF redirect bypass [93]: Disable allow_redirects in requests lib, manually follow redirects with SSRF validation on each hop
  • SSRF fail-open [82]: Remove except Exception: pass -- DNS failures and unresolvable hostnames now block the request (fail closed)
  • CSRF enforcement [92]: Explicit 3-way state handling -- no state (warn + allow for providers that don't support it), state expected but missing from callback (reject), mismatch (reject)

Remaining architectural items (separate PR)

Priority File Issue
HIGH http_request.py DNS rebinding TOCTOU -- resolve-then-request pattern. Needs pinned-IP transport adapter.
MODERATE read_file.py, write_file.py Blocklist too narrow -- misses /etc/passwd, /proc/self/, .env. Consider allowlist approach.
MODERATE prompt_sanitizer.py Strip vs reject -- sequential re.sub can concatenate text into new payloads. Detect-and-reject is safer.
MODERATE prompt_sanitizer.py Overly broad regex -- matches "run", "import" in normal text. Now strips instead of just logging.

Follow-up from #195

Test plan

  • All modified files pass py_compile syntax check
  • Manual verification of SSRF blocking with redirect to metadata IP
  • Manual verification of OAuth flow with/without state parameter
  • Manual verification of HTTP request to unresolvable hostname returns error

🤖 Generated with Claude Code

eesb99 and others added 4 commits April 16, 2026 00:30
…dential storage, prompt injection)

- Fix reflected XSS in OAuth callback by HTML-escaping error parameter
- Add OAuth state parameter validation to prevent CSRF attacks
- Add SSRF protection to http_request action (block private IPs, cloud metadata)
- Add path traversal protection to read_file/write_file actions (block sensitive dirs)
- Set restrictive file permissions (0600) on stored credentials
- Make prompt sanitizer actually strip detected injection patterns instead of just logging

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ial perms

- Fix socket.gaierror -> _socket.gaierror reference bug that silently
  disabled SSRF protection when DNS resolution failed
- Use hmac.compare_digest() for OAuth state comparison to prevent
  timing side-channel attacks
- Use os.open() with 0o600 mode for atomic credential file permissions
  instead of write-then-chmod race

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rcement

SSRF (http_request.py):
- Extract _is_url_ssrf_safe() helper for reuse across redirect hops
- Disable allow_redirects in requests lib, manually follow redirects
  with SSRF validation on each hop (closes redirect bypass)
- Remove fail-open except Exception: pass -- DNS failures now block
  the request instead of silently allowing it
- Unresolvable hostnames return an error (fail closed)

OAuth CSRF (oauth_server.py):
- Explicit 3-way state handling: no state expected (warn + allow),
  state expected but missing from callback (reject), mismatch (reject)
- Previously silently skipped validation when state was absent

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- context/claude.md: Session 2 summary with unified review findings,
  implementation details, code design assessment, and advisor recommendations
- Updated PR references (CraftOS-dev#195 merged, CraftOS-dev#198 open)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@zfoong
Copy link
Copy Markdown
Collaborator

zfoong commented Apr 16, 2026

Some changes are repeated and are implemented in V1.2.3. Can you make another PR pointing at the V1.2.3 version branch?

@eesb99
Copy link
Copy Markdown
Contributor Author

eesb99 commented Apr 16, 2026

Superseded by #200 which targets V1.2.3 with only the incremental fixes (no duplication with #195).

@eesb99 eesb99 closed this Apr 16, 2026
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.

2 participants