mirror of
https://forge.fsky.io/oneflux/omegafox.git
synced 2026-02-10 07:02:03 -08:00
pythonlib: Add more leak warnings 0.2.8
Warns the user for when the passed parameters are likely to cause a leak.
This commit is contained in:
parent
4a1cd7ec64
commit
351e99ed18
8 changed files with 171 additions and 36 deletions
28
.gitignore
vendored
28
.gitignore
vendored
|
|
@ -1,20 +1,32 @@
|
|||
# Local builds
|
||||
/camoufox-*
|
||||
/firefox-*
|
||||
/mozilla-unified
|
||||
/extra-docs
|
||||
/.vscode
|
||||
_old/
|
||||
dist/
|
||||
bin/
|
||||
venv/
|
||||
/bundle/fonts/extra
|
||||
launch
|
||||
launch.exe
|
||||
|
||||
# Internal testing
|
||||
/extra-docs
|
||||
/tests
|
||||
/.vscode
|
||||
/bundle/fonts/extra
|
||||
pythonlib/*.png
|
||||
scripts/*.png
|
||||
test*
|
||||
|
||||
# Old data
|
||||
_old/
|
||||
*.old
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Logs
|
||||
wget-log
|
||||
*.kate-swp
|
||||
*.log
|
||||
test.py
|
||||
|
||||
# Python interface
|
||||
venv/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.mmdb
|
||||
|
|
@ -116,11 +116,3 @@ class InvalidOS(ValueError):
|
|||
"""
|
||||
|
||||
...
|
||||
|
||||
|
||||
class DetectionWarning(RuntimeWarning):
|
||||
"""
|
||||
Raised when a the user has a setting enabled that can cause detection.
|
||||
"""
|
||||
|
||||
...
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
import os.path
|
||||
import re
|
||||
from dataclasses import asdict
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from browserforge.fingerprints import Fingerprint, FingerprintGenerator
|
||||
from yaml import CLoader, load
|
||||
|
||||
from camoufox.pkgman import load_yaml
|
||||
|
||||
# Load the browserforge.yaml file
|
||||
with open(os.path.join(os.path.dirname(__file__), 'browserforge.yml'), 'r') as f:
|
||||
BROWSERFORGE_DATA = load(f, Loader=CLoader)
|
||||
BROWSERFORGE_DATA = load_yaml('browserforge.yml')
|
||||
|
||||
FP_GENERATOR = FingerprintGenerator(browser='firefox', os=('linux', 'macos', 'windows'))
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import requests
|
|||
from platformdirs import user_cache_dir
|
||||
from tqdm import tqdm
|
||||
from typing_extensions import TypeAlias
|
||||
from yaml import CLoader, load
|
||||
|
||||
from .exceptions import UnsupportedArchitecture, UnsupportedOS
|
||||
|
||||
|
|
@ -337,3 +338,11 @@ def unzip(
|
|||
with ZipFile(zip_file) as zf:
|
||||
for member in tqdm(zf.infolist(), desc=desc):
|
||||
zf.extract(member, extract_path)
|
||||
|
||||
|
||||
def load_yaml(file: str) -> dict:
|
||||
"""
|
||||
Loads a local YAML file and returns it as a dictionary.
|
||||
"""
|
||||
with open(Path(__file__).parent / file, 'r') as f:
|
||||
return load(f, Loader=CLoader)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import os
|
||||
import sys
|
||||
import warnings
|
||||
from os import environ
|
||||
from pprint import pprint
|
||||
from random import randrange
|
||||
|
|
@ -20,7 +19,6 @@ from .addons import (
|
|||
threaded_try_load_addons,
|
||||
)
|
||||
from .exceptions import (
|
||||
DetectionWarning,
|
||||
InvalidOS,
|
||||
InvalidPropertyType,
|
||||
NonFirefoxFingerprint,
|
||||
|
|
@ -30,6 +28,7 @@ from .fingerprints import from_browserforge, generate_fingerprint
|
|||
from .ip import Proxy, public_ip, valid_ipv4, valid_ipv6
|
||||
from .locale import geoip_allowed, get_geolocation, normalize_locale
|
||||
from .pkgman import OS_NAME, get_path, installed_verstr
|
||||
from .warnings import LeakWarning
|
||||
from .xpi_dl import add_default_addons
|
||||
|
||||
LAUNCH_FILE = {
|
||||
|
|
@ -197,12 +196,7 @@ def check_custom_fingerprint(fingerprint: Fingerprint) -> None:
|
|||
'If this is intentional, pass `i_know_what_im_doing=True`.'
|
||||
)
|
||||
|
||||
warnings.warn(
|
||||
'Passing your own fingerprint is not recommended. '
|
||||
'BrowserForge fingerprints are automatically generated within Camoufox '
|
||||
'based on the provided `os` and `screen` constraints.',
|
||||
category=DetectionWarning,
|
||||
)
|
||||
LeakWarning.warn('custom_fingerprint', False)
|
||||
|
||||
|
||||
def check_valid_os(os: ListOrString) -> None:
|
||||
|
|
@ -249,6 +243,45 @@ def set_into(target: Dict[str, Any], key: str, value: Any) -> None:
|
|||
target[key] = value
|
||||
|
||||
|
||||
def is_domain_set(
|
||||
config: Dict[str, Any],
|
||||
*properties: str,
|
||||
) -> bool:
|
||||
"""
|
||||
Checks if a domain is set in the config.
|
||||
"""
|
||||
for prop in properties:
|
||||
# If the . prefix exists, check if the domain is a prefix of any key in the config
|
||||
if prop.endswith('.'):
|
||||
if any(key.startswith(prop) for key in config):
|
||||
return True
|
||||
# Otherwise, check if the domain is a direct key in the config
|
||||
else:
|
||||
if prop in config:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def warn_manual_config(config: Dict[str, Any]) -> None:
|
||||
"""
|
||||
Warns the user if they are manually setting properties that Camoufox already sets internally.
|
||||
"""
|
||||
# Manual locale setting
|
||||
if is_domain_set(
|
||||
config, 'navigator.language', 'navigator.languages', 'headers.Accept-Language'
|
||||
):
|
||||
LeakWarning.warn('locale', False)
|
||||
# Manual User-Agent setting
|
||||
if is_domain_set(config, 'headers.User-Agent'):
|
||||
LeakWarning.warn('header-ua', False)
|
||||
# Manual navigator setting
|
||||
if is_domain_set(config, 'navigator.'):
|
||||
LeakWarning.warn('navigator', False)
|
||||
# Manual screen/window setting
|
||||
if is_domain_set(config, 'screen.', 'window.', 'document.body.'):
|
||||
LeakWarning.warn('viewport', False)
|
||||
|
||||
|
||||
def get_launch_options(
|
||||
*,
|
||||
config: Optional[Dict[str, Any]] = None,
|
||||
|
|
@ -282,24 +315,27 @@ def get_launch_options(
|
|||
if config is None:
|
||||
config = {}
|
||||
|
||||
# Set default values for optional arguments
|
||||
if addons is None:
|
||||
addons = []
|
||||
if args is None:
|
||||
args = []
|
||||
if firefox_user_prefs is None:
|
||||
firefox_user_prefs = {}
|
||||
if i_know_what_im_doing is None:
|
||||
i_know_what_im_doing = False
|
||||
|
||||
# Warn the user if headless is being used
|
||||
# https://github.com/daijro/camoufox/issues/26
|
||||
if headless:
|
||||
warnings.warn(
|
||||
'It is currently not recommended to use headless mode in Camoufox. '
|
||||
'Some WAFs are able to detect headless browsers. The issue is currently being investigated.',
|
||||
category=DetectionWarning,
|
||||
)
|
||||
LeakWarning.warn('headless', i_know_what_im_doing)
|
||||
elif headless is None:
|
||||
headless = False
|
||||
|
||||
# Warn the user for manual config settings
|
||||
if not i_know_what_im_doing:
|
||||
warn_manual_config(config)
|
||||
|
||||
# Assert the target OS is valid
|
||||
if os:
|
||||
check_valid_os(os)
|
||||
|
|
@ -366,6 +402,14 @@ def get_launch_options(
|
|||
geolocation = get_geolocation(geoip)
|
||||
config.update(geolocation.as_config())
|
||||
|
||||
# Raise a warning when a proxy is being used without spoofing geolocation
|
||||
elif (
|
||||
proxy
|
||||
and 'localhost' not in proxy.get('server', '')
|
||||
and not is_domain_set('geolocation', config)
|
||||
):
|
||||
LeakWarning.warn('proxy_without_geoip')
|
||||
|
||||
# Set locale
|
||||
if locale:
|
||||
parsed_locale = normalize_locale(locale)
|
||||
|
|
@ -391,10 +435,13 @@ def get_launch_options(
|
|||
if block_webrtc:
|
||||
firefox_user_prefs['media.peerconnection.enabled'] = False
|
||||
if allow_webgl:
|
||||
LeakWarning.warn('allow_webgl', i_know_what_im_doing)
|
||||
firefox_user_prefs['webgl.disabled'] = False
|
||||
|
||||
# Launch
|
||||
# Load the addons
|
||||
threaded_try_load_addons(get_debug_port(args), addons)
|
||||
|
||||
# Prepare environment variables to pass to Camoufox
|
||||
env_vars = {
|
||||
**get_env_vars(config, target_os),
|
||||
**(cast(Dict[str, Union[str, float, bool]], environ) if env is None else env),
|
||||
|
|
|
|||
44
pythonlib/camoufox/warnings.py
Normal file
44
pythonlib/camoufox/warnings.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import inspect
|
||||
import warnings
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from camoufox.pkgman import load_yaml
|
||||
|
||||
WARNINGS_DATA = load_yaml('warnings.yml')
|
||||
|
||||
|
||||
class LeakWarning(RuntimeWarning):
|
||||
"""
|
||||
Raised when a the user has a setting enabled that can cause detection.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def warn(warning_key: str, i_know_what_im_doing: Optional[bool] = None) -> None:
|
||||
"""
|
||||
Warns the user if a passed parameter can cause leaks.
|
||||
"""
|
||||
warning = WARNINGS_DATA[warning_key]
|
||||
if i_know_what_im_doing:
|
||||
return
|
||||
if i_know_what_im_doing is not None:
|
||||
warning += '\nIf this is intentional, pass `i_know_what_im_doing=True`.'
|
||||
|
||||
# Get caller information
|
||||
current_module = Path(__file__).parent
|
||||
frame = inspect.currentframe()
|
||||
while frame:
|
||||
if not Path(frame.f_code.co_filename).is_relative_to(current_module):
|
||||
break
|
||||
frame = frame.f_back
|
||||
|
||||
if frame:
|
||||
warnings.warn_explicit(
|
||||
warning,
|
||||
category=LeakWarning,
|
||||
filename=frame.f_code.co_filename,
|
||||
lineno=frame.f_lineno,
|
||||
)
|
||||
return
|
||||
|
||||
warnings.warn(warning, category=LeakWarning)
|
||||
32
pythonlib/camoufox/warnings.yml
Normal file
32
pythonlib/camoufox/warnings.yml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
headless: >-
|
||||
Headless mode in Camoufox is not recommended at this time.
|
||||
Some WAFs are able to detect headless browsers. The issue is currently being investigated.
|
||||
|
||||
navigator: >-
|
||||
Manually setting navigator properties is not recommended.
|
||||
Device information is automatically generated within Camoufox
|
||||
based on the provided `os`.
|
||||
|
||||
locale: >-
|
||||
Use the `locale` parameter in Camoufox instead of setting the config manually.
|
||||
|
||||
header-ua: >-
|
||||
Do not set the header.User-Agent manually. Camoufox will generate a User-Agent for you.
|
||||
|
||||
viewport: >-
|
||||
Manually setting screen & window properties is not recommended.
|
||||
Screen dimensions are randomly generated within Camoufox
|
||||
based on the provided screen constraints. See here:
|
||||
https://github.com/daijro/camoufox/tree/main/pythonlib#browserforge-integration.
|
||||
|
||||
custom_fingerprint: >-
|
||||
Passing your own fingerprint is not recommended.
|
||||
BrowserForge fingerprints are automatically generated within Camoufox
|
||||
based on the provided `os` and `screen` constraints.
|
||||
|
||||
proxy_without_geoip: >-
|
||||
When using a proxy, it is heavily recommended that you pass `geoip=True`.
|
||||
|
||||
allow_webgl: >-
|
||||
Enabling WebGL can lead to Canvas fingerprinting and detection.
|
||||
Camoufox will automatically spoof your vendor and renderer, but it cannot spoof your WebGL fingerprint.
|
||||
|
|
@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|||
|
||||
[tool.poetry]
|
||||
name = "camoufox"
|
||||
version = "0.2.7"
|
||||
version = "0.2.8"
|
||||
description = "Wrapper around Playwright to help launch Camoufox"
|
||||
authors = ["daijro <daijro.dev@gmail.com>"]
|
||||
license = "MIT"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue