@natchs/browser-mcp 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +356 -13
- package/dist/core/audit-logger.d.ts +3 -0
- package/dist/core/audit-logger.d.ts.map +1 -0
- package/dist/core/audit-logger.js +5 -0
- package/dist/core/audit-logger.js.map +1 -0
- package/dist/core/auth.d.ts.map +1 -1
- package/dist/core/auth.js +29 -1
- package/dist/core/auth.js.map +1 -1
- package/dist/core/body-fetch.d.ts.map +1 -1
- package/dist/core/body-fetch.js +26 -2
- package/dist/core/body-fetch.js.map +1 -1
- package/dist/core/browser-lifecycle.d.ts +29 -0
- package/dist/core/browser-lifecycle.d.ts.map +1 -0
- package/dist/core/browser-lifecycle.js +107 -0
- package/dist/core/browser-lifecycle.js.map +1 -0
- package/dist/core/browser-provider.d.ts +7 -3
- package/dist/core/browser-provider.d.ts.map +1 -1
- package/dist/core/browser-provider.js +65 -10
- package/dist/core/browser-provider.js.map +1 -1
- package/dist/core/config.d.ts +22 -6
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +6 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/errors.d.ts +0 -12
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +4 -13
- package/dist/core/errors.js.map +1 -1
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +3 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/network-capture-utils.d.ts +49 -0
- package/dist/core/network-capture-utils.d.ts.map +1 -0
- package/dist/core/network-capture-utils.js +56 -0
- package/dist/core/network-capture-utils.js.map +1 -0
- package/dist/core/network-capture.d.ts +2 -39
- package/dist/core/network-capture.d.ts.map +1 -1
- package/dist/core/network-capture.js +17 -54
- package/dist/core/network-capture.js.map +1 -1
- package/dist/core/network-export.d.ts +3 -3
- package/dist/core/network-export.d.ts.map +1 -1
- package/dist/core/network-export.js +13 -21
- package/dist/core/network-export.js.map +1 -1
- package/dist/core/output.d.ts +0 -28
- package/dist/core/output.d.ts.map +1 -1
- package/dist/core/registry.d.ts +2 -0
- package/dist/core/registry.d.ts.map +1 -1
- package/dist/core/registry.js +14 -3
- package/dist/core/registry.js.map +1 -1
- package/dist/core/sandbox.d.ts +4 -5
- package/dist/core/sandbox.d.ts.map +1 -1
- package/dist/core/sandbox.js +31 -23
- package/dist/core/sandbox.js.map +1 -1
- package/dist/core/session.d.ts +4 -3
- package/dist/core/session.d.ts.map +1 -1
- package/dist/core/session.js +43 -22
- package/dist/core/session.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +2 -1
- package/dist/prompts/index.js.map +1 -1
- package/dist/tools/admin/cache.js +3 -3
- package/dist/tools/admin/cache.js.map +1 -1
- package/dist/tools/admin/server-status.js +2 -2
- package/dist/tools/admin/server-status.js.map +1 -1
- package/dist/tools/browser/cookies.js +4 -4
- package/dist/tools/browser/cookies.js.map +1 -1
- package/dist/tools/browser/download.js +2 -2
- package/dist/tools/browser/download.js.map +1 -1
- package/dist/tools/browser/evaluate.d.ts.map +1 -1
- package/dist/tools/browser/evaluate.js +23 -6
- package/dist/tools/browser/evaluate.js.map +1 -1
- package/dist/tools/browser/index.d.ts.map +1 -1
- package/dist/tools/browser/index.js +2 -0
- package/dist/tools/browser/index.js.map +1 -1
- package/dist/tools/browser/page-info.js +2 -2
- package/dist/tools/browser/page-info.js.map +1 -1
- package/dist/tools/browser/pdf.js +4 -4
- package/dist/tools/browser/pdf.js.map +1 -1
- package/dist/tools/browser/screenshot.js +3 -3
- package/dist/tools/browser/screenshot.js.map +1 -1
- package/dist/tools/browser/scroll.d.ts +17 -0
- package/dist/tools/browser/scroll.d.ts.map +1 -0
- package/dist/tools/browser/scroll.js +30 -0
- package/dist/tools/browser/scroll.js.map +1 -0
- package/dist/tools/extraction/extract-css.js +7 -7
- package/dist/tools/extraction/extract-css.js.map +1 -1
- package/dist/tools/extraction/extract.js +4 -4
- package/dist/tools/extraction/extract.js.map +1 -1
- package/dist/tools/interaction/click.d.ts +1 -2
- package/dist/tools/interaction/click.d.ts.map +1 -1
- package/dist/tools/interaction/click.js +9 -15
- package/dist/tools/interaction/click.js.map +1 -1
- package/dist/tools/interaction/drag.js +4 -4
- package/dist/tools/interaction/drag.js.map +1 -1
- package/dist/tools/interaction/file-upload.d.ts.map +1 -1
- package/dist/tools/interaction/file-upload.js +11 -5
- package/dist/tools/interaction/file-upload.js.map +1 -1
- package/dist/tools/interaction/fill.d.ts.map +1 -1
- package/dist/tools/interaction/fill.js +5 -7
- package/dist/tools/interaction/fill.js.map +1 -1
- package/dist/tools/interaction/hover.js +3 -3
- package/dist/tools/interaction/hover.js.map +1 -1
- package/dist/tools/interaction/press-key.js +3 -3
- package/dist/tools/interaction/press-key.js.map +1 -1
- package/dist/tools/interaction/select.js +4 -4
- package/dist/tools/interaction/select.js.map +1 -1
- package/dist/tools/interaction/type.d.ts +1 -1
- package/dist/tools/interaction/type.js +4 -4
- package/dist/tools/interaction/type.js.map +1 -1
- package/dist/tools/navigation/back.js +2 -2
- package/dist/tools/navigation/back.js.map +1 -1
- package/dist/tools/navigation/forward.js +2 -2
- package/dist/tools/navigation/forward.js.map +1 -1
- package/dist/tools/navigation/navigate.js +2 -2
- package/dist/tools/navigation/navigate.js.map +1 -1
- package/dist/tools/navigation/refresh.js +2 -2
- package/dist/tools/navigation/refresh.js.map +1 -1
- package/dist/tools/navigation/wait-for.js +2 -2
- package/dist/tools/navigation/wait-for.js.map +1 -1
- package/dist/tools/network/console.js +2 -2
- package/dist/tools/network/console.js.map +1 -1
- package/dist/tools/network/dialog.js +2 -2
- package/dist/tools/network/dialog.js.map +1 -1
- package/dist/tools/network/network-clear.js +2 -2
- package/dist/tools/network/network-clear.js.map +1 -1
- package/dist/tools/network/network-entries.js +2 -2
- package/dist/tools/network/network-entries.js.map +1 -1
- package/dist/tools/network/network-export.d.ts +2 -2
- package/dist/tools/network/network-export.js +2 -2
- package/dist/tools/network/network-export.js.map +1 -1
- package/dist/tools/network/network-requests.js +2 -2
- package/dist/tools/network/network-requests.js.map +1 -1
- package/dist/tools/network/network-response.js +2 -2
- package/dist/tools/network/network-response.js.map +1 -1
- package/dist/tools/network/network-save.js +2 -2
- package/dist/tools/network/network-save.js.map +1 -1
- package/dist/tools/network/wait-nav.js +2 -2
- package/dist/tools/network/wait-nav.js.map +1 -1
- package/dist/tools/network/websocket-frames.js +2 -2
- package/dist/tools/network/websocket-frames.js.map +1 -1
- package/dist/tools/re/api-discover.d.ts +3 -3
- package/dist/tools/re/api-discover.d.ts.map +1 -1
- package/dist/tools/re/api-discover.js +32 -11
- package/dist/tools/re/api-discover.js.map +1 -1
- package/dist/tools/re/auth-analyze.d.ts +3 -3
- package/dist/tools/re/auth-analyze.d.ts.map +1 -1
- package/dist/tools/re/auth-analyze.js +43 -6
- package/dist/tools/re/auth-analyze.js.map +1 -1
- package/dist/tools/re/js-beautify.js +3 -3
- package/dist/tools/re/js-beautify.js.map +1 -1
- package/dist/tools/re/js-deobfuscate.js +3 -3
- package/dist/tools/re/js-deobfuscate.js.map +1 -1
- package/dist/tools/session/close.js +2 -2
- package/dist/tools/session/close.js.map +1 -1
- package/dist/tools/session/list.js +2 -2
- package/dist/tools/session/list.js.map +1 -1
- package/dist/tools/session/open.js +2 -2
- package/dist/tools/session/open.js.map +1 -1
- package/dist/tools/stealth/fingerprint.d.ts +13 -0
- package/dist/tools/stealth/fingerprint.d.ts.map +1 -1
- package/dist/tools/stealth/fingerprint.js +16 -3
- package/dist/tools/stealth/fingerprint.js.map +1 -1
- package/dist/tools/stealth/human-behavior.js +2 -2
- package/dist/tools/stealth/human-behavior.js.map +1 -1
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
# @natchs/browser-mcp
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@natchs/browser-mcp)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](package.json)
|
|
4
6
|
|
|
5
7
|
---
|
|
6
8
|
|
|
7
|
-
##
|
|
9
|
+
## 🇹🇷 Türkçe
|
|
10
|
+
|
|
11
|
+
**Browser automation MCP server** — reverse engineering, web scraping ve data extraction için tasarlanmış, AI ajanların tarayıcıyı tam kontrol etmesini sağlayan bir Model Context Protocol sunucusu.
|
|
12
|
+
|
|
13
|
+
### Quick Start
|
|
8
14
|
|
|
9
15
|
```bash
|
|
10
16
|
# 1. Install
|
|
@@ -14,7 +20,7 @@ npm install @natchs/browser-mcp
|
|
|
14
20
|
npx @natchs/browser-mcp
|
|
15
21
|
```
|
|
16
22
|
|
|
17
|
-
|
|
23
|
+
#### MCP Client Config
|
|
18
24
|
|
|
19
25
|
Claude Desktop, Cursor, VS Code veya herhangi bir MCP istemcisine eklemek için:
|
|
20
26
|
|
|
@@ -39,11 +45,143 @@ npm run build
|
|
|
39
45
|
npx @natchs/browser-mcp
|
|
40
46
|
```
|
|
41
47
|
|
|
48
|
+
#### Browser Profili: 3 Mod
|
|
49
|
+
|
|
50
|
+
Ajanın hangi tarayıcıyı kullanacağını `BROWSER_MODE` ortam değişkeni belirler:
|
|
51
|
+
|
|
52
|
+
| Mod | Açıklama | Ne Zaman Kullanılır? |
|
|
53
|
+
|-----|----------|---------------------|
|
|
54
|
+
| `fresh` (default) | Playwright'ın kendi Chromium'u. Her seferinde sıfır profil, çerez/ext/login yok | Temiz ortam, iz bırakmamak |
|
|
55
|
+
| `persistent` | **Senin Chrome profilin.** Gerçek çerezler, geçmiş, uzantılar, oturum açmış hesaplar — hepsi ajana kullanıma hazır | Ajanın sitelere "sen" olarak girmesi gereken işlemler |
|
|
56
|
+
| `connect` | Halihazırda açık Chrome'una CDP ile bağlanır | Chrome'u elle kontrol ederken ajanın eşlik etmesi |
|
|
57
|
+
|
|
58
|
+
**Örnek — persistent (otomatik profil tespiti):**
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
BROWSER_MODE=persistent npx @natchs/browser-mcp
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
v2.3.0 ile Chrome profili otomatik tespit edilir. Hiçbir yol belirtmeniz gerekmez. Windows/macOS/Linux hepsinde çalışır. Manuel yol belirtmek için:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
BROWSER_MODE=persistent BROWSER_USER_DATA_DIR=C:\Users\...\User Data\Default npx @natchs/browser-mcp
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Örnek — connect (mevcut Chrome'a bağlan):**
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Önce Chrome'u debug port ile aç:
|
|
74
|
+
"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222
|
|
75
|
+
|
|
76
|
+
# Sonra ajanı bağla:
|
|
77
|
+
BROWSER_MODE=connect npx @natchs/browser-mcp
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**MCP Client Config ile kullanım — her mod için ayrı profil:**
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"mcpServers": {
|
|
85
|
+
"browser-mcp-persistent": {
|
|
86
|
+
"command": "npx",
|
|
87
|
+
"args": ["@natchs/browser-mcp"],
|
|
88
|
+
"env": {
|
|
89
|
+
"BROWSER_MODE": "persistent"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"browser-mcp-fresh": {
|
|
93
|
+
"command": "npx",
|
|
94
|
+
"args": ["@natchs/browser-mcp"],
|
|
95
|
+
"env": {
|
|
96
|
+
"BROWSER_MODE": "fresh"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
42
103
|
---
|
|
43
104
|
|
|
44
|
-
|
|
105
|
+
### Ortam Değişkenleri
|
|
106
|
+
|
|
107
|
+
Tüm yapılandırma, ortam değişkenleri aracılığıyla yapılabilir. Aşağıdaki tablo, desteklenen tüm değişkenleri listeler.
|
|
108
|
+
|
|
109
|
+
#### Browser
|
|
110
|
+
|
|
111
|
+
| Variable | Default | Description | Required |
|
|
112
|
+
|----------|---------|-------------|----------|
|
|
113
|
+
| `BROWSER_MODE` | `fresh` | Browser modu: `fresh`, `persistent`, `connect` | No |
|
|
114
|
+
| `BROWSER_HEADLESS` | `true` | Headless modda çalıştır (`true`/`false`/`1`/`0`/`yes`/`no`) | No |
|
|
115
|
+
| `BROWSER_USER_DATA_DIR` | — | Chrome kullanıcı veri dizini (mutlak yol) | No |
|
|
116
|
+
| `BROWSER_CHANNEL` | `""` | Browser kanalı (`chrome`, `msedge`, `chromium`, vb.) | No |
|
|
117
|
+
| `BROWSER_DEBUG_PORT` | `9222` | CDP debug port numarası | No |
|
|
118
|
+
| `BROWSER_AUTO_DETECT_PROFILE` | `true` | Chrome profilini otomatik tespit et | No |
|
|
119
|
+
| `BROWSER_VIEWPORT_WIDTH` | `1280` | Görüntü alanı genişliği (px) | No |
|
|
120
|
+
| `BROWSER_VIEWPORT_HEIGHT` | `720` | Görüntü alanı yüksekliği (px) | No |
|
|
121
|
+
| `BROWSER_USER_AGENT` | — | Özel User-Agent string'i | No |
|
|
122
|
+
| `BROWSER_LOCALE` | — | Tarayıcı locale değeri (örn. `tr-TR`) | No |
|
|
123
|
+
| `BROWSER_TIMEOUT` | `30000` | Browser işlemleri için timeout (ms) | No |
|
|
124
|
+
| `BROWSER_AUTO_INSTALL` | `true` | Chromium'u otomatik kur (`false` ile devre dışı) | No |
|
|
125
|
+
|
|
126
|
+
#### Network & Download
|
|
127
|
+
|
|
128
|
+
| Variable | Default | Description | Required |
|
|
129
|
+
|----------|---------|-------------|----------|
|
|
130
|
+
| `NETWORK_HAR_ENABLED` | `1` | HAR yakalamayı etkinleştir (`0` ile devre dışı) | No |
|
|
131
|
+
| `NETWORK_MAX_ENTRIES` | `5000` | Maksimum network kaydı sayısı | No |
|
|
132
|
+
| `NETWORK_MAX_RESPONSE_BODY_SIZE` | `262144` | Maksimum response body boyutu (bytes) | No |
|
|
133
|
+
| `NETWORK_STORE_RESPONSE_BODIES` | `false` | Response body'leri hafızada tut | No |
|
|
134
|
+
| `NETWORK_EXCLUDE_BODY_TYPES` | `["image","media","font","stylesheet"]` | Body kaydı dışı bırakılacak tipler (JSON array) | No |
|
|
135
|
+
| `NETWORK_EXPORT_DIR` | `./network-logs` | Network log dışa aktarma dizini | No |
|
|
136
|
+
| `NETWORK_CAPTURE_FAILED` | `true` | Başarısız istekleri de yakala | No |
|
|
137
|
+
| `NETWORK_CAPTURE_WS` | `true` | WebSocket frame'lerini yakala | No |
|
|
138
|
+
| `NETWORK_WS_MAX_FRAMES` | `1000` | Maksimum WS frame sayısı | No |
|
|
139
|
+
| `NETWORK_WS_MAX_FRAME_SIZE` | `65536` | Maksimum WS frame payload boyutu | No |
|
|
140
|
+
| `NETWORK_MAX_MEMORY_MB` | `256` | Network capture için maksimum bellek (MB) | No |
|
|
141
|
+
| `NETWORK_CAPTURE_REQUEST_BODY` | `false` | Request body'lerini de yakala | No |
|
|
142
|
+
| `NETWORK_DOWNLOAD_DIR` | `./downloads` | İndirilen dosyalar için dizin | No |
|
|
143
|
+
| `NETWORK_MAX_DOWNLOAD_SIZE` | `104857600` | Maksimum indirme boyutu (bytes, varsayılan 100MB) | No |
|
|
144
|
+
| `NETWORK_DOWNLOAD_ENABLED` | `false` | Dosya indirme özelliğini etkinleştir | No |
|
|
145
|
+
| `NETWORK_SAVE_ENABLED` | `false` | Network capture kaydetme özelliğini etkinleştir (`network_save` tool'u) | No |
|
|
146
|
+
|
|
147
|
+
#### Rate Limiting
|
|
148
|
+
|
|
149
|
+
| Variable | Default | Description | Required |
|
|
150
|
+
|----------|---------|-------------|----------|
|
|
151
|
+
| `RATE_LIMIT_ENABLED` | `true` | Rate limiting'i etkinleştir | No |
|
|
152
|
+
| `RATE_LIMIT_GLOBAL_RPM` | `120` | Global dakikalık istek limiti | No |
|
|
153
|
+
| `RATE_LIMIT_PER_TOOL_RPM` | `30` | Tool başına dakikalık istek limiti | No |
|
|
154
|
+
| `RATE_LIMIT_BURST_SIZE` | `10` | Maksimum burst boyutu | No |
|
|
155
|
+
|
|
156
|
+
#### Cache
|
|
157
|
+
|
|
158
|
+
| Variable | Default | Description | Required |
|
|
159
|
+
|----------|---------|-------------|----------|
|
|
160
|
+
| `CACHE_MAX_ENTRIES` | `100` | Maksimum önbellek girişi sayısı | No |
|
|
161
|
+
| `CACHE_TTL_SECONDS` | `300` | Önbellek TTL değeri (saniye) | No |
|
|
162
|
+
|
|
163
|
+
#### Security
|
|
164
|
+
|
|
165
|
+
| Variable | Default | Description | Required |
|
|
166
|
+
|----------|---------|-------------|----------|
|
|
167
|
+
| `SECURITY_API_KEY` | `""` | API anahtarı (boş = auth kapalı) | No |
|
|
168
|
+
| `SECURITY_ALLOWED_DIRS` | `[]` | İzin verilen dizinler (JSON array) | No |
|
|
169
|
+
| `SECURITY_MAX_MEMORY_MB` | `512` | Maksimum bellek kullanımı (MB) | No |
|
|
170
|
+
| `SECURITY_DEFAULT_TIMEOUT` | `30000` | Varsayılan işlem timeout'u (ms) | No |
|
|
171
|
+
| `SECURITY_MAX_TIMEOUT` | `120000` | Maksimum timeout (ms) | No |
|
|
172
|
+
| `SECURITY_MAX_SESSIONS` | `10` | Maksimum eşzamanlı browser session sayısı | No |
|
|
173
|
+
|
|
174
|
+
#### Config
|
|
175
|
+
|
|
176
|
+
| Variable | Default | Description | Required |
|
|
177
|
+
|----------|---------|-------------|----------|
|
|
178
|
+
| `BROWSER_MCP_CONFIG` | — | Yapılandırma dosyası yolu (JSON) | No |
|
|
45
179
|
|
|
46
|
-
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### Detaylı Özellikler
|
|
183
|
+
|
|
184
|
+
#### Mevcut Yetenekler
|
|
47
185
|
|
|
48
186
|
| Kategori | Tool Sayısı | Neler Yapabilir? |
|
|
49
187
|
|----------|------------|-------------------|
|
|
@@ -59,7 +197,7 @@ npx @natchs/browser-mcp
|
|
|
59
197
|
|
|
60
198
|
**Toplam: 40+ tool, 9 kategori, production-grade mimari**
|
|
61
199
|
|
|
62
|
-
|
|
200
|
+
#### Ne Yapabilir?
|
|
63
201
|
|
|
64
202
|
- **Reverse Engineering**: JS deobfuscation, API auth analizi, network isteklerini HAR formatında export
|
|
65
203
|
- **Web Scraping**: Cloudflare koruması olmayan sitelerden HTML/Markdown/text çekme, tablo ve Schema.org yapılandırılmış veri extraction
|
|
@@ -71,7 +209,15 @@ npx @natchs/browser-mcp
|
|
|
71
209
|
- **Observability**: Structured JSON logging, tool metrikleri (call count, süre, hata), LRU cache + TTL
|
|
72
210
|
- **Rate Limiting**: Token bucket, global + per-tool, yapılandırılabilir RPM
|
|
73
211
|
|
|
74
|
-
|
|
212
|
+
#### Browser Profil Yönetimi (v2.3.0)
|
|
213
|
+
|
|
214
|
+
Ajan, 3 farklı browser modundan biriyle çalışır:
|
|
215
|
+
|
|
216
|
+
- **`fresh` (default):** Playwright'ın kendi Chromium'unu kullanır, her seferinde sıfır profil. Çerez, geçmiş, uzantı — hiçbiri taşınmaz.
|
|
217
|
+
- **`persistent`:** Gerçek Chrome profilinizi kullanır. Oturum açtığınız tüm sitelere (Gmail, GitHub, ChatGPT, kurumsal VPN) ajan da "sizmiş gibi" erişir. v2.3.0 ile profil otomatik tespit edilir — `BROWSER_MODE=persistent` yazmanız yeterli.
|
|
218
|
+
- **`connect`:** Halihazırda `--remote-debugging-port` ile açılmış Chrome'unuza bağlanır. Mevcut sekmeleri ve oturumları ajanla paylaşırsınız.
|
|
219
|
+
|
|
220
|
+
#### Ne Yapamaz? (Mevcut Sınırlamalar)
|
|
75
221
|
|
|
76
222
|
- **Cloudflare/anti-bot korumalı siteler**: Challenge sayfalarını geçemez, manuel çözüm gerekir
|
|
77
223
|
- **Captcha çözümü**: Dahili captcha çözücü yoktur (üçüncü parti servislerle entegre edilebilir)
|
|
@@ -80,23 +226,23 @@ npx @natchs/browser-mcp
|
|
|
80
226
|
- **Canvas/WebGL fingerprinting**: Temel fingerprint değişir ama gelişmiş anti-bot sistemlerini geçemeyebilir
|
|
81
227
|
- **Mobil browser simülasyonu**: Sadece Chromium desktop, mobile viewport taklidi yapabilir
|
|
82
228
|
|
|
83
|
-
|
|
229
|
+
#### Güvenlik Özellikleri
|
|
84
230
|
|
|
85
231
|
- `redirect: 'manual'` tüm URL fetch çağrılarında — SSRF redirect bypass koruması
|
|
86
232
|
- `validateUrlAsync` DNS lookup — DNS rebind saldırılarına karşı
|
|
87
233
|
- `DANGEROUS_EXTENSIONS` blocklist (.exe, .bat, .sh vb) → güvenli `.bin` fallback
|
|
88
234
|
- Pseudo-FS path blocking (`/proc/`, `/sys/`, `/etc/` vb)
|
|
89
235
|
- Cookie header filtresi — Stage 3 HTTP re-fetch'te cross-origin credential sızıntısı önlenir
|
|
90
|
-
- `downloadEnabled` varsayılan **false** — kullanıcı açıkça enable etmeden
|
|
236
|
+
- `downloadEnabled` (download) ve `networkSaveEnabled` (network_save) varsayılan **false** — kullanıcı açıkça enable etmeden çalışmaz
|
|
91
237
|
- Input sanitizasyonu (null byte, path traversal, fileName injection)
|
|
92
238
|
|
|
93
|
-
|
|
239
|
+
#### MCP Client Uyumluluğu
|
|
94
240
|
|
|
95
241
|
Claude Desktop, Cursor, VS Code (Cline, Roo Code), Continue.dev, özel MCP istemcileri — protocol uyumlu tüm platformlar.
|
|
96
242
|
|
|
97
243
|
---
|
|
98
244
|
|
|
99
|
-
|
|
245
|
+
### Daha Fazlası Yolda
|
|
100
246
|
|
|
101
247
|
Bu proje aktif geliştirme aşamasındadır. Kısa süre içinde:
|
|
102
248
|
|
|
@@ -108,7 +254,204 @@ Bu proje aktif geliştirme aşamasındadır. Kısa süre içinde:
|
|
|
108
254
|
|
|
109
255
|
---
|
|
110
256
|
|
|
111
|
-
|
|
257
|
+
### Geliştirme
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
# Test
|
|
261
|
+
npm test
|
|
262
|
+
npm run test:coverage
|
|
263
|
+
|
|
264
|
+
# Type check (tsc --noEmit)
|
|
265
|
+
npm run lint
|
|
266
|
+
|
|
267
|
+
# Build
|
|
268
|
+
npm run build
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Lisans
|
|
272
|
+
|
|
273
|
+
MIT
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## 🇬🇧 English
|
|
278
|
+
|
|
279
|
+
**Browser automation MCP server** — a Model Context Protocol server designed for reverse engineering, web scraping, and data extraction. It gives AI agents full control over a browser.
|
|
280
|
+
|
|
281
|
+
### Quick Start
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
# 1. Install
|
|
285
|
+
npm install @natchs/browser-mcp
|
|
286
|
+
|
|
287
|
+
# 2. Run (Chromium installs automatically ~30s on first run)
|
|
288
|
+
npx @natchs/browser-mcp
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
#### MCP Client Config
|
|
292
|
+
|
|
293
|
+
Add to Claude Desktop, Cursor, VS Code, or any MCP client:
|
|
294
|
+
|
|
295
|
+
```json
|
|
296
|
+
{
|
|
297
|
+
"mcpServers": {
|
|
298
|
+
"browser-mcp": {
|
|
299
|
+
"command": "npx",
|
|
300
|
+
"args": ["@natchs/browser-mcp"]
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
You can also clone and build locally:
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
git clone https://github.com/natchs/browser-mcp.git
|
|
310
|
+
cd browser-mcp
|
|
311
|
+
npm ci
|
|
312
|
+
npm run build
|
|
313
|
+
npx @natchs/browser-mcp
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
#### Browser Profile: 3 Modes
|
|
317
|
+
|
|
318
|
+
The `BROWSER_MODE` environment variable determines which browser the agent uses:
|
|
319
|
+
|
|
320
|
+
| Mode | Description | When to Use |
|
|
321
|
+
|------|-------------|-------------|
|
|
322
|
+
| `fresh` (default) | Playwright's own Chromium. Fresh profile every time, no cookies/extensions/logins | Clean environment, leave no trace |
|
|
323
|
+
| `persistent` | **Your Chrome profile.** Real cookies, history, extensions, logged-in accounts — all available to the agent | When the agent needs to act "as you" on sites |
|
|
324
|
+
| `connect` | Connects to your already-open Chrome via CDP | When manually controlling Chrome alongside the agent |
|
|
325
|
+
|
|
326
|
+
**Example — persistent (auto-detect profile):**
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
BROWSER_MODE=persistent npx @natchs/browser-mcp
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Since v2.3.0 the Chrome profile is auto-detected. No path needed. Works on Windows/macOS/Linux. To specify a manual path:
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
BROWSER_MODE=persistent BROWSER_USER_DATA_DIR=C:\Users\...\User Data\Default npx @natchs/browser-mcp
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**Example — connect (attach to existing Chrome):**
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
# First open Chrome with debug port:
|
|
342
|
+
"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222
|
|
343
|
+
|
|
344
|
+
# Then start the agent:
|
|
345
|
+
BROWSER_MODE=connect npx @natchs/browser-mcp
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**MCP Client Config — separate profiles per mode:**
|
|
349
|
+
|
|
350
|
+
```json
|
|
351
|
+
{
|
|
352
|
+
"mcpServers": {
|
|
353
|
+
"browser-mcp-persistent": {
|
|
354
|
+
"command": "npx",
|
|
355
|
+
"args": ["@natchs/browser-mcp"],
|
|
356
|
+
"env": {
|
|
357
|
+
"BROWSER_MODE": "persistent"
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
"browser-mcp-fresh": {
|
|
361
|
+
"command": "npx",
|
|
362
|
+
"args": ["@natchs/browser-mcp"],
|
|
363
|
+
"env": {
|
|
364
|
+
"BROWSER_MODE": "fresh"
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
### Environment Variables
|
|
374
|
+
|
|
375
|
+
All configuration can be done via environment variables. The table below lists all supported variables. (Same as the Turkish table above — see the Turkish section for the full list.)
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
### Detailed Features
|
|
380
|
+
|
|
381
|
+
#### Current Capabilities
|
|
382
|
+
|
|
383
|
+
| Category | Tools | Capabilities |
|
|
384
|
+
|----------|-------|--------------|
|
|
385
|
+
| **Navigation** | 5 | Open page, back/forward, refresh, wait for element/URL |
|
|
386
|
+
| **Interaction** | 8 | Click, fill form, select box, hover, drag-drop, keyboard, file upload |
|
|
387
|
+
| **Extraction** | 7 | HTML, Markdown, plain text, CSS selector, tables, Schema.org, Open Graph |
|
|
388
|
+
| **Network** | 10 | Request/response tracking, HAR/JSON/CSV export, WebSocket frame capture, body save, console log |
|
|
389
|
+
| **Browser Control** | 8 | Screenshot, PDF, cookie management, JavaScript execution, file download |
|
|
390
|
+
| **Session** | 3 | Multi-session open/close/list, automatic TTL cleanup |
|
|
391
|
+
| **Admin** | 3 | Server status, cache statistics, cache clear |
|
|
392
|
+
| **RE Tools** | 4 | JavaScript beautify/deobfuscate, API endpoint discovery, auth analysis |
|
|
393
|
+
| **Stealth** | 2 | Fingerprint rotation, human behavior simulation |
|
|
394
|
+
|
|
395
|
+
**Total: 40+ tools, 9 categories, production-grade architecture**
|
|
396
|
+
|
|
397
|
+
#### What It Can Do
|
|
398
|
+
|
|
399
|
+
- **Reverse Engineering**: JS deobfuscation, API auth analysis, network request export in HAR format
|
|
400
|
+
- **Web Scraping**: HTML/Markdown/text extraction from non-Cloudflare sites, table and Schema.org structured data extraction
|
|
401
|
+
- **Network Monitoring**: Real-time HTTP/HTTPS interception, WebSocket frame inspection, binary body save to disk
|
|
402
|
+
- **Form Automation**: Login forms, search, multi-step form filling, file upload
|
|
403
|
+
- **Session Management**: Each isolated, concurrent browser sessions with automatic TTL cleanup
|
|
404
|
+
- **Security**: SSRF protection (internal IP blocking, DNS rebind prevention, redirect bypass guard), path traversal prevention, MIME-based extension blocklist, cookie leak protection
|
|
405
|
+
- **Data Export**: Network captures as HAR/JSON/CSV, body save, WS frame save (.jsonl)
|
|
406
|
+
- **Observability**: Structured JSON logging, tool metrics (call count, duration, errors), LRU cache + TTL
|
|
407
|
+
- **Rate Limiting**: Token bucket, global + per-tool, configurable RPM
|
|
408
|
+
|
|
409
|
+
#### Browser Profile Management (v2.3.0)
|
|
410
|
+
|
|
411
|
+
The agent works in one of 3 browser modes:
|
|
412
|
+
|
|
413
|
+
- **`fresh` (default):** Uses Playwright's own Chromium, fresh profile every time. No cookies, history, or extensions are carried over.
|
|
414
|
+
- **`persistent`:** Uses your real Chrome profile. The agent accesses all your logged-in sites (Gmail, GitHub, ChatGPT, corporate VPN) as "you." Since v2.3.0, profiles are auto-detected — just set `BROWSER_MODE=persistent`.
|
|
415
|
+
- **`connect`:** Connects to your already-running Chrome via `--remote-debugging-port`. Share existing tabs and sessions with the agent.
|
|
416
|
+
|
|
417
|
+
#### Limitations
|
|
418
|
+
|
|
419
|
+
- **Cloudflare/anti-bot sites**: Cannot bypass challenge pages, manual solving required
|
|
420
|
+
- **Captcha solving**: No built-in captcha solver (third-party services can be integrated)
|
|
421
|
+
- **Visual recognition**: Can take screenshots but cannot interpret content
|
|
422
|
+
- **Native file download**: `browser_download` is URL-based, does not cover Playwright native download events
|
|
423
|
+
- **Canvas/WebGL fingerprinting**: Basic fingerprint changes but may not bypass advanced anti-bot systems
|
|
424
|
+
- **Mobile browser simulation**: Chromium desktop only, can emulate mobile viewport
|
|
425
|
+
|
|
426
|
+
#### Security Features
|
|
427
|
+
|
|
428
|
+
- `redirect: 'manual'` on all URL fetch calls — SSRF redirect bypass protection
|
|
429
|
+
- `validateUrlAsync` DNS lookup — DNS rebind attack prevention
|
|
430
|
+
- `DANGEROUS_EXTENSIONS` blocklist (.exe, .bat, .sh etc.) → safe `.bin` fallback
|
|
431
|
+
- Pseudo-FS path blocking (`/proc/`, `/sys/`, `/etc/` etc.)
|
|
432
|
+
- Cookie header filter — prevents cross-origin credential leakage in Stage 3 HTTP re-fetch
|
|
433
|
+
- `downloadEnabled` and `networkSaveEnabled` default to **false** — must be explicitly enabled
|
|
434
|
+
- Input sanitization (null byte, path traversal, fileName injection)
|
|
435
|
+
|
|
436
|
+
#### MCP Client Compatibility
|
|
437
|
+
|
|
438
|
+
Claude Desktop, Cursor, VS Code (Cline, Roo Code), Continue.dev, custom MCP clients — all protocol-compliant platforms.
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
### Roadmap
|
|
443
|
+
|
|
444
|
+
This project is under active development. Coming soon:
|
|
445
|
+
|
|
446
|
+
- **New tools**: PDF extraction, screenshot annotation, form detection, cookie manager, session snapshot/restore
|
|
447
|
+
- **Cloudflare bypass**: Playwright Stealth integration, rotatable proxy support
|
|
448
|
+
- **Batch scraping**: Multi-page scraping pipeline, queue system
|
|
449
|
+
- **Performance**: Ring buffer optimization, streaming response, lazy evaluation
|
|
450
|
+
- **Developer Experience**: Interactive CLI, playground UI, type-safe client SDK
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
### Development
|
|
112
455
|
|
|
113
456
|
```bash
|
|
114
457
|
# Test
|
|
@@ -122,6 +465,6 @@ npm run lint
|
|
|
122
465
|
npm run build
|
|
123
466
|
```
|
|
124
467
|
|
|
125
|
-
|
|
468
|
+
### License
|
|
126
469
|
|
|
127
470
|
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-logger.d.ts","sourceRoot":"","sources":["../../src/core/audit-logger.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,mBAAmB,GAAG,aAAa,GAAG,YAAY,GAAG,aAAa,GAAG,gBAAgB,CAAC;AAEhI,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAElF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-logger.js","sourceRoot":"","sources":["../../src/core/audit-logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrC,MAAM,UAAU,QAAQ,CAAC,KAAiB,EAAE,OAAgC;IAC1E,MAAM,CAAC,IAAI,CAAC,WAAW,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC"}
|
package/dist/core/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIhD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,CA2ChE"}
|
package/dist/core/auth.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as crypto from 'node:crypto';
|
|
2
|
+
import { auditLog } from './audit-logger.js';
|
|
1
3
|
/**
|
|
2
4
|
* Creates an auth middleware that checks apiKey.
|
|
3
5
|
* If apiKey is not set, the middleware passes through (no auth).
|
|
@@ -5,7 +7,33 @@
|
|
|
5
7
|
export function createAuthMiddleware(apiKey) {
|
|
6
8
|
return async (pc, next) => {
|
|
7
9
|
if (apiKey) {
|
|
8
|
-
if (!pc.args.api_key
|
|
10
|
+
if (!pc.args.api_key) {
|
|
11
|
+
auditLog('AUTH_FAILURE', { reason: 'missing_key', tool: pc.toolName });
|
|
12
|
+
return {
|
|
13
|
+
...pc,
|
|
14
|
+
response: {
|
|
15
|
+
content: [{
|
|
16
|
+
type: 'text',
|
|
17
|
+
text: JSON.stringify({ ok: false, error: { code: 'UNAUTHORIZED', message: 'Invalid or missing API key' } }),
|
|
18
|
+
}],
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const providedKey = String(pc.args.api_key);
|
|
23
|
+
if (providedKey.length !== apiKey.length) {
|
|
24
|
+
auditLog('AUTH_FAILURE', { reason: 'length_mismatch', tool: pc.toolName });
|
|
25
|
+
return {
|
|
26
|
+
...pc,
|
|
27
|
+
response: {
|
|
28
|
+
content: [{
|
|
29
|
+
type: 'text',
|
|
30
|
+
text: JSON.stringify({ ok: false, error: { code: 'UNAUTHORIZED', message: 'Invalid or missing API key' } }),
|
|
31
|
+
}],
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
if (!crypto.timingSafeEqual(Buffer.from(providedKey), Buffer.from(apiKey))) {
|
|
36
|
+
auditLog('AUTH_FAILURE', { reason: 'key_mismatch', tool: pc.toolName });
|
|
9
37
|
return {
|
|
10
38
|
...pc,
|
|
11
39
|
response: {
|
package/dist/core/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAe;IAClD,OAAO,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;QACxB,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACrB,QAAQ,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;gBACvE,OAAO;oBACL,GAAG,EAAE;oBACL,QAAQ,EAAE;wBACR,OAAO,EAAE,CAAC;gCACR,IAAI,EAAE,MAAe;gCACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,4BAA4B,EAAE,EAAE,CAAC;6BAC5G,CAAC;qBACH;iBACF,CAAC;YACJ,CAAC;YACD,MAAM,WAAW,GAAG,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC5C,IAAI,WAAW,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;gBACzC,QAAQ,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,iBAAiB,EAAE,IAAI,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAC3E,OAAO;oBACL,GAAG,EAAE;oBACL,QAAQ,EAAE;wBACR,OAAO,EAAE,CAAC;gCACR,IAAI,EAAE,MAAe;gCACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,4BAA4B,EAAE,EAAE,CAAC;6BAC5G,CAAC;qBACH;iBACF,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;gBAC3E,QAAQ,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;gBACxE,OAAO;oBACL,GAAG,EAAE;oBACL,QAAQ,EAAE;wBACR,OAAO,EAAE,CAAC;gCACR,IAAI,EAAE,MAAe;gCACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,4BAA4B,EAAE,EAAE,CAAC;6BAC5G,CAAC;qBACH;iBACF,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"body-fetch.d.ts","sourceRoot":"","sources":["../../src/core/body-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"body-fetch.d.ts","sourceRoot":"","sources":["../../src/core/body-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAMxC,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IACjC,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,qBAAa,gBAAgB;IACf,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAEnC,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,eAAe,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,SAAS,CAAA;KAAE,CAAC;CAgFrK"}
|
package/dist/core/body-fetch.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { ErrorCode } from './errors.js';
|
|
2
|
-
import { validateUrl } from './sandbox.js';
|
|
2
|
+
import { validateUrl, isInternalIP } from './sandbox.js';
|
|
3
3
|
import { logger } from './logger.js';
|
|
4
|
+
import { auditLog } from './audit-logger.js';
|
|
5
|
+
import * as dns from 'node:dns';
|
|
4
6
|
export class BodyFetchService {
|
|
5
7
|
config;
|
|
6
8
|
constructor(config) {
|
|
@@ -38,12 +40,34 @@ export class BodyFetchService {
|
|
|
38
40
|
}
|
|
39
41
|
const urlCheck = validateUrl(entry.url);
|
|
40
42
|
if (!urlCheck.valid) {
|
|
43
|
+
auditLog('DNS_REBIND', { url: entry.url, reason: urlCheck.error });
|
|
41
44
|
return { error: 'SSRF blocked: ' + urlCheck.error, code: ErrorCode.NETWORK_RESPONSE_FAILED };
|
|
42
45
|
}
|
|
46
|
+
const parsedUrl = new URL(entry.url);
|
|
47
|
+
let fetchUrl = entry.url;
|
|
48
|
+
try {
|
|
49
|
+
const addresses = await dns.promises.lookup(parsedUrl.hostname, { all: true });
|
|
50
|
+
for (const addr of addresses) {
|
|
51
|
+
if (isInternalIP(addr.address)) {
|
|
52
|
+
auditLog('INTERNAL_IP', { url: entry.url, ip: addr.address });
|
|
53
|
+
return { error: `DNS rebind blocked: ${entry.url} resolves to internal IP ${addr.address}`, code: ErrorCode.INTERNAL_IP };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// TOCTOU DNS rebind fix: use resolved IP directly for HTTP
|
|
57
|
+
if (parsedUrl.protocol === 'http:' && addresses.length > 0) {
|
|
58
|
+
fetchUrl = `http://${addresses[0].address}${parsedUrl.pathname}${parsedUrl.search}`;
|
|
59
|
+
headers['Host'] = parsedUrl.hostname;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
64
|
+
auditLog('DNS_REBIND', { url: entry.url, reason: `DNS lookup failed for ${parsedUrl.hostname}: ${errMsg}` });
|
|
65
|
+
throw new Error(`DNS lookup failed for ${parsedUrl.hostname}: ${errMsg}`);
|
|
66
|
+
}
|
|
43
67
|
const controller = new AbortController();
|
|
44
68
|
const timeout = setTimeout(() => controller.abort(), 30000);
|
|
45
69
|
try {
|
|
46
|
-
const response = await fetch(
|
|
70
|
+
const response = await fetch(fetchUrl, {
|
|
47
71
|
method: entry.method,
|
|
48
72
|
headers: Object.keys(headers).length > 0 ? headers : undefined,
|
|
49
73
|
signal: controller.signal,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"body-fetch.js","sourceRoot":"","sources":["../../src/core/body-fetch.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"body-fetch.js","sourceRoot":"","sources":["../../src/core/body-fetch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Browser, BrowserContext, Page } from 'playwright';
|
|
2
|
+
import { BrowserProvider } from './browser-provider.js';
|
|
3
|
+
export declare class BrowserLifecycle {
|
|
4
|
+
private provider;
|
|
5
|
+
private headless;
|
|
6
|
+
private browser;
|
|
7
|
+
private context;
|
|
8
|
+
private pages;
|
|
9
|
+
private nextPageId;
|
|
10
|
+
private _maxPages;
|
|
11
|
+
constructor(provider: BrowserProvider | undefined, headless: boolean, maxPages?: number);
|
|
12
|
+
set maxPages(value: number);
|
|
13
|
+
get maxPages(): number;
|
|
14
|
+
get hasProvider(): boolean;
|
|
15
|
+
ensureBrowser(): Promise<Browser>;
|
|
16
|
+
createContext(): Promise<BrowserContext>;
|
|
17
|
+
getOrCreateContext(): Promise<BrowserContext>;
|
|
18
|
+
createPage(): Promise<{
|
|
19
|
+
page: Page;
|
|
20
|
+
id: string;
|
|
21
|
+
}>;
|
|
22
|
+
getPage(id: string): Page | undefined;
|
|
23
|
+
closePage(id: string): Promise<void>;
|
|
24
|
+
shutdown(): Promise<void>;
|
|
25
|
+
isRunning(): boolean;
|
|
26
|
+
getCurrentContext(): BrowserContext | null;
|
|
27
|
+
getCurrentBrowser(): Browser | null;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=browser-lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-lifecycle.d.ts","sourceRoot":"","sources":["../../src/core/browser-lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAIxD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,UAAU,CAAK;IAEvB,OAAO,CAAC,SAAS,CAAM;gBAEX,QAAQ,EAAE,eAAe,GAAG,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,SAAK;IAMnF,IAAI,QAAQ,CAAC,KAAK,EAAE,MAAM,EAEzB;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAEK,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC;IAWjC,aAAa,IAAI,OAAO,CAAC,cAAc,CAAC;IAQxC,kBAAkB,IAAI,OAAO,CAAC,cAAc,CAAC;IAM7C,UAAU,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAWvD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAI/B,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQpC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB/B,SAAS,IAAI,OAAO;IAIpB,iBAAiB,IAAI,cAAc,GAAG,IAAI;IAI1C,iBAAiB,IAAI,OAAO,GAAG,IAAI;CAGpC"}
|