File size: 5,329 Bytes
95b8512
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# Camofox-Browser Integration

Rhodawk now ships with an embedded
[camofox-browser](https://github.com/jo-inc/camofox-browser) anti-detection
browser server so the orchestrator and analysis engines can browse the live
web without being fingerprinted, blocked by Cloudflare, or flagged by
Google's bot detection.

## Why

Several Rhodawk subsystems already need to fetch real-world web content:

| Subsystem            | Today                       | With camofox-browser                       |
|----------------------|-----------------------------|--------------------------------------------|
| `cve_intel.py`       | Plain `requests` to NVD/SSEC | Real-browser fetch with stable element refs |
| `repo_harvester.py`  | GitHub REST + raw HTML       | Authenticated session reuse, no rate-limit captcha |
| `knowledge_rag.py`   | Static doc scraping          | JS-rendered docs (Notion, Confluence, etc.) |
| `red_team_fuzzer.py` | n/a                          | Live target reconnaissance                 |
| `bounty_gateway.py`  | HackerOne / Bugcrowd REST    | UI fallback when the REST API is down      |

camofox patches Firefox at the **C++ implementation level** β€”
`navigator.hardwareConcurrency`, WebGL renderers, AudioContext, screen
geometry, WebRTC β€” all spoofed before JavaScript ever sees them. No shims,
no wrappers, no tells.

## Architecture

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  app.py / orchestrator      β”‚  HTTP   β”‚  /opt/camofox  (node)        β”‚
β”‚  cve_intel.py / harvester   β”‚ ──────▢ β”‚  127.0.0.1:9377              β”‚
β”‚  knowledge_rag.py / …       β”‚         β”‚  camofox-browser server      β”‚
β”‚                             β”‚         β”‚  β”œβ”€β”€ Camoufox (Firefox fork) β”‚
β”‚  camofox_client.py          β”‚         β”‚  β”œβ”€β”€ Playwright contexts     β”‚
β”‚  └─ CamofoxClient (REST)    β”‚         β”‚  └── per-userId session jar  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

* **Server** is launched by `entrypoint.sh` alongside the OpenClaude gRPC
  daemons. Listens on `127.0.0.1:9377` (not exposed publicly by default).
* **Client** is `camofox_client.py` β€” a thin, dependency-free
  (`requests`-only) Python wrapper that any module can import.
* **Sessions** are isolated per `userId` so concurrent research jobs
  cannot leak cookies into each other.

## Quick Start (Python)

```python
from camofox_client import get_client, fetch_snapshot

# One-shot: fetch a snapshot of a URL with element refs.
snap = fetch_snapshot(
    "https://nvd.nist.gov/vuln/detail/CVE-2024-3094",
    user_id="cve_intel",
)
if snap.get("available"):
    print(snap["snapshot"][:2000])

# Long-running session:
client = get_client()
if client.is_available():
    tab = client.create_tab("harvester", "https://github.com/torvalds/linux")
    snap = client.snapshot(tab)
    client.click(tab, "e1")           # click the first interactive element
    client.type_text(tab, "e2", "fix") # type into the search box
    png = client.screenshot(tab, full_page=True)
    client.close_tab(tab)
```

If the camofox server is not running, `is_available()` returns `False` and
`fetch_snapshot()` returns `{"available": False, "reason": "..."}` so callers
can degrade gracefully to plain `requests`.

## Environment Variables

| Variable                 | Default                        | Purpose                                   |
|--------------------------|--------------------------------|-------------------------------------------|
| `CAMOFOX_BASE_URL`       | `http://127.0.0.1:9377`        | Where the Python client looks for the API |
| `CAMOFOX_PORT`           | `9377`                         | Port the node server binds to             |
| `CAMOFOX_HOST`           | `127.0.0.1`                    | Host the node server binds to             |
| `CAMOFOX_HEADLESS`       | `virtual`                      | `virtual` uses xvfb; `true` uses Firefox headless mode |
| `CAMOFOX_PROFILE_DIR`    | `/data/camofox/profiles`       | Persistent per-user storage state         |
| `CAMOFOX_COOKIES_DIR`    | `/data/camofox/cookies`        | Drop Netscape cookie files here for import |
| `CAMOFOX_API_KEY`        | *(unset β†’ cookie writes disabled)* | Bearer token required for `import_cookies` |
| `PROXY_HOST` / `PROXY_PORT` / `PROXY_USERNAME` / `PROXY_PASSWORD` | *(unset)* | Route browser traffic through a residential proxy. Camoufox's GeoIP then auto-aligns locale + timezone. |

## Files Added

| Path                       | What it is                                  |
|----------------------------|---------------------------------------------|
| `camofox_client.py`        | Python REST client + module-level helpers   |
| `CAMOFOX_INTEGRATION.md`   | This document                               |
| `Dockerfile` (modified)    | Installs `@askjo/camofox-browser` under `/opt/camofox` and the X/GTK runtime libs Camoufox needs |
| `entrypoint.sh` (modified) | Launches the camofox server before the OpenClaude daemons |