@ai-ecoverse/slicc 1.39.2 → 1.39.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +17 -2
  2. package/package.json +8 -8
package/README.md CHANGED
@@ -760,7 +760,12 @@ Only browsers the user named are listed: the one seven runs in, `--cdp` and `--c
760
760
  - **Refused**, with `{"id":…,"sessionId"?:…,"error":{"code":-32000,"message":"slicc: refused: target is on seven's origin"}}`, never forwarded: `Target.createTarget`, `Page.navigate` and anything else whose `url` is protected; `Page.navigateToHistoryEntry` to an entry whose URL is protected (the node looks it up with `Page.getNavigationHistory`); `Target.attachToTarget`, `activateTarget`, `closeTarget`, `autoAttachRelated`, `Browser.getWindowForTarget` and any other command whose `targetId` or `frameId` is a protected target; and every command on a session whose target is protected, or became so. `Target.getTargetInfo` and `Target.detachFromTarget` stay allowed.
761
761
  - **Origins and storage.** A command whose `origin`, `securityOrigin`, `ownerOrigin`, `issuerOrigin`, `topLevelOrigin`, `topLevelSite`, `embeddedOrigin`, `requestingOrigin`, `scopeURL` or `manifestId` is protected, or whose `storageKey` or `cacheId` names seven's storage, is refused the same way. This covers `Storage.*`, `IndexedDB.*`, `CacheStorage.*`, `DOMStorage.*`, `FileSystem.*`, `ServiceWorker.*`, `PWA.*`, `Browser.setPermission` and `Browser.grantPermissions`. Free-form values (`expression`, `arguments`, `value`, `headers`, `postData` and the like) aren't searched.
762
762
  - **Cookies.** `Network.getCookies`, `Network.getAllCookies`, `Storage.getCookies` and `Page.getCookies` answer without the cookies whose domain is protected (`sliccy.ai` and every subdomain, and each extra origin's host and its parents: cookies ignore ports), and without partitioned cookies whose `partitionKey.topLevelSite` is such a site. `Network.setCookie`, `setCookies`, `deleteCookies`, `Storage.setCookies` and `Page.deleteCookie` for such a domain, a URL on such a host, or a partition key under such a site, are refused with `slicc: refused: cookies on seven's origin`. So are `Network.clearBrowserCookies` and `Storage.clearCookies`, except in a browser context this stream created with `Target.createBrowserContext`.
763
- - **Requests a page makes to seven.** For a request whose URL is protected, `Network.*` and `Fetch.*` events lose their `Cookie` and `Set-Cookie` headers, their raw header texts and their cookie lists, and `requestWillBeSentExtraInfo` drops seven's cookies from `associatedCookies` for any request. Chrome can send `requestWillBeSentExtraInfo` and `responseReceivedExtraInfo` before the event that names the request's URL, so the node holds them until the request is found to be protected, gets its response, finishes or fails (a WebSocket or WebTransport once it is created); one still held after 2 seconds is passed on stripped, as for a protected request. For a WebSocket, WebTransport or EventSource on a protected origin (`ws:` and `wss:` count as `http:` and `https:`), `webSocketWillSendHandshakeRequest`, `webSocketHandshakeResponseReceived`, `webSocketFrameError`, `eventSourceMessageReceived` and `dataReceived` are dropped. Reading such a request's body (`Network.getResponseBody`, `Fetch.getResponseBody`, `takeResponseBody…AsStream`, `Audits.getEncodedResponse` and the like) is refused. The node also checks the answer, because the page may ask before the node has seen the request. When `Network.getResponseBody`, `searchInResponseBody`, `streamResourceContent`, `getResponseBodyForInterception`, `takeResponseBodyForInterceptionAsStream`, `getRequestPostData`, `Fetch.getResponseBody`, `Fetch.takeResponseBodyAsStream` or `Audits.getEncodedResponse` answers, the node holds the answer until the request has a response (for `getRequestPostData`, until it is sent; for an intercepted request, until it is paused). If the request is protected by then, the answer is refused, and a stream it handed out is closed. If the node still hasn't seen the request after 2 seconds, the answer is refused with `slicc: refused: slicc hasn't seen this request, so it could be seven's`. `Network.replayXHR` is refused with that message too, unless the node has already seen the request; for a protected request it is refused like the body getters. `IO.read` is refused, with `slicc: refused: slicc didn't hand out this stream, so it could be seven's`, unless the node passed that handle to the page in an allowed answer (`take…AsStream`, `Page.printToPDF`, `Network.loadNetworkResource`, or `IO.resolveBlob` as `blob:<uuid>`). Continuing, failing or fulfilling it is allowed, except for a document request, which the node fails itself (see the next items).
763
+ - **Requests a page makes to seven.** For a request whose URL is protected, `Network.*` and `Fetch.*` events lose their `Cookie` and `Set-Cookie` headers, their raw header texts and their cookie lists, and `requestWillBeSentExtraInfo` drops seven's cookies from `associatedCookies` for any request. Chrome can send `requestWillBeSentExtraInfo` and `responseReceivedExtraInfo` before the event that names the request's URL, so the node holds them until the request is found to be protected, gets its response, finishes or fails (a WebSocket or WebTransport once it is created); one still held after 2 seconds is passed on stripped, as for a protected request. For a WebSocket, WebTransport or EventSource on a protected origin (`ws:` and `wss:` count as `http:` and `https:`), `webSocketWillSendHandshakeRequest`, `webSocketHandshakeResponseReceived`, `webSocketFrameError`, `eventSourceMessageReceived` and `dataReceived` are dropped. Reading such a request's body (`Network.getResponseBody`, `Fetch.getResponseBody`, `takeResponseBody…AsStream`, `Audits.getEncodedResponse` and the like) is refused. The node also checks the answer, because the page may ask before the node has seen the request. When `Network.getResponseBody`, `searchInResponseBody`, `streamResourceContent`, `getResponseBodyForInterception`, `takeResponseBodyForInterceptionAsStream`, `getRequestPostData`, `Fetch.getResponseBody`, `Fetch.takeResponseBodyAsStream` or `Audits.getEncodedResponse` answers, the node holds the answer until the request has a response (for `getRequestPostData`, until it is sent; for an intercepted request, until it is paused). If the request is protected by then, the answer is refused, and a stream it handed out is closed. If the node still hasn't seen the request after 2 seconds, the answer is refused with `slicc: refused: slicc hasn't seen this request, so it could be seven's`. `Network.replayXHR` is refused with that message too, unless the node has already seen the request; for a protected request it is refused like the body getters. `IO.read` is refused, with `slicc: refused: slicc didn't hand out this stream, so it could be seven's`, unless the node passed that handle to the page in an allowed answer (`take…AsStream`, `Page.printToPDF`, `Network.loadNetworkResource`, or `IO.resolveBlob` as `blob:<uuid>`). - **Paused requests to seven.** A page session's own interception never gets to touch a request whose URL is protected, whatever its kind (a document, `fetch()`, XHR, an image or any other subresource), at either stage. The node keeps `Fetch.requestPaused`, `Fetch.authRequired` and the deprecated `Network.requestIntercepted` for such a request from the page and settles it itself:
764
+ - a document request is failed (`Fetch.failRequest` with `BlockedByClient`, or `Network.continueInterceptedRequest` with `errorReason: BlockedByClient`);
765
+ - any other request continues untouched (`Fetch.continueRequest`, or `Network.continueInterceptedRequest` with only its `interceptionId`);
766
+ - an auth challenge gets the browser's own handling (`Fetch.continueWithAuth`, or `Network.continueInterceptedRequest`, with `authChallengeResponse: {"response": "Default"}`).
767
+
768
+ `Fetch.continueRequest`, `continueResponse`, `failRequest`, `fulfillRequest`, `continueWithAuth` and `Network.continueInterceptedRequest` are refused with `slicc: refused: slicc didn't pass this paused request to the page, so it could be seven's` for any `requestId` or `interceptionId` the node hasn't passed to that session in a paused event. So a guessed id can't fulfil, change or fail a protected request, even one that is still paused. The node remembers the last 16 384 ids it passed on; an id older than that is refused too.
764
769
  - **Browser-wide commands**, refused with their own reason after `slicc: refused: `: `Target.exposeDevToolsProtocol` (it would give a page the whole browser) and `Target.sendMessageToTarget` (attach with `flatten: true` instead), on any target; `Fetch.enable` on the browser itself (a page session is fine); `Tracing.start`; `Extensions.loadUnpacked`; and `Browser.setPermission`, `Browser.grantPermissions` without an `origin` and `Browser.resetPermissions`, except in a browser context this stream created.
765
770
  - **Auto-attach.** With `Target.setAutoAttach`, a session to a protected target is detached by the node at once (`Target.detachFromTarget` on its parent session), and the page never sees its `attachedToTarget` or `detachedFromTarget`.
766
771
  - **Navigation by other means.** A script's `location = …`, a link, `window.open` or a server redirect isn't a command the node can refuse, so the node guards the network instead.
@@ -771,7 +776,7 @@ Only browsers the user named are listed: the one seven runs in, `--cdp` and `--c
771
776
  - Page commands on a touched target's session wait until the node's own session there is ready. That takes at most 10 s; after that, or when the node's session can't be set up or is lost, they are refused with `slicc: refused: slicc can't keep seven's origin out of this target`.
772
777
  - In touched targets, service workers are bypassed for every request, not only for protected ones.
773
778
  - The guard covers every frame that shares the touched target's process. A cross-site iframe's navigation pauses in its parent's target, before the iframe becomes a target of its own, with the frame's id as `frameId` (the id the iframe target gets later). A popup's request pauses in the popup's target, with its `targetId` as `frameId`. A redirect into a protected origin pauses again at the request stage, with `redirectedRequestId`, even when the first URL didn't match.
774
- - The page's own `Fetch.enable` on a page session still works. Chrome chains the interceptors of a target's sessions, the most recently enabled first, so the page's interceptor could see a protected document's request before the node's does, or after the node failed it, at the response stage. The node fails such a `Fetch.requestPaused` (`resourceType: Document`, protected URL, either stage) itself, and the page never sees it.
779
+ - The page's own `Fetch.enable` on a page session still works. Chrome chains the interceptors of a target's sessions, the most recently enabled first, so the page's interceptor could see a protected document's request before the node's does, or after the node failed it, at the response stage. The node fails such a request itself, and the page never sees it (see *Paused requests to seven* above).
775
780
  - When a target commits a protected origin all the same (see the limits below), the node sees it arrive (`Target.targetInfoChanged`) only after the browser committed it. A request the node failed also leaves the target on the protected URL, showing the error page. Either way the node detaches every page session on the target, drops their events and results, and refuses further commands on them; the page gets `Target.detachedFromTarget`.
776
781
  - **Auto-attach of targets without a URL.** A cross-site iframe can attach before its URL is known (`url: ""`, which stays empty while it waits for the debugger), and so can a `window.open` popup. So when an auto-attached session (one that doesn't answer the page's own `Target.attachToTarget`) is to a page or iframe target with an empty URL, the node holds it:
777
782
  - The page doesn't get its `attachedToTarget` yet, its events are dropped, and page commands on it are refused.
@@ -1190,6 +1195,16 @@ In the same process, probe ports, dirs and a process list passed in explicitly (
1190
1195
 
1191
1196
  **Port guard.** On CI (`CI` set), or with `SLICC_TEST_PORT_GUARD=1`, `TestMain` holds `127.0.0.1:9222` to `9229` (and `[::1]` where it can) for the whole run, and the run fails if anything connects to them, other than the one test that lends a port to its own fake browser. On CI a port it can't hold fails the run. Off CI it is off by default, so a developer's own Chrome on those ports is never touched; the guarded tests then skip.
1192
1197
 
1198
+ **Protected-origin vectors.** `test/integration/testdata/link/protect.js` exports `protectVectors`, the attacks the relay must stop, in a shape other guards reuse: `{ id, setup, trigger, control: { origin: 'ordinary', expected }, expected }`. Each runs three times, through the relay, against the same server under three names: an ordinary origin (`ordinary.test`, the control, which must succeed), seven (an `--origin`) and the vault (`vault.sliccy.ai`). A run passes when its observations match `control.expected` or `expected`, and a vector whose control fails fails as a whole. The only run left out is the vault in the same-site iframe cases, since no unprotected page is same-site with a `sliccy.ai` host. The observations come from the test server's log of requests and of the beacons an injected init script sends, and from what the page's own CDP session saw. The cases:
1199
+ - C1, an init script, then `location.href`;
1200
+ - C2, redirect chains through allowed hops (301, 302, 303, 307, 308, and a POST form through 307 and 308), and a chain that passes through the protected origin and back out;
1201
+ - C3, an instrumented popup that navigates itself, and a popup opened on a redirect chain;
1202
+ - C4, static and script-inserted iframes, same-site and cross-site to the page;
1203
+ - C5, the page's own `Fetch.enable` on every request at both stages: a document, `fetch()`, XHR, an image, an auth challenge, and fulfilling guessed request ids;
1204
+ - C6, cookie reads, writes and clears, and storage commands that name the origin or its storage key.
1205
+
1206
+ Chrome 156 no longer has `Network.setRequestInterception`, so the deprecated `Network.requestIntercepted` path is tested against a fake browser instead.
1207
+
1193
1208
  **Real browsers in tests.** The Chrome the harness starts itself is `SLICC_TEST_CHROME` (test-only: the path of a Chrome executable), else the machine's Chrome or Chromium, with the real environment, a temporary profile and `--use-mock-keychain --password-store=basic`. The tests that have `slicc` itself launch a real Chrome run it under a temporary home, where its profiles are throwaway ones. Off CI they never launch the machine's own Chrome: they need `SLICC_TEST_CHROME` set to a Chrome for Testing inside its `.app`, which they link into the temporary home's `Applications` folder on macOS and launch by its id (`chrome-for-testing`), and they skip with a notice without it, or on other systems. On CI they launch the runner's Google Chrome. An older Chrome for Testing can fail the tests that read Chrome's own prefs.
1194
1209
 
1195
1210
  On GitHub's Windows runners the system drive `C:` is slow: with Chrome profiles there, Chrome sometimes waited seconds before a new tab's first request (up to past the 15 s page-load limit) or before exiting (`did not exit`). With them on `D:`, the runner's temp drive, those stalls weren't seen and the suite ran about a quarter faster. So CI points `TEMP` and `TMP` at the runner's temp dir, and the tests' temporary homes and Chrome profiles live there. When a test page doesn't load, the failure says where it stopped: the tab's URL and `readyState`, the resources it fetched, and every request the page server saw.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc",
3
- "version": "1.39.2",
3
+ "version": "1.39.3",
4
4
  "description": "SLICC's command line for seven: links a machine's network, compute and browsers to seven over WebRTC",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -18,12 +18,12 @@
18
18
  "node": ">=18"
19
19
  },
20
20
  "optionalDependencies": {
21
- "@ai-ecoverse/slicc-darwin-arm64": "1.39.2",
22
- "@ai-ecoverse/slicc-darwin-amd64": "1.39.2",
23
- "@ai-ecoverse/slicc-linux-arm64": "1.39.2",
24
- "@ai-ecoverse/slicc-linux-amd64": "1.39.2",
25
- "@ai-ecoverse/slicc-windows-arm64": "1.39.2",
26
- "@ai-ecoverse/slicc-windows-amd64": "1.39.2",
27
- "@ai-ecoverse/slicc-jerk": "^0.15.2"
21
+ "@ai-ecoverse/slicc-darwin-arm64": "1.39.3",
22
+ "@ai-ecoverse/slicc-darwin-amd64": "1.39.3",
23
+ "@ai-ecoverse/slicc-linux-arm64": "1.39.3",
24
+ "@ai-ecoverse/slicc-linux-amd64": "1.39.3",
25
+ "@ai-ecoverse/slicc-windows-arm64": "1.39.3",
26
+ "@ai-ecoverse/slicc-windows-amd64": "1.39.3",
27
+ "@ai-ecoverse/slicc-jerk": "^0.16.0"
28
28
  }
29
29
  }