Skip to content

Commit adc74bc

Browse files
ericdalloeca-agent
andcommitted
Fix auto-discovery false positives behind reverse proxies
probePort() used `mode: 'no-cors'` which only checked "is something listening?" — any HTTP response (even a 502 from Tailscale serve) counted as a live ECA server. Now performs a real CORS-enabled health check and validates the JSON response (`status: "ok"`), so reverse-proxy ports without an actual ECA backend are correctly filtered out. 🤖 Generated with [eca](https://eca.dev) Co-Authored-By: eca-agent <git@eca.dev>
1 parent d2064c8 commit adc74bc

1 file changed

Lines changed: 7 additions & 3 deletions

File tree

src/bridge/connection.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ import { detectBrowser, fetchWithTimeout, ipToSslipHostname, isLocalNetworkHost,
1414
* Lightweight probe to check if an ECA server is listening on a given port.
1515
*
1616
* Used by auto-discovery to quickly scan a port range without requiring
17-
* full authentication. Uses `mode: 'no-cors'` so we only need to know
18-
* "is something responding?" — the opaque response is fine for discovery.
17+
* full authentication. Performs a real CORS-enabled health check and
18+
* validates the JSON response, so reverse-proxy ports without an actual
19+
* ECA backend (e.g. Tailscale `serve`) are correctly filtered out.
1920
*
2021
* Tries both HTTP and HTTPS in parallel to handle protocol mismatches
2122
* (e.g. user selected HTTPS but server runs HTTP, or vice-versa).
@@ -35,7 +36,10 @@ export async function probePort(
3536
? ipToSslipHostname(`${host}:${port}`).split(':')[0]
3637
: host;
3738
const url = `${proto}://${effectiveHost}:${port}/api/v1/health`;
38-
await fetchWithTimeout(url, { mode: 'no-cors' }, 3_000);
39+
const res = await fetchWithTimeout(url, {}, 3_000);
40+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
41+
const body = await res.json();
42+
if (body?.status !== 'ok') throw new Error('Not an ECA server');
3943
}),
4044
);
4145
return results.some((r) => r.status === 'fulfilled');

0 commit comments

Comments
 (0)