Skip to content
bitzorcas
中EN

Guide

Crawler security and browser sessions

The current Selenium port, implicit browser state, SSRF and script risks, cancellation limits, and production isolation design.

Last updated

The crawler port hides Selenium types, but it does not create a secure browser platform. Its operations share an implicit “current page,” making it a trusted internal primitive rather than a multi-tenant request API.

1. Four current operations

MethodInputEffect/output
OpenUrlAsyncURL, optional TenantIdMutates current browser page
FindElementAsyncID/name/class/tag/CSS/XPathElement snapshot
ScreenshotAsyncoptional TenantIdURL, title, PNG bytes
ExecuteScriptAsyncscript and argumentsArbitrary script result

TenantId is not an isolation boundary. Open ignores it and Screenshot uses it only in a Debug log.

2. Implicit session race

"Shared CrawlingService""Tenant B""Tenant A""Shared CrawlingService""Tenant B""Tenant A"OpenUrl(A)OpenUrl(B)Screenshot()possibly B's page

The port has no browser/session handle and cannot bind open→find→script→screenshot into one atomic work unit. A singleton SDK service can leak page state, cookies, and results across concurrent callers.

3. Current URL validation

The adapter rejects only blank URLs. It has no scheme, host, resolved-address, port, redirect, user-info, DNS-rebinding, download-size, or response-type policy.

Passing user input directly therefore creates SSRF exposure to cloud metadata, private networks, link-local services, and the local host.

4. Policy wrapper

Open an approved target
// ① Require an absolute normalized HTTP(S) URI without user-info.
Uri target = await urlPolicy.ParseAndValidateAsync(command.Url, cancellationToken);
// ② Validate every resolved address against public/tenant allowlists.
await urlPolicy.AssertPublicOrTenantAllowlistedAsync(target, cancellationToken);
// ③ The current port does not repeat these controls.
Result opened = await crawler.OpenUrlAsync(
new CrawlerOpenUrlRequest(target.ToString(), trustedTenantId),
cancellationToken);

Redirects require per-hop revalidation; validating the initial address alone is insufficient.

5. Script boundary

ExecuteScriptAsync only rejects blank script. It defines no template catalog, operation allowlist, sandbox, or output budget. User-controlled script is arbitrary execution inside the browser context.

Expose server-owned operations such as ReadInvoiceTotal; map them to fixed scripts and schemas. Arguments should be bounded JSON primitives and validated selectors.

Server-owned script catalog
// ① Resolve only an operation registered by the server.
CrawlerScriptDefinition definition = scriptCatalog.Get(command.Operation);
definition.Validate(command.Arguments, currentTarget);
// ② The request never supplies raw JavaScript.
return await crawler.ExecuteScriptAsync(
new CrawlerExecuteScriptRequest(definition.Script, command.Arguments), ct);

6. Locator and data leakage

CSS and XPath can be computationally expensive. XPath can also reach content outside an intended page region. Constrain strategy, length, count, and root scope per operation.

Element projection includes the full href, which can contain tokens or query secrets. Redact or normalize it before logs, audit, or client output.

7. Serializable output

The adapter converts only a directly returned IWebElement to a string. Collections, dictionaries, or nested objects can still contain Selenium objects and fail serialization or leak implementation details.

A production contract should allow only explicit JSON scalars and bounded arrays. Reject unknown object graphs.

8. Cancellation and timeout

Synchronous Selenium calls are wrapped in Task.Run(..., cancellationToken). Cancellation can prevent scheduling but does not interrupt a WebDriver call that has started.

Configure WebDriver page/script timeouts, work-unit deadlines, driver disposal after timeout, process watchdogs, bounded queues, and tenant concurrency quotas. Do not describe the token as immediate underlying cancellation.

9. Error translation

The adapter catches WebDriver, no-such-element/not-found, and timeout exceptions, returns ProviderFailed, and includes the raw exception message.

Owner code should classify target rejection, navigation timeout, missing element, script failure, and broken session. Raw details belong in restricted diagnostics; unknown exceptions still need global handling.

10. Isolation design

Trusted owner request

Tenant quota queue

Browser session pool

Session + tenant binding

Fixed operation catalog

Destroy / clear state

A session should bind tenant, actor, allowed domains, creation time, deadline, and exclusive ownership. Cleanup must cover cookies, local storage, downloads, cache, and temporary profiles. High-sensitivity work should use disposable processes/containers.

11. Test matrix

Cover loopback, private IPv4/IPv6, link-local and metadata targets; encoded IPs, user-info, redirects and rebinding; concurrent tenant isolation; cookie/storage cleanup; timed-out driver retirement; arbitrary script and huge-output rejection; nested element results; and error-detail redaction.

No such tests exist in current source, so the port should remain a trusted internal primitive.

A consumer design review must identify:

  • whether a page may contain another tenant’s data;
  • the exact domain and redirect allowlists;
  • who owns each browser session;
  • which cookies or credentials enter the browser;
  • which fixed scripts and selectors are allowed;
  • maximum navigation and script time;
  • maximum screenshot and script-output bytes;
  • cleanup evidence after success, timeout, and crash;
  • response fields that require redaction;
  • the fallback behavior when no browser is available.

12. Operations and source check

Limit browser CPU, memory, file descriptors, and processes. Pin browser/driver compatibility, patch promptly, deny network egress by default, isolate downloads, and monitor queue, sessions, timeouts, crashes, and cleanup failures.

Treat browser unavailability as an explicit degraded capability, never as permission to bypass the owner workflow.

Terminal window
rg -n "OpenUrlAsync|ExecuteScriptAsync|Task.Run|IWebElement" \
src/Platform/ToolConnectors -g '*.cs'

Back to Tool Connectors

100%

Scroll or use controls to zoom · drag when enlarged · double-click for 100% / 200%