garrytan/gstack · error · Error
JS execution blocked: current page (${hostname}) does not ma
Error message
JS execution blocked: current page (${hostname}) does not match any cookie-imported domain. Imported cookies for: ${[...importedDomains].join(', ')}. This prevents cross-origin cookie exfiltration. Navigate to an imported domain or run without imported cookies. What it means
Thrown by assertJsOriginAllowed when cookies have been imported for specific domains and the current page's hostname does not match any imported domain. This blocks js/eval execution on untrusted pages to prevent cross-origin cookie exfiltration via document.cookie. The check is bypassed only when no cookies have been imported, or when the page is about:blank / a data: URI.
Source
Thrown at browse/src/read-commands.ts:203
function assertJsOriginAllowed(bm: BrowserManager, pageUrl: string): void {
if (!bm.hasCookieImports()) return;
let hostname: string;
try {
hostname = new URL(pageUrl).hostname;
} catch {
return; // about:blank, data: URIs — allow (no cookies at risk)
}
const importedDomains = bm.getCookieImportedDomains();
const allowed = [...importedDomains].some(domain => {
// Exact match or subdomain match (e.g., ".github.com" matches "api.github.com")
const normalized = domain.startsWith('.') ? domain : '.' + domain;
return hostname === domain.replace(/^\./, '') || hostname.endsWith(normalized);
});
if (!allowed) {
throw new Error(
`JS execution blocked: current page (${hostname}) does not match any cookie-imported domain. ` +
`Imported cookies for: ${[...importedDomains].join(', ')}. ` +
`This prevents cross-origin cookie exfiltration. Navigate to an imported domain or run without imported cookies.`
);
}
}
export async function handleReadCommand(
command: string,
args: string[],
session: TabSession,
bm?: BrowserManager,
): Promise<string> {
const page = session.getPage();
// Frame-aware target for content extraction
const target = session.getActiveFrameOrPage();
switch (command) {View on GitHub (pinned to 94993f7401)
Solutions
- Navigate to a page under an imported domain before running js
- Import cookies for the additional domain (use .domain.com form to cover subdomains)
- Run without imported cookies if cross-origin exfiltration is not a concern for this flow
- Check the current URL: `browse js location.href` is itself blocked, so inspect via the text/links commands first
Example fix
// before: cookies imported for github.com, page is on evil.com browse js 'document.cookie' // throws // after: navigate to an imported domain first browse navigate https://github.com browse js 'document.cookie'
Defensive patterns
Strategy: try-catch
Validate before calling
function isOriginAllowed(pageUrl: string, importedDomains: Set<string>): boolean {
let hostname: string;
try { hostname = new URL(pageUrl).hostname; }
catch { return true; } // about:blank, data: URIs are allowed
if (importedDomains.size === 0) return true; // no imports → no restriction
return [...importedDomains].some(domain => {
const normalized = domain.startsWith('.') ? domain : '.' + domain;
return hostname === domain.replace(/^\.//, '') || hostname.endsWith(normalized);
});
}
// before running js
if (bm.hasCookieImports() && !isOriginAllowed(page.url(), bm.getCookieImportedDomains())) {
throw new Error(`Refusing js on ${page.url()}: not an imported domain. Navigate first.`);
} Type guard
function isAllowedHostname(hostname: string, importedDomains: Set<string>): boolean {
return [...importedDomains].some(domain => {
const normalized = domain.startsWith('.') ? domain : '.' + domain;
return hostname === domain.replace(/^\.//, '') || hostname.endsWith(normalized);
});
} Try / catch
try {
await runJs(expr);
} catch (e: any) {
if (/JS execution blocked/.test(e.message)) {
// navigate to an imported domain, then retry
const target = [...bm.getCookieImportedDomains()][0].replace(/^\./, '');
await browse.navigate(`https://${target}`);
await runJs(expr);
} else throw e;
} Prevention
- Import cookies with the .domain.com form to cover all subdomains
- Before running js, verify the current page hostname with the text/links commands (js itself is blocked)
- Clear imported cookies if you need to run js on an unrelated page
- Watch for OAuth/SSO redirects that cross origins mid-flow — re-navigate before js
When it happens
Trigger: After importing cookies for github.com, running `browse js ...` while the page is on a different hostname (e.g., evil.com, an OAuth redirect page, a login portal). bm.hasCookieImports() is true, the page hostname does not match any imported domain exactly or as a subdomain.
Common situations: Agent navigated through an OAuth/SSO redirect that crosses origins; testing flow legitimately spans multiple domains but cookies were imported for only one; forgot to import cookies for a subdomain (e.g., imported github.com but page is on api.github.com without the .github.com wildcard); landed on a phishing/interstitial page.
Related errors
- Path must be within: ${TEMP_ONLY.join(', ')} (remote file se
- Cookie domain "${c.domain}" does not match current page doma
- --domain "${domain}" does not match current page domain "${p
- Invalid skill name "${name}". Must be lowercase letters/digi
- Invalid file path in stageSkill: "${relPath}".
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/21eecc1eeb48c9ce.
Report an issue: GitHub.