mirror of
https://github.com/daijro/camoufox.git
synced 2026-10-03 16:00:19 +00:00
fix(python): send an IPv6 WebRTC address to setWebRTCIPv6
The per-context init script passed every webrtc_ip, IPv6 included, to window.setWebRTCIPv4(), and never called setWebRTCIPv6(). An IPv6 address (given directly, or resolved as a proxy's exit IP) was stored as the context's IPv4 value and the IPv6 slot stayed empty. The script now picks the setter by address family, and an address that is neither raises InvalidIP instead of being passed through. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
46e5c8d1a4
commit
0bbd15246f
@@ -617,7 +617,7 @@ bundles are shipped in the wheel.
|
||||
| Audio seed | Derived from the identity (NewBrowser) or `randint(1, 2^32-1)` (NewContext) | Never 0 |
|
||||
| Timezone | From preset, or `timezone` in `CAMOU_CONFIG` | The init script calls `setTimezone()` only for an explicit value; otherwise the C++ side falls back to `CAMOU_CONFIG` (set from geoip at launch) or the browser default. |
|
||||
| Speech voices | `_generate_random_voice_subset()` | Follows the measured model in `voice-manifests.json`: Windows gets the display language's OneCore pack plus its legacy Desktop voices at their measured rate; macOS the compact + Eloquence base plus rare downloads; Linux speech-dispatcher's espeak-ng list. Seeded by the identity. NOT from presets. |
|
||||
| WebRTC IP | Not set by default | User sets via `window.setWebRTCIPv4()`. NewContext init script defaults to empty string `""` |
|
||||
| WebRTC IP | Not set by default | NewContext's `webrtc_ip` (or the proxy's exit IP) goes to `window.setWebRTCIPv4()` or `window.setWebRTCIPv6()` by address family; an invalid address raises `InvalidIP`. Without one, the init script calls `setWebRTCIPv4("")` |
|
||||
| Geolocation | User parameter or geoip detection | Via Playwright `context.setGeolocation()` |
|
||||
|
||||
### Key Files
|
||||
|
||||
@@ -204,7 +204,7 @@ async def AsyncNewContext(
|
||||
preset: A fingerprint preset dict to use. If None, fpgen draws a new identity.
|
||||
os: Target OS for the drawn identity ("windows", "macos", "linux").
|
||||
ff_version: Firefox major version to claim in the UA. Defaults to the browser's own.
|
||||
webrtc_ip: IPv4 address to spoof for WebRTC ICE candidates.
|
||||
webrtc_ip: IPv4 or IPv6 address to spoof for WebRTC ICE candidates.
|
||||
proxy: Per-context proxy (Playwright format: {"server": "...", "username": "...", "password": "..."}).
|
||||
Unless webrtc_ip and timezone_id are both given, they are looked up from the
|
||||
proxy's exit IP; InvalidIP is raised if that lookup fails.
|
||||
|
||||
@@ -11,6 +11,7 @@ from random import Random, choice, randint, randrange
|
||||
from typing import Any, Dict, FrozenSet, List, Optional, Set, Tuple
|
||||
|
||||
from camoufox._warnings import FallbackWarning
|
||||
from camoufox.ip import valid_ipv4, validate_ip
|
||||
from camoufox.pkgman import load_yaml
|
||||
from camoufox.webgl import sample_webgl
|
||||
|
||||
@@ -1759,8 +1760,10 @@ def _build_init_script(values: Dict[str, Any]) -> str:
|
||||
# WebRTC IP
|
||||
ip = values.get('webrtcIP')
|
||||
if ip:
|
||||
validate_ip(ip)
|
||||
fn_name = 'setWebRTCIPv4' if valid_ipv4(ip) else 'setWebRTCIPv6'
|
||||
lines.append(
|
||||
f' if (typeof w.setWebRTCIPv4 === "function") w.setWebRTCIPv4({_json.dumps(ip)});'
|
||||
f' if (typeof w.{fn_name} === "function") w.{fn_name}({_json.dumps(ip)});'
|
||||
)
|
||||
else:
|
||||
lines.append(
|
||||
|
||||
@@ -182,7 +182,7 @@ def NewContext(
|
||||
preset: A fingerprint preset dict to use. If None, fpgen draws a new identity.
|
||||
os: Target OS for the drawn identity ("windows", "macos", "linux").
|
||||
ff_version: Firefox major version to claim in the UA. Defaults to the browser's own.
|
||||
webrtc_ip: IPv4 address to spoof for WebRTC ICE candidates.
|
||||
webrtc_ip: IPv4 or IPv6 address to spoof for WebRTC ICE candidates.
|
||||
proxy: Per-context proxy (Playwright format: {"server": "...", "username": "...", "password": "..."}).
|
||||
Unless webrtc_ip and timezone_id are both given, they are looked up from the
|
||||
proxy's exit IP; InvalidIP is raised if that lookup fails.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
"""The per-context init script hands a WebRTC IP to the setter for its family."""
|
||||
|
||||
import pytest
|
||||
|
||||
from camoufox.exceptions import InvalidIP
|
||||
from camoufox.fingerprints import _build_init_script
|
||||
|
||||
|
||||
def test_ipv4_goes_to_the_ipv4_setter():
|
||||
script = _build_init_script({"webrtcIP": "203.0.113.7"})
|
||||
assert 'w.setWebRTCIPv4("203.0.113.7")' in script
|
||||
assert "setWebRTCIPv6(" not in script
|
||||
|
||||
|
||||
def test_ipv6_goes_to_the_ipv6_setter():
|
||||
script = _build_init_script({"webrtcIP": "2001:db8::7"})
|
||||
assert 'w.setWebRTCIPv6("2001:db8::7")' in script
|
||||
assert "2001:db8::7" not in script.split("setWebRTCIPv6")[0]
|
||||
|
||||
|
||||
def test_an_invalid_address_is_refused():
|
||||
with pytest.raises(InvalidIP):
|
||||
_build_init_script({"webrtcIP": "not-an-ip"})
|
||||
Reference in New Issue
Block a user