Skip to content

fix(http): accept IPv6 loopback Host headers - #172

Merged
ErikBjare merged 2 commits into
ActivityWatch:masterfrom
0xbrayo:fix/92-ipv6-host
Oct 19, 2026
Merged

ErikBjare merged 2 commits into
ActivityWatch:masterfrom
0xbrayo:fix/92-ipv6-host

Conversation

@0xbrayo

@0xbrayo 0xbrayo commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

Closes #92.

Parse Host headers as authorities so [::1] and [::1]:5600 reach the API instead of being rejected with HTTP 400. Allow IPv6 loopback alongside localhost and IPv4 loopback, retain configured-host matching, and reject malformed authority syntax, empty suffixes, invalid ports, userinfo, and URL path/query/fragment components.

Add Host-header regressions and a real HTTP request over an IPv6 loopback listener, with an explicit skip when IPv6 is unavailable. Document aw-server --host ::1, since a default localhost bind can resolve to IPv4 only. Include the new tests in make test for Windows, Linux, and macOS CI.

Validation: 75 tests passed locally, including the live IPv6 listener test; Ruff, Black, mypy, and git diff --check passed. The IPv6 tests reproduce HTTP 400 against the original code. All 75 tests also pass on Windows, Linux, and macOS CI, including the live IPv6 test on Windows.

@0xbrayo

0xbrayo commented Sep 24, 2026

Copy link
Copy Markdown
Member Author

🤖 Claude, on behalf of @0xbrayo

@greptile review

@greptile-apps

greptile-apps Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] This PR appears safe to merge; no actionable issues remain.

Summary

This PR accepts bracketed IPv6 loopback addresses in Host headers while retaining configured-host matching.

  • IPv6 loopback requests now pass the API's Host check.

Both earlier, unnumbered findings are addressed: empty suffixes are rejected, and the listener test compares decoded JSON instead of exact response bytes.

Reviews (3) · Last reviewed commit: "fix(http): reject malformed Host authori..." · Reviewed by Greptile

Comment thread aw_server/rest.py
Comment thread tests/test_host_header.py Outdated
@0xbrayo

0xbrayo commented Sep 24, 2026

Copy link
Copy Markdown
Member Author

🤖 Claude, on behalf of @0xbrayo

@greptile review

@TimeToBuildBob

Copy link
Copy Markdown
Contributor

Thanks @0xbrayo. I checked the authority parser against hostile inputs by running the same regex + urlsplit logic standalone, and every one of these is rejected: localhost.evil.com, [::1].evil, 127.0.0.1@evil, empty host, localhost:, localhost:99999, [::1]:abc, localhost., evil.com#localhost, localhost\@evil. Accepted: [::1], [::1]:5600, localhost:5600, LOCALHOST. The DNS-rebinding protection is preserved. Only observation (non-blocking): non-canonical IPv6 loopback spellings like [0:0:0:0:0:0:0:1] and [::ffff:127.0.0.1] are rejected, which is the conservative choice. LGTM from my side; CI is green.

@0xbrayo

0xbrayo commented Oct 19, 2026

Copy link
Copy Markdown
Member Author

🤖 Claude, on behalf of @0xbrayo

@greptile review

@ErikBjare
ErikBjare merged commit f8a352c into ActivityWatch:master Oct 19, 2026
9 checks passed
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.

IPv6 localhost [::1] server does not respond Windows 10

3 participants