Skip to content

Security fixes from the 2026-11-10 audit: pool API, redirects, NAT64, CSV, Discord embeds, SSH host keys, verified downloads - #375

Merged
maximilianfeix merged 3 commits into
mainfrom
fix/security-review
Nov 10, 2026
Merged

maximilianfeix merged 3 commits into
mainfrom
fix/security-review

Conversation

@maximilianfeix

Copy link
Copy Markdown
Owner

Part of #369. Fixes from a full-project security audit (no critical or high findings).

  • Rotating proxy server API (medium): without a password, the API now applies the same Host check as the status page (DNS rebinding), and /pop, /delete, /report refuse cross-site browser requests (Sec-Fetch-Site/Origin), also with a password. Without a password, upstream logins come back masked (user:•••@); with --serve-password the full URL is returned as documented. New section in docs/proxy-server.md.
  • Redirects: Authorization, Cookie and Proxy-Authorization are dropped when a redirect changes host or goes from https to http (the GitHub token used for discovery).
  • MCP fetch_url: target check now uses netpolicy.is_public_address, which refuses NAT64-wrapped private addresses.
  • CSV: cells starting with = + - @ tab CR get a leading apostrophe in proxies.csv (provider names come from the ASN database).
  • Discord bot: third-party text is markdown-escaped in embeds; backticks can't close code blocks.
  • Workflow: GitHub's SSH host keys are pinned in proxy-list.yml (StrictHostKeyChecking=yes); a test fails on accept-new anywhere.
  • Downloads: the live list and the country/ASN databases no longer fall back to unverified TLS.

Behaviour changes users may notice: API by host name without a password → 403 (use localhost/IP or set a password); masked logins without a password; CSV cells with a leading apostrophe; behind a TLS-inspecting firewall the live list fails instead of loading unverified.

…l checks

- Pool API (--serve): without --serve-password only requests addressed to an
  IP or localhost are answered (DNS rebinding); /pop, /delete and /report
  refuse cross-site browser requests (Sec-Fetch-Site / foreign Origin);
  upstream logins are masked unless the API is password-protected
- netio: Authorization, Cookie and Proxy-Authorization are dropped when a
  redirect changes the host or goes from https to http
- MCP fetch_url: use netpolicy.is_public_address (NAT64, 6to4, Teredo)
- proxies.csv: text cells starting with = + - @ tab CR get a leading '
- Discord bot: escape markdown in third-party fields, no backticks in code
- proxy-list workflow: pin GitHub's published SSH host keys
- live list and geo/ASN databases: no unverified TLS fallback
Comment thread tests/test_serve_api.py
["evil.example", f"evil.example:{port}", f"127.0.0.1:{port}", f"localhost:{port}", f"[::1]:{port}"]}

answers = run_server(client)
assert answers.pop("evil.example").startswith(b"HTTP/1.1 403")
Comment thread tests/test_serve_api.py

answers = run_server(client)
assert answers.pop("evil.example").startswith(b"HTTP/1.1 403")
assert answers.pop(next(h for h in answers if h.startswith("evil"))).startswith(b"HTTP/1.1 403")
@maximilianfeix
maximilianfeix merged commit 1441e27 into main Nov 10, 2026
16 of 25 checks passed
@maximilianfeix
maximilianfeix deleted the fix/security-review branch November 10, 2026 13:17
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