6 Commits

Author SHA1 Message Date
Alexandre Teixeira
9ffa87e394 fix(tests): make webhook SSRF test clean-worktree deterministic
Test-only fix continuing #2523. Makes the webhook SSRF test deterministic in clean worktrees without creating ./data or repo-local DB artifacts.
2026-06-05 08:16:28 +01:00
Alexandre Teixeira
a9c1c698b0 refactor(tests): add import-state isolation helper
Test-only refactor continuing #2523. Adds a shared import-state isolation helper with focused coverage and migrates two pilot tests that manually preserved sys.modules and parent package attributes.
2026-06-05 07:30:14 +01:00
Alexandre Teixeira
a54f41037d fix(tests): restore src.database after webhook import
Restores both sys.modules and parent src.database package state after the webhook SSRF tests import src.webhook_manager against the real database module. Fixes one focused #2580 CI-baseline pollution bucket.
2026-06-04 21:21:51 +01:00
Vykos
5869106089 test: stabilize full test collection 2026-06-04 00:27:29 +01:00
ghreprimand
6fd52cf317 Replace webhook manager datetime.utcnow calls (#1499)
Co-authored-by: ghreprimand <203024559+ghreprimand@users.noreply.github.com>
2026-06-03 14:14:23 +09:00
Tatlatat
da3876c168 Webhook: block IPv6 SSRF bypasses
The webhook URL guard's _ip_is_private() only checks a hardcoded
_PRIVATE_NETWORKS list, which misses several addresses that route
internally. validate_webhook_url() therefore ALLOWED:

- http://[::]/                      (IPv6 unspecified, reaches localhost)
- http://[::ffff:127.0.0.1]/        (IPv4-mapped IPv6 loopback = 127.0.0.1)
- http://[::ffff:169.254.169.254]/  (IPv4-mapped cloud metadata endpoint)

The last one is the dangerous case: a webhook pointed at the mapped
169.254.169.254 can pull cloud instance credentials (SSRF -> credential
theft).

Harden _ip_is_private(): first unwrap IPv4-mapped IPv6 to its embedded IPv4
(addr.ipv4_mapped), then reject via the stdlib address properties
(is_private, is_loopback, is_link_local, is_reserved, is_multicast,
is_unspecified) in addition to the existing network list. Public addresses
still pass.

tests/test_webhook_ssrf_resilience.py asserts validate_webhook_url raises
for the three IPv6 bypasses plus 127.0.0.1 and 0.0.0.0, and still accepts a
public IP literal. The IPv6 cases fail before this change.
2026-06-02 20:28:12 +09:00