Affected Version: 4.1.3
Summary
AnyProxy's local web interface (default http://127.0.0.1:8002, started automatically by anyproxy --web / anyproxy-ca workflows) has no authentication whatsoever, and its JSON API endpoints explicitly set Access-Control-Allow-Origin: *, unconditionally allowing any website to read the responses via fetch()/XMLHttpRequest. In addition, the companion WebSocket server performs no Origin validation at all, so any web page can open a WebSocket connection to it and receive a live broadcast stream of every request/response AnyProxy is currently recording, including headers such as Cookie and Authorization.
Because AnyProxy is a MITM debugging proxy, its whole purpose is to sit in the path of the traffic the user is inspecting (often traffic for other sites they are actively logged into while debugging). Any web page the user happens to have open in the same browser — completely unrelated to AnyProxy — can silently exfiltrate that captured traffic in real time, with zero user interaction with AnyProxy and no way for the user to notice.
Details
lib/webInterface.js sets a wildcard CORS header on the endpoints that expose the recorder's data:
// lib/webInterface.js
app.get('/latestLog', (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
recorder.getRecords(null, 10000, (err, docs) => {
if (err) {
res.end(err.toString());
} else {
res.json(docs);
}
});
});
/latestLog returns up to 10,000 full traffic records via recorder.getRecords, and each record includes the full request/response headers as captured by recorder.js:
// lib/recorder.js — normalizeInfo()
singleRecord.reqHeader = info.req.headers; // includes Cookie, Authorization, etc.
...
singleRecord.resHeader = info.resHeader;
The same Access-Control-Allow-Origin: * pattern is repeated on /fetchBody, /fetchCrtFile, /api/getQrCode, and /api/getInitData (lib/webInterface.js), so response bodies (/fetchBody, which can carry account data, tokens, API responses) and the AnyProxy root CA certificate (/fetchCrtFile) are also readable cross-origin. None of these routes check the Host or Origin request header before responding, and there is no authentication middleware anywhere in getServer().
Separately, lib/wsServer.js creates a ws WebSocketServer on the same HTTP server with no Origin verification:
// lib/wsServer.js
const wss = new WebSocketServer({
server: config.server,
clientTracking: true,
});
...
recorder.on('update', (data) => {
try {
sendMultipleMessage(data); // broadcast to ALL connected clients, no origin filter
} catch (e) { ... }
});
sendMultipleMessage broadcasts every new/updated traffic record to every connected WebSocket client with wss.broadcast(...). Browsers do not apply the Same-Origin Policy to the WebSocket handshake itself, so a malicious page can open new WebSocket('ws://127.0.0.1:8002') from any origin and receive this live firehose without any CORS headers being involved at all — this channel is not mitigated even by fixing the Access-Control-Allow-Origin: * issue above.
Live validation
Pinned release: anyproxy@4.1.3 (npm), matching git commit b93f9481 ("release 4.1.3", the HEAD of the repository).
- Started AnyProxy locally with its default web UI:
node bin/anyproxy -w 8002
- Sent a forged
Origin header from a completely unrelated domain directly to the web API and confirmed the server reflects/allows it unconditionally:
$ curl -sS -i -H "Origin: http://evil.example.com" http://127.0.0.1:8002/api/getInitData
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
...
{"status":"success","rootCAExists":false, ...}
- Proxied a request carrying secret cookie values through AnyProxy (simulating the victim debugging a real logged-in site):
$ curl -x http://127.0.0.1:8001 -H "Cookie: session=SECRET_TOKEN_abc123; auth=topsecret" http://httpbin.org/get
- Confirmed the secret is retrievable cross-origin via the wildcarded HTTP endpoint:
$ curl -sS -H "Origin: http://evil.example.com" http://127.0.0.1:8002/latestLog
[{"url":"http://httpbin.org/get","reqHeader":{"Cookie":"session=SECRET_TOKEN_abc123; auth=topsecret", ...}, ...}]
- Confirmed the WebSocket channel independently discloses the same data with no Origin check, by connecting with a forged
Origin: http://evil.example.com header and observing a live broadcast the moment a second proxied request was made:
$ curl -x http://127.0.0.1:8001 -H "Cookie: session2=ANOTHER_SECRET_xyz" http://httpbin.org/headers
WebSocket client output (Origin header forged to evil.example.com, connection accepted, no rejection):
WS OPENED cross-origin (evil.example.com) with no rejection
WS MESSAGE: {"type":"updateMultiple","content":[{"url":"http://httpbin.org/headers", ...,
"reqHeader":{...,"Cookie":"session2=ANOTHER_SECRET_xyz"}, ...}]}
Both channels independently and fully disclosed the injected secret values to a simulated cross-origin attacker, with zero authentication and zero legitimate Origin required.
Proof of Concept
(available upon request)
Impact
Any website a user visits in the same browser while AnyProxy's local web UI is running can silently steal the full contents of every HTTP/HTTPS request and response AnyProxy has captured or is currently capturing — including session cookies, Authorization bearer tokens, API keys in headers or bodies, and any other sensitive data present in traffic the user is debugging through AnyProxy. Because AnyProxy's entire purpose is to intercept traffic for other applications the user is actively testing (often while logged in with real credentials), this converts routine use of a local debugging tool into a drive-by credential/session theft primitive triggerable by any page open in another tab, with no interaction with AnyProxy required.
Affected Version: 4.1.3
Summary
AnyProxy's local web interface (default
http://127.0.0.1:8002, started automatically byanyproxy --web/anyproxy-caworkflows) has no authentication whatsoever, and its JSON API endpoints explicitly setAccess-Control-Allow-Origin: *, unconditionally allowing any website to read the responses viafetch()/XMLHttpRequest. In addition, the companion WebSocket server performs noOriginvalidation at all, so any web page can open a WebSocket connection to it and receive a live broadcast stream of every request/response AnyProxy is currently recording, including headers such asCookieandAuthorization.Because AnyProxy is a MITM debugging proxy, its whole purpose is to sit in the path of the traffic the user is inspecting (often traffic for other sites they are actively logged into while debugging). Any web page the user happens to have open in the same browser — completely unrelated to AnyProxy — can silently exfiltrate that captured traffic in real time, with zero user interaction with AnyProxy and no way for the user to notice.
Details
lib/webInterface.jssets a wildcard CORS header on the endpoints that expose the recorder's data:/latestLogreturns up to 10,000 full traffic records viarecorder.getRecords, and each record includes the full request/response headers as captured byrecorder.js:The same
Access-Control-Allow-Origin: *pattern is repeated on/fetchBody,/fetchCrtFile,/api/getQrCode, and/api/getInitData(lib/webInterface.js), so response bodies (/fetchBody, which can carry account data, tokens, API responses) and the AnyProxy root CA certificate (/fetchCrtFile) are also readable cross-origin. None of these routes check theHostorOriginrequest header before responding, and there is no authentication middleware anywhere ingetServer().Separately,
lib/wsServer.jscreates awsWebSocketServeron the same HTTP server with no Origin verification:sendMultipleMessagebroadcasts every new/updated traffic record to every connected WebSocket client withwss.broadcast(...). Browsers do not apply the Same-Origin Policy to the WebSocket handshake itself, so a malicious page can opennew WebSocket('ws://127.0.0.1:8002')from any origin and receive this live firehose without any CORS headers being involved at all — this channel is not mitigated even by fixing theAccess-Control-Allow-Origin: *issue above.Live validation
Pinned release:
anyproxy@4.1.3(npm), matching git commitb93f9481("release 4.1.3", the HEAD of the repository).Originheader from a completely unrelated domain directly to the web API and confirmed the server reflects/allows it unconditionally:Origin: http://evil.example.comheader and observing a live broadcast the moment a second proxied request was made:Both channels independently and fully disclosed the injected secret values to a simulated cross-origin attacker, with zero authentication and zero legitimate Origin required.
Proof of Concept
(available upon request)
Impact
Any website a user visits in the same browser while AnyProxy's local web UI is running can silently steal the full contents of every HTTP/HTTPS request and response AnyProxy has captured or is currently capturing — including session cookies,
Authorizationbearer tokens, API keys in headers or bodies, and any other sensitive data present in traffic the user is debugging through AnyProxy. Because AnyProxy's entire purpose is to intercept traffic for other applications the user is actively testing (often while logged in with real credentials), this converts routine use of a local debugging tool into a drive-by credential/session theft primitive triggerable by any page open in another tab, with no interaction with AnyProxy required.