Summary
At commit 2dbee34e4065cbbd6e60412862b69625bc9b252e, ScriptCat has several current-branch data paths that can produce a serialized message larger than Chrome's 64 MiB extension-message limit.
The directly affected path is Chrome extension messaging through chrome.runtime.sendMessage and response delivery. The observed failure is:
Message exceeded maximum allowed size of 64MiB.
This branch does not use Chrome native-messaging APIs. ScriptCat's External Access feature uses a separate offscreen WebSocket. The native-messaging limit and the generic extension-message limit must therefore be kept distinct.
Primary failure path
The Script Editor resource path can construct an oversized response as follows:
- A
Resource retains both textual content and base64 fields.
- The service-worker resource service computes Base64 for every resource and also fills
content for text resources.
- The Resource pane requests all resources in one call.
- The message client and server add request/response envelopes.
- Chrome serializes or encodes the complete response before delivery.
For a large text resource, the response can contain the source text and another Base64 representation of the same bytes, in addition to JSON escaping, metadata, and protocol envelopes. Base64 expands binary data by approximately one third. A resource can be valid in storage while its complete response is too large to cross the message boundary.
When delivery fails, the receiving side may only see an absent/failed response while the service worker logs sendResponse error. That log is a transport symptom; it does not establish that a native host was involved.
Current-branch risk matrix
| Path |
Payload |
Assessment |
| Script Editor resource retrieval |
All resources for a script, including code-like text, metadata, content, and Base64 |
Highest-confidence direct path. Text resources may duplicate the same bytes; all resources are returned in one response. |
| Runtime page-load aggregation |
Enabled scripts, values, metadata, and resources |
Aggregate size is not bounded at the page-load composition point. It can exceed a runtime message boundary when many or large scripts are enabled. |
| Full script execution |
Script code, values, and resources sent toward offscreen and sandbox execution |
Uses structured-clone postMessage paths rather than the proven Chrome runtime-message cap, but remains a large structured-clone payload and requires independent transport limits. |
| GM value service and broadcasts |
Arbitrary JSON-serializable values and encoded update entries |
Values are not bounded by the message layer. Large values can exceed the generic extension-message limit when sent through runtime messaging or included in aggregates. |
| Backup and synchronization |
Script code, values, and Base64 resource data |
Full backup/resource forms can be large; page-to-service-worker requests and responses must be treated as transport boundaries. Local file/blob creation alone is not the same boundary. |
| Agent APIs |
Skill data, task/chat content, attachments, MCP results, and tool output |
These payloads can contain arbitrary strings and objects and can reach extension messaging without a shared serialized-byte budget. |
| Message queue |
Broadcast messages and arbitrary queue payloads |
Queue broadcasts ultimately use extension messaging in relevant contexts and have no common payload-size guard. |
| External Access WebSocket |
Script summaries, source reads, grep matches, and responses |
Not subject to Chrome's extension-message limit. However, source grep has no total result-byte cap, and the generated frame limit is not consistently enforced. A long matching line or repeated context can create an oversized WebSocket response. |
Transport boundaries that are not interchangeable
src/manifest.json opts the Chrome-target build into "message_serialization": "structured_clone"; Firefox removes this manifest key during its build. Chrome's structured-clone implementation still has a 64 MiB extension-message ceiling.
chrome.runtime.sendMessage, runtime ports, and related extension-message APIs are the path covered by the 64 MiB claim.
- Service-worker/offscreen
postMessage, sandbox WindowMessage, and content/inject CustomEvent are separate structured-clone or DOM channels. This audit does not claim that they share the same documented 64 MiB limit, only that they can carry large payloads and need their own bounded-transfer tests.
- ScriptCat has no
nativeMessaging permission, connectNative, or sendNativeMessage implementation on this commit.
- External Access uses an offscreen WebSocket to the local
sctl service. Its source-read cap and WebSocket framing are separate from Chrome runtime messaging.
- Local OPFS/IndexedDB/storage operations and trace logging are not themselves proof of a Chrome runtime-message failure. Trace logging can include large objects, but the default service-worker/offscreen logger level is not the primary trigger identified here.
Protocol clarification
Chrome's generic extension messaging documentation states a maximum message size of 64 MiB. Current Chromium checks the encoded/serialized message size before sending; JSON fallback measures the serialized UTF-8 byte string, while structured clone measures the encoded message bytes. The size is therefore not the JavaScript UTF-16 string length. Unicode, JSON escaping, duplicated fields, Base64 expansion, and envelopes all affect the final size.
The current Chromium comparison rejects values strictly larger than 64 * 1024 * 1024 bytes. Code should still leave headroom for envelopes and browser/version differences rather than targeting the boundary.
Native messaging is a separate protocol. If it is discussed for comparison only: messages are JSON encoded as UTF-8 and prefixed with a four-byte native-endian length; extension-to-host messages are documented up to 64 MiB, while host-to-Chrome messages are limited to 1 MiB. Native messaging is not the transport used by the current ScriptCat branch.
Recommended direction
- Avoid transmitting duplicate resource representations. Keep cached forms internally only when necessary, and choose one bounded wire representation.
- Retrieve resources lazily or through bounded pages/chunks instead of returning every resource in one response.
- Prefer resource identifiers or handles over embedding large bodies in page-load and metadata aggregates.
- Add transport-specific serialized-byte budgets before runtime responses, runtime broadcasts, structured-clone transfers, and WebSocket sends.
- Bound aggregate page-load data, GM values, backups, agent/tool payloads, queue messages, and total WebSocket grep responses.
- Enforce the configured External Access frame limit and make the total grep-result limit effective.
- Convert oversized transfers into explicit diagnostics that identify the operation and transport without logging sensitive payload contents.
Acceptance criteria for a future fix
- Tests measure the actual transport representation, including Unicode, JSON escaping, envelopes, and Base64.
- Exact-limit and over-limit cases are covered.
- Large text resources do not transmit both full text and Base64 unnecessarily.
- Large resource collections load progressively without requiring a single response near 64 MiB.
- Page-load, value, backup, agent, queue, and WebSocket paths have explicit byte bounds or handle/chunk-based transfer.
- Oversized responses fail deterministically with an operation-specific diagnostic.
- Separate
chrome.runtime, service-worker/offscreen postMessage, sandbox WindowMessage, content/inject CustomEvent, and WebSocket cases are tested independently.
- Browser/version behavior is reported separately from the current-branch source findings.
Evidence from this commit
Authoritative browser references
Scope limitation
This advisory is bound to ScriptCat commit 2dbee34e4065cbbd6e60412862b69625bc9b252e. It is a static source audit plus authoritative protocol analysis; it does not claim a live browser reproduction for every path. Browser-version and transport-specific behavior should be confirmed independently when implementing the remediation.
Summary
At commit
2dbee34e4065cbbd6e60412862b69625bc9b252e, ScriptCat has several current-branch data paths that can produce a serialized message larger than Chrome's 64 MiB extension-message limit.The directly affected path is Chrome extension messaging through
chrome.runtime.sendMessageand response delivery. The observed failure is:This branch does not use Chrome native-messaging APIs. ScriptCat's External Access feature uses a separate offscreen WebSocket. The native-messaging limit and the generic extension-message limit must therefore be kept distinct.
Primary failure path
The Script Editor resource path can construct an oversized response as follows:
Resourceretains both textualcontentandbase64fields.contentfor text resources.For a large text resource, the response can contain the source text and another Base64 representation of the same bytes, in addition to JSON escaping, metadata, and protocol envelopes. Base64 expands binary data by approximately one third. A resource can be valid in storage while its complete response is too large to cross the message boundary.
When delivery fails, the receiving side may only see an absent/failed response while the service worker logs
sendResponse error. That log is a transport symptom; it does not establish that a native host was involved.Current-branch risk matrix
postMessagepaths rather than the proven Chrome runtime-message cap, but remains a large structured-clone payload and requires independent transport limits.Transport boundaries that are not interchangeable
src/manifest.jsonopts the Chrome-target build into"message_serialization": "structured_clone"; Firefox removes this manifest key during its build. Chrome's structured-clone implementation still has a 64 MiB extension-message ceiling.chrome.runtime.sendMessage, runtime ports, and related extension-message APIs are the path covered by the 64 MiB claim.postMessage, sandboxWindowMessage, and content/injectCustomEventare separate structured-clone or DOM channels. This audit does not claim that they share the same documented 64 MiB limit, only that they can carry large payloads and need their own bounded-transfer tests.nativeMessagingpermission,connectNative, orsendNativeMessageimplementation on this commit.sctlservice. Its source-read cap and WebSocket framing are separate from Chrome runtime messaging.Protocol clarification
Chrome's generic extension messaging documentation states a maximum message size of 64 MiB. Current Chromium checks the encoded/serialized message size before sending; JSON fallback measures the serialized UTF-8 byte string, while structured clone measures the encoded message bytes. The size is therefore not the JavaScript UTF-16 string length. Unicode, JSON escaping, duplicated fields, Base64 expansion, and envelopes all affect the final size.
The current Chromium comparison rejects values strictly larger than
64 * 1024 * 1024bytes. Code should still leave headroom for envelopes and browser/version differences rather than targeting the boundary.Native messaging is a separate protocol. If it is discussed for comparison only: messages are JSON encoded as UTF-8 and prefixed with a four-byte native-endian length; extension-to-host messages are documented up to 64 MiB, while host-to-Chrome messages are limited to 1 MiB. Native messaging is not the transport used by the current ScriptCat branch.
Recommended direction
Acceptance criteria for a future fix
chrome.runtime, service-worker/offscreenpostMessage, sandboxWindowMessage, content/injectCustomEvent, and WebSocket cases are tested independently.Evidence from this commit
sendResponseerror pathAuthoritative browser references
Scope limitation
This advisory is bound to ScriptCat commit
2dbee34e4065cbbd6e60412862b69625bc9b252e. It is a static source audit plus authoritative protocol analysis; it does not claim a live browser reproduction for every path. Browser-version and transport-specific behavior should be confirmed independently when implementing the remediation.