Security: LockInTime/headless

Security

SECURITY.md

Security policy

Headless exists to give an AI agent a browser it cannot misuse. The safety rules are enforced by the host process, not by prompting, so a vulnerability here is a vulnerability in the product's core promise. We take reports seriously.

Reporting a vulnerability

Do not open a public issue.

Use GitHub's private vulnerability reporting: Report a vulnerability. That opens a private advisory visible only to maintainers.

Please include:

  • affected version or commit, and platform (macOS engine or Linux Chromium engine)
  • what boundary you crossed, and the commands or page that crossed it
  • a minimal reproduction — a fixture page is ideal
  • what an attacker gains

We aim to acknowledge within 3 working days and to ship a fix or a documented mitigation before any public disclosure. Tell us if you intend to publish, and we will agree a timeline with you.

What counts as a vulnerability

These are host-enforced contracts. Anything that defeats one is in scope:

BoundaryExpected behaviour
No arbitrary code executionThere is no JavaScript-evaluation verb and no shell verb. Reaching arbitrary in-page or host execution through the protocol is a vulnerability.
NavigationHTTP/HTTPS only. file:, javascript:, data:, credential-bearing URLs, and external application schemes must be refused at every layer.
DownloadsPage-initiated downloads are denied. Executables, installers, scripts, libraries, and disk images are blocked by extension.
Control planeA 0600 Unix socket inside a 0700 per-user directory, with a peer-UID check. There is no TCP listener and no Chromium debug port. Any remote reachability is a vulnerability.
ArtifactsBare validated names, O_EXCL creation at 0600 inside a 0700 root, never overwritten. Path traversal or reading outside the store is a vulnerability.
SecretsCookie and storage values require both --values and HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS=1. Authorization, cookie, token, and secret headers, plus URL credentials, are always redacted. Flow recordings never contain typed values.
Untrusted contentEverything derived from a page is marked untrustedContent and is never executed as a command. A page that induces the host to act on its own text is a vulnerability.
SandboxThe Linux host refuses to run as root and never passes --no-sandbox. Snap Chromium is rejected before launch.

Prompt injection that merely persuades an agent to do something within these boundaries is not a host vulnerability — but if page content can escape the untrustedContent marking or reach a privileged path, that is.

Known limitations (not vulnerabilities)

These are documented design boundaries, not defects:

  • Same-user access. Any process running as your OS user can reach that user's socket, browser profile, and artifacts. Run untrusted agents as separate OS users.
  • Shared session state. Sessions are windows (macOS) or tabs (Linux) over one browser profile, so cookies and storage are shared between sessions. Per-session isolation is tracked in the roadmap, not implied today.
  • macOS diagnostics are best-effort. WebKit does not expose Chromium's event stream; the macOS QA bridge runs in the page world and is therefore observable by the page. Hardening it is tracked as #28.
  • Recording scope. The recorder captures browser frames only — never OS chrome, other applications, or audio.
  • Network mocking is Linux-only. macOS returns UNSUPPORTED_CAPABILITY rather than partially emulating traffic control.
  • HTTP on macOS. The ATS exception is limited to WKWebView so browser pages can use HTTP when required. Native application networking retains the default ATS protections.

Supported versions

Headless is pre-1.x in practice: fixes land on main and ship in the next tagged release. There is no long-term support branch yet.

Hardening guidance for operators

  • Run agents as a dedicated OS user, not your own account.
  • Leave HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS unset unless you are actively debugging, and never in a shared session.
  • Keep the stdio MCP server local, or tunnel it over SSH. Do not bridge it to a network listener.
  • Treat every artifact, report, and console line as potentially sensitive page content.

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Security: LockInTime/headless

Security

SECURITY.md

Security policy

Headless exists to give an AI agent a browser it cannot misuse. The safety rules are enforced by the host process, not by prompting, so a vulnerability here is a vulnerability in the product's core promise. We take reports seriously.

Reporting a vulnerability

Do not open a public issue.

Use GitHub's private vulnerability reporting: Report a vulnerability. That opens a private advisory visible only to maintainers.

Please include:

  • affected version or commit, and platform (macOS engine or Linux Chromium engine)
  • what boundary you crossed, and the commands or page that crossed it
  • a minimal reproduction — a fixture page is ideal
  • what an attacker gains

We aim to acknowledge within 3 working days and to ship a fix or a documented mitigation before any public disclosure. Tell us if you intend to publish, and we will agree a timeline with you.

What counts as a vulnerability

These are host-enforced contracts. Anything that defeats one is in scope:

BoundaryExpected behaviour
No arbitrary code executionThere is no JavaScript-evaluation verb and no shell verb. Reaching arbitrary in-page or host execution through the protocol is a vulnerability.
NavigationHTTP/HTTPS only. file:, javascript:, data:, credential-bearing URLs, and external application schemes must be refused at every layer.
DownloadsPage-initiated downloads are denied. Executables, installers, scripts, libraries, and disk images are blocked by extension.
Control planeA 0600 Unix socket inside a 0700 per-user directory, with a peer-UID check. There is no TCP listener and no Chromium debug port. Any remote reachability is a vulnerability.
ArtifactsBare validated names, O_EXCL creation at 0600 inside a 0700 root, never overwritten. Path traversal or reading outside the store is a vulnerability.
SecretsCookie and storage values require both --values and HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS=1. Authorization, cookie, token, and secret headers, plus URL credentials, are always redacted. Flow recordings never contain typed values.
Untrusted contentEverything derived from a page is marked untrustedContent and is never executed as a command. A page that induces the host to act on its own text is a vulnerability.
SandboxThe Linux host refuses to run as root and never passes --no-sandbox. Snap Chromium is rejected before launch.

Prompt injection that merely persuades an agent to do something within these boundaries is not a host vulnerability — but if page content can escape the untrustedContent marking or reach a privileged path, that is.

Known limitations (not vulnerabilities)

These are documented design boundaries, not defects:

  • Same-user access. Any process running as your OS user can reach that user's socket, browser profile, and artifacts. Run untrusted agents as separate OS users.
  • Shared session state. Sessions are windows (macOS) or tabs (Linux) over one browser profile, so cookies and storage are shared between sessions. Per-session isolation is tracked in the roadmap, not implied today.
  • macOS diagnostics are best-effort. WebKit does not expose Chromium's event stream; the macOS QA bridge runs in the page world and is therefore observable by the page. Hardening it is tracked as #28.
  • Recording scope. The recorder captures browser frames only — never OS chrome, other applications, or audio.
  • Network mocking is Linux-only. macOS returns UNSUPPORTED_CAPABILITY rather than partially emulating traffic control.
  • HTTP on macOS. The ATS exception is limited to WKWebView so browser pages can use HTTP when required. Native application networking retains the default ATS protections.

Supported versions

Headless is pre-1.x in practice: fixes land on main and ship in the next tagged release. There is no long-term support branch yet.

Hardening guidance for operators

  • Run agents as a dedicated OS user, not your own account.
  • Leave HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS unset unless you are actively debugging, and never in a shared session.
  • Keep the stdio MCP server local, or tunnel it over SSH. Do not bridge it to a network listener.
  • Treat every artifact, report, and console line as potentially sensitive page content.

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Security: LockInTime/headless

Security

SECURITY.md

Security policy

Headless exists to give an AI agent a browser it cannot misuse. The safety rules are enforced by the host process, not by prompting, so a vulnerability here is a vulnerability in the product's core promise. We take reports seriously.

Reporting a vulnerability

Do not open a public issue.

Use GitHub's private vulnerability reporting: Report a vulnerability. That opens a private advisory visible only to maintainers.

Please include:

  • affected version or commit, and platform (macOS engine or Linux Chromium engine)
  • what boundary you crossed, and the commands or page that crossed it
  • a minimal reproduction — a fixture page is ideal
  • what an attacker gains

We aim to acknowledge within 3 working days and to ship a fix or a documented mitigation before any public disclosure. Tell us if you intend to publish, and we will agree a timeline with you.

What counts as a vulnerability

These are host-enforced contracts. Anything that defeats one is in scope:

BoundaryExpected behaviour
No arbitrary code executionThere is no JavaScript-evaluation verb and no shell verb. Reaching arbitrary in-page or host execution through the protocol is a vulnerability.
NavigationHTTP/HTTPS only. file:, javascript:, data:, credential-bearing URLs, and external application schemes must be refused at every layer.
DownloadsPage-initiated downloads are denied. Executables, installers, scripts, libraries, and disk images are blocked by extension.
Control planeA 0600 Unix socket inside a 0700 per-user directory, with a peer-UID check. There is no TCP listener and no Chromium debug port. Any remote reachability is a vulnerability.
ArtifactsBare validated names, O_EXCL creation at 0600 inside a 0700 root, never overwritten. Path traversal or reading outside the store is a vulnerability.
SecretsCookie and storage values require both --values and HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS=1. Authorization, cookie, token, and secret headers, plus URL credentials, are always redacted. Flow recordings never contain typed values.
Untrusted contentEverything derived from a page is marked untrustedContent and is never executed as a command. A page that induces the host to act on its own text is a vulnerability.
SandboxThe Linux host refuses to run as root and never passes --no-sandbox. Snap Chromium is rejected before launch.

Prompt injection that merely persuades an agent to do something within these boundaries is not a host vulnerability — but if page content can escape the untrustedContent marking or reach a privileged path, that is.

Known limitations (not vulnerabilities)

These are documented design boundaries, not defects:

  • Same-user access. Any process running as your OS user can reach that user's socket, browser profile, and artifacts. Run untrusted agents as separate OS users.
  • Shared session state. Sessions are windows (macOS) or tabs (Linux) over one browser profile, so cookies and storage are shared between sessions. Per-session isolation is tracked in the roadmap, not implied today.
  • macOS diagnostics are best-effort. WebKit does not expose Chromium's event stream; the macOS QA bridge runs in the page world and is therefore observable by the page. Hardening it is tracked as #28.
  • Recording scope. The recorder captures browser frames only — never OS chrome, other applications, or audio.
  • Network mocking is Linux-only. macOS returns UNSUPPORTED_CAPABILITY rather than partially emulating traffic control.
  • HTTP on macOS. The ATS exception is limited to WKWebView so browser pages can use HTTP when required. Native application networking retains the default ATS protections.

Supported versions

Headless is pre-1.x in practice: fixes land on main and ship in the next tagged release. There is no long-term support branch yet.

Hardening guidance for operators

  • Run agents as a dedicated OS user, not your own account.
  • Leave HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS unset unless you are actively debugging, and never in a shared session.
  • Keep the stdio MCP server local, or tunnel it over SSH. Do not bridge it to a network listener.
  • Treat every artifact, report, and console line as potentially sensitive page content.

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Security: LockInTime/headless

Security

SECURITY.md

Security policy

Headless exists to give an AI agent a browser it cannot misuse. The safety rules are enforced by the host process, not by prompting, so a vulnerability here is a vulnerability in the product's core promise. We take reports seriously.

Reporting a vulnerability

Do not open a public issue.

Use GitHub's private vulnerability reporting: Report a vulnerability. That opens a private advisory visible only to maintainers.

Please include:

  • affected version or commit, and platform (macOS engine or Linux Chromium engine)
  • what boundary you crossed, and the commands or page that crossed it
  • a minimal reproduction — a fixture page is ideal
  • what an attacker gains

We aim to acknowledge within 3 working days and to ship a fix or a documented mitigation before any public disclosure. Tell us if you intend to publish, and we will agree a timeline with you.

What counts as a vulnerability

These are host-enforced contracts. Anything that defeats one is in scope:

BoundaryExpected behaviour
No arbitrary code executionThere is no JavaScript-evaluation verb and no shell verb. Reaching arbitrary in-page or host execution through the protocol is a vulnerability.
NavigationHTTP/HTTPS only. file:, javascript:, data:, credential-bearing URLs, and external application schemes must be refused at every layer.
DownloadsPage-initiated downloads are denied. Executables, installers, scripts, libraries, and disk images are blocked by extension.
Control planeA 0600 Unix socket inside a 0700 per-user directory, with a peer-UID check. There is no TCP listener and no Chromium debug port. Any remote reachability is a vulnerability.
ArtifactsBare validated names, O_EXCL creation at 0600 inside a 0700 root, never overwritten. Path traversal or reading outside the store is a vulnerability.
SecretsCookie and storage values require both --values and HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS=1. Authorization, cookie, token, and secret headers, plus URL credentials, are always redacted. Flow recordings never contain typed values.
Untrusted contentEverything derived from a page is marked untrustedContent and is never executed as a command. A page that induces the host to act on its own text is a vulnerability.
SandboxThe Linux host refuses to run as root and never passes --no-sandbox. Snap Chromium is rejected before launch.

Prompt injection that merely persuades an agent to do something within these boundaries is not a host vulnerability — but if page content can escape the untrustedContent marking or reach a privileged path, that is.

Known limitations (not vulnerabilities)

These are documented design boundaries, not defects:

  • Same-user access. Any process running as your OS user can reach that user's socket, browser profile, and artifacts. Run untrusted agents as separate OS users.
  • Shared session state. Sessions are windows (macOS) or tabs (Linux) over one browser profile, so cookies and storage are shared between sessions. Per-session isolation is tracked in the roadmap, not implied today.
  • macOS diagnostics are best-effort. WebKit does not expose Chromium's event stream; the macOS QA bridge runs in the page world and is therefore observable by the page. Hardening it is tracked as #28.
  • Recording scope. The recorder captures browser frames only — never OS chrome, other applications, or audio.
  • Network mocking is Linux-only. macOS returns UNSUPPORTED_CAPABILITY rather than partially emulating traffic control.
  • HTTP on macOS. The ATS exception is limited to WKWebView so browser pages can use HTTP when required. Native application networking retains the default ATS protections.

Supported versions

Headless is pre-1.x in practice: fixes land on main and ship in the next tagged release. There is no long-term support branch yet.

Hardening guidance for operators

  • Run agents as a dedicated OS user, not your own account.
  • Leave HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS unset unless you are actively debugging, and never in a shared session.
  • Keep the stdio MCP server local, or tunnel it over SSH. Do not bridge it to a network listener.
  • Treat every artifact, report, and console line as potentially sensitive page content.

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Security: LockInTime/headless

Security

SECURITY.md

Security policy

Headless exists to give an AI agent a browser it cannot misuse. The safety rules are enforced by the host process, not by prompting, so a vulnerability here is a vulnerability in the product's core promise. We take reports seriously.

Reporting a vulnerability

Do not open a public issue.

Use GitHub's private vulnerability reporting: Report a vulnerability. That opens a private advisory visible only to maintainers.

Please include:

  • affected version or commit, and platform (macOS engine or Linux Chromium engine)
  • what boundary you crossed, and the commands or page that crossed it
  • a minimal reproduction — a fixture page is ideal
  • what an attacker gains

We aim to acknowledge within 3 working days and to ship a fix or a documented mitigation before any public disclosure. Tell us if you intend to publish, and we will agree a timeline with you.

What counts as a vulnerability

These are host-enforced contracts. Anything that defeats one is in scope:

BoundaryExpected behaviour
No arbitrary code executionThere is no JavaScript-evaluation verb and no shell verb. Reaching arbitrary in-page or host execution through the protocol is a vulnerability.
NavigationHTTP/HTTPS only. file:, javascript:, data:, credential-bearing URLs, and external application schemes must be refused at every layer.
DownloadsPage-initiated downloads are denied. Executables, installers, scripts, libraries, and disk images are blocked by extension.
Control planeA 0600 Unix socket inside a 0700 per-user directory, with a peer-UID check. There is no TCP listener and no Chromium debug port. Any remote reachability is a vulnerability.
ArtifactsBare validated names, O_EXCL creation at 0600 inside a 0700 root, never overwritten. Path traversal or reading outside the store is a vulnerability.
SecretsCookie and storage values require both --values and HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS=1. Authorization, cookie, token, and secret headers, plus URL credentials, are always redacted. Flow recordings never contain typed values.
Untrusted contentEverything derived from a page is marked untrustedContent and is never executed as a command. A page that induces the host to act on its own text is a vulnerability.
SandboxThe Linux host refuses to run as root and never passes --no-sandbox. Snap Chromium is rejected before launch.

Prompt injection that merely persuades an agent to do something within these boundaries is not a host vulnerability — but if page content can escape the untrustedContent marking or reach a privileged path, that is.

Known limitations (not vulnerabilities)

These are documented design boundaries, not defects:

  • Same-user access. Any process running as your OS user can reach that user's socket, browser profile, and artifacts. Run untrusted agents as separate OS users.
  • Shared session state. Sessions are windows (macOS) or tabs (Linux) over one browser profile, so cookies and storage are shared between sessions. Per-session isolation is tracked in the roadmap, not implied today.
  • macOS diagnostics are best-effort. WebKit does not expose Chromium's event stream; the macOS QA bridge runs in the page world and is therefore observable by the page. Hardening it is tracked as #28.
  • Recording scope. The recorder captures browser frames only — never OS chrome, other applications, or audio.
  • Network mocking is Linux-only. macOS returns UNSUPPORTED_CAPABILITY rather than partially emulating traffic control.
  • HTTP on macOS. The ATS exception is limited to WKWebView so browser pages can use HTTP when required. Native application networking retains the default ATS protections.

Supported versions

Headless is pre-1.x in practice: fixes land on main and ship in the next tagged release. There is no long-term support branch yet.

Hardening guidance for operators

  • Run agents as a dedicated OS user, not your own account.
  • Leave HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS unset unless you are actively debugging, and never in a shared session.
  • Keep the stdio MCP server local, or tunnel it over SSH. Do not bridge it to a network listener.
  • Treat every artifact, report, and console line as potentially sensitive page content.

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Security: LockInTime/headless

Security

SECURITY.md

Security policy

Headless exists to give an AI agent a browser it cannot misuse. The safety rules are enforced by the host process, not by prompting, so a vulnerability here is a vulnerability in the product's core promise. We take reports seriously.

Reporting a vulnerability

Do not open a public issue.

Use GitHub's private vulnerability reporting: Report a vulnerability. That opens a private advisory visible only to maintainers.

Please include:

  • affected version or commit, and platform (macOS engine or Linux Chromium engine)
  • what boundary you crossed, and the commands or page that crossed it
  • a minimal reproduction — a fixture page is ideal
  • what an attacker gains

We aim to acknowledge within 3 working days and to ship a fix or a documented mitigation before any public disclosure. Tell us if you intend to publish, and we will agree a timeline with you.

What counts as a vulnerability

These are host-enforced contracts. Anything that defeats one is in scope:

BoundaryExpected behaviour
No arbitrary code executionThere is no JavaScript-evaluation verb and no shell verb. Reaching arbitrary in-page or host execution through the protocol is a vulnerability.
NavigationHTTP/HTTPS only. file:, javascript:, data:, credential-bearing URLs, and external application schemes must be refused at every layer.
DownloadsPage-initiated downloads are denied. Executables, installers, scripts, libraries, and disk images are blocked by extension.
Control planeA 0600 Unix socket inside a 0700 per-user directory, with a peer-UID check. There is no TCP listener and no Chromium debug port. Any remote reachability is a vulnerability.
ArtifactsBare validated names, O_EXCL creation at 0600 inside a 0700 root, never overwritten. Path traversal or reading outside the store is a vulnerability.
SecretsCookie and storage values require both --values and HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS=1. Authorization, cookie, token, and secret headers, plus URL credentials, are always redacted. Flow recordings never contain typed values.
Untrusted contentEverything derived from a page is marked untrustedContent and is never executed as a command. A page that induces the host to act on its own text is a vulnerability.
SandboxThe Linux host refuses to run as root and never passes --no-sandbox. Snap Chromium is rejected before launch.

Prompt injection that merely persuades an agent to do something within these boundaries is not a host vulnerability — but if page content can escape the untrustedContent marking or reach a privileged path, that is.

Known limitations (not vulnerabilities)

These are documented design boundaries, not defects:

  • Same-user access. Any process running as your OS user can reach that user's socket, browser profile, and artifacts. Run untrusted agents as separate OS users.
  • Shared session state. Sessions are windows (macOS) or tabs (Linux) over one browser profile, so cookies and storage are shared between sessions. Per-session isolation is tracked in the roadmap, not implied today.
  • macOS diagnostics are best-effort. WebKit does not expose Chromium's event stream; the macOS QA bridge runs in the page world and is therefore observable by the page. Hardening it is tracked as #28.
  • Recording scope. The recorder captures browser frames only — never OS chrome, other applications, or audio.
  • Network mocking is Linux-only. macOS returns UNSUPPORTED_CAPABILITY rather than partially emulating traffic control.
  • HTTP on macOS. The ATS exception is limited to WKWebView so browser pages can use HTTP when required. Native application networking retains the default ATS protections.

Supported versions

Headless is pre-1.x in practice: fixes land on main and ship in the next tagged release. There is no long-term support branch yet.

Hardening guidance for operators

  • Run agents as a dedicated OS user, not your own account.
  • Leave HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS unset unless you are actively debugging, and never in a shared session.
  • Keep the stdio MCP server local, or tunnel it over SSH. Do not bridge it to a network listener.
  • Treat every artifact, report, and console line as potentially sensitive page content.

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Security: LockInTime/headless

Security

SECURITY.md

Security policy

Headless exists to give an AI agent a browser it cannot misuse. The safety rules are enforced by the host process, not by prompting, so a vulnerability here is a vulnerability in the product's core promise. We take reports seriously.

Reporting a vulnerability

Do not open a public issue.

Use GitHub's private vulnerability reporting: Report a vulnerability. That opens a private advisory visible only to maintainers.

Please include:

  • affected version or commit, and platform (macOS engine or Linux Chromium engine)
  • what boundary you crossed, and the commands or page that crossed it
  • a minimal reproduction — a fixture page is ideal
  • what an attacker gains

We aim to acknowledge within 3 working days and to ship a fix or a documented mitigation before any public disclosure. Tell us if you intend to publish, and we will agree a timeline with you.

What counts as a vulnerability

These are host-enforced contracts. Anything that defeats one is in scope:

BoundaryExpected behaviour
No arbitrary code executionThere is no JavaScript-evaluation verb and no shell verb. Reaching arbitrary in-page or host execution through the protocol is a vulnerability.
NavigationHTTP/HTTPS only. file:, javascript:, data:, credential-bearing URLs, and external application schemes must be refused at every layer.
DownloadsPage-initiated downloads are denied. Executables, installers, scripts, libraries, and disk images are blocked by extension.
Control planeA 0600 Unix socket inside a 0700 per-user directory, with a peer-UID check. There is no TCP listener and no Chromium debug port. Any remote reachability is a vulnerability.
ArtifactsBare validated names, O_EXCL creation at 0600 inside a 0700 root, never overwritten. Path traversal or reading outside the store is a vulnerability.
SecretsCookie and storage values require both --values and HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS=1. Authorization, cookie, token, and secret headers, plus URL credentials, are always redacted. Flow recordings never contain typed values.
Untrusted contentEverything derived from a page is marked untrustedContent and is never executed as a command. A page that induces the host to act on its own text is a vulnerability.
SandboxThe Linux host refuses to run as root and never passes --no-sandbox. Snap Chromium is rejected before launch.

Prompt injection that merely persuades an agent to do something within these boundaries is not a host vulnerability — but if page content can escape the untrustedContent marking or reach a privileged path, that is.

Known limitations (not vulnerabilities)

These are documented design boundaries, not defects:

  • Same-user access. Any process running as your OS user can reach that user's socket, browser profile, and artifacts. Run untrusted agents as separate OS users.
  • Shared session state. Sessions are windows (macOS) or tabs (Linux) over one browser profile, so cookies and storage are shared between sessions. Per-session isolation is tracked in the roadmap, not implied today.
  • macOS diagnostics are best-effort. WebKit does not expose Chromium's event stream; the macOS QA bridge runs in the page world and is therefore observable by the page. Hardening it is tracked as #28.
  • Recording scope. The recorder captures browser frames only — never OS chrome, other applications, or audio.
  • Network mocking is Linux-only. macOS returns UNSUPPORTED_CAPABILITY rather than partially emulating traffic control.
  • HTTP on macOS. The ATS exception is limited to WKWebView so browser pages can use HTTP when required. Native application networking retains the default ATS protections.

Supported versions

Headless is pre-1.x in practice: fixes land on main and ship in the next tagged release. There is no long-term support branch yet.

Hardening guidance for operators

  • Run agents as a dedicated OS user, not your own account.
  • Leave HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS unset unless you are actively debugging, and never in a shared session.
  • Keep the stdio MCP server local, or tunnel it over SSH. Do not bridge it to a network listener.
  • Treat every artifact, report, and console line as potentially sensitive page content.

There aren't any published security advisories

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Security: LockInTime/headless

Security

SECURITY.md

Security policy

Headless exists to give an AI agent a browser it cannot misuse. The safety rules are enforced by the host process, not by prompting, so a vulnerability here is a vulnerability in the product's core promise. We take reports seriously.

Reporting a vulnerability

Do not open a public issue.

Use GitHub's private vulnerability reporting: Report a vulnerability. That opens a private advisory visible only to maintainers.

Please include:

  • affected version or commit, and platform (macOS engine or Linux Chromium engine)
  • what boundary you crossed, and the commands or page that crossed it
  • a minimal reproduction — a fixture page is ideal
  • what an attacker gains

We aim to acknowledge within 3 working days and to ship a fix or a documented mitigation before any public disclosure. Tell us if you intend to publish, and we will agree a timeline with you.

What counts as a vulnerability

These are host-enforced contracts. Anything that defeats one is in scope:

BoundaryExpected behaviour
No arbitrary code executionThere is no JavaScript-evaluation verb and no shell verb. Reaching arbitrary in-page or host execution through the protocol is a vulnerability.
NavigationHTTP/HTTPS only. file:, javascript:, data:, credential-bearing URLs, and external application schemes must be refused at every layer.
DownloadsPage-initiated downloads are denied. Executables, installers, scripts, libraries, and disk images are blocked by extension.
Control planeA 0600 Unix socket inside a 0700 per-user directory, with a peer-UID check. There is no TCP listener and no Chromium debug port. Any remote reachability is a vulnerability.
ArtifactsBare validated names, O_EXCL creation at 0600 inside a 0700 root, never overwritten. Path traversal or reading outside the store is a vulnerability.
SecretsCookie and storage values require both --values and HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS=1. Authorization, cookie, token, and secret headers, plus URL credentials, are always redacted. Flow recordings never contain typed values.
Untrusted contentEverything derived from a page is marked untrustedContent and is never executed as a command. A page that induces the host to act on its own text is a vulnerability.
SandboxThe Linux host refuses to run as root and never passes --no-sandbox. Snap Chromium is rejected before launch.

Prompt injection that merely persuades an agent to do something within these boundaries is not a host vulnerability — but if page content can escape the untrustedContent marking or reach a privileged path, that is.

Known limitations (not vulnerabilities)

These are documented design boundaries, not defects:

  • Same-user access. Any process running as your OS user can reach that user's socket, browser profile, and artifacts. Run untrusted agents as separate OS users.
  • Shared session state. Sessions are windows (macOS) or tabs (Linux) over one browser profile, so cookies and storage are shared between sessions. Per-session isolation is tracked in the roadmap, not implied today.
  • macOS diagnostics are best-effort. WebKit does not expose Chromium's event stream; the macOS QA bridge runs in the page world and is therefore observable by the page. Hardening it is tracked as #28.
  • Recording scope. The recorder captures browser frames only — never OS chrome, other applications, or audio.
  • Network mocking is Linux-only. macOS returns UNSUPPORTED_CAPABILITY rather than partially emulating traffic control.
  • HTTP on macOS. The ATS exception is limited to WKWebView so browser pages can use HTTP when required. Native application networking retains the default ATS protections.

Supported versions

Headless is pre-1.x in practice: fixes land on main and ship in the next tagged release. There is no long-term support branch yet.

Hardening guidance for operators

  • Run agents as a dedicated OS user, not your own account.
  • Leave HEADLESS_ALLOW_SENSITIVE_DIAGNOSTICS unset unless you are actively debugging, and never in a shared session.
  • Keep the stdio MCP server local, or tunnel it over SSH. Do not bridge it to a network listener.
  • Treat every artifact, report, and console line as potentially sensitive page content.

There aren't any published security advisories