@ai-ecoverse/slicc 1.30.0 → 1.31.0

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 +25 -3
  2. package/package.json +7 -7
package/README.md CHANGED
@@ -466,7 +466,7 @@ HELLO from `attach`: `{ "v": 1, "role": "node", "name", "host", "version", "mode
466
466
 
467
467
  ### `cdp` (browser control)
468
468
 
469
- > **Warning:** a seven with the `cdp` capability has full control of every listed browser: its tabs, cookies, stored passwords and logged-in sessions, files it can download, and anything a page in it can reach. That includes the browser seven runs in (`seven: true`), whether slicc launched it or not: with `slicc` or `slicc attach` on your everyday browser, seven can drive all of that browser, without a further prompt. List only browsers you would let that seven use as you. For `follow` that is a seven on another machine.
469
+ > **Warning:** a seven with the `cdp` capability has full control of every listed browser: its tabs, cookies, stored passwords and logged-in sessions, files it can download, and anything a page in it can reach. That includes the browser seven runs in (`seven: true`), whether slicc launched it or not: with `slicc` or `slicc attach` on your everyday browser, seven can drive all of that browser, without a further prompt. List only browsers you would let that seven use as you. For `follow` that is a seven on another machine. The one exception is seven's own origin, which the node keeps out of reach (see below).
470
470
 
471
471
  Only browsers the user named are listed: the one seven runs in, `--cdp` and `--cdp-extra` for `attach`, the extras picked with `--browser` or in the picker for `slicc`, and `--cdp` for `follow`. A browser discovery found but nobody picked is not.
472
472
 
@@ -480,7 +480,7 @@ Only browsers the user named are listed: the one seven runs in, `--cdp` and `--c
480
480
  - **OPENED:** `{ "product", "protocolVersion" }`, the `Browser` and `Protocol-Version` fields of `/json/version` (from `Browser.getVersion` for a `wsOnly` browser).
481
481
  - **RESET:** `ENOENT` for an id that isn't listed, `ECONNREFUSED` when the browser doesn't answer, `EPROTO` for an OPEN without `browser`.
482
482
 
483
- **Bytes**, both directions: a sequence of messages, each a `u32` BE length plus one UTF-8 CDP JSON message of at most 64 MiB (67 108 864 bytes). The node sends each page message as one WebSocket text message, and each text message from the browser as one stream message. A length over 64 MiB from the page, or a browser message over 64 MiB, is `RESET EMSGSIZE`, and a page END in the middle of a message is `RESET EPROTO`. Browser messages that start with `{"method":"Network.webSocketFrameReceived"` or `{"method":"Network.webSocketFrameSent"` are dropped: seven runs inside a browser it may debug, so those events would carry the CDP traffic itself and grow without bound (parity with slicc-node's `/cdp`).
483
+ **Bytes**, both directions: a sequence of messages, each a `u32` BE length plus one UTF-8 CDP JSON message of at most 64 MiB (67 108 864 bytes). The node sends each page message as one WebSocket text message, and each text message from the browser as one stream message, after the filter below. A length over 64 MiB from the page, or a browser message over 64 MiB, is `RESET EMSGSIZE`, and a page END in the middle of a message is `RESET EPROTO`. Browser messages that start with `{"method":"Network.webSocketFrameReceived"` or `{"method":"Network.webSocketFrameSent"` are dropped: seven runs inside a browser it may debug, so those events would carry the CDP traffic itself and grow without bound (parity with slicc-node's `/cdp`).
484
484
 
485
485
  **Closing.**
486
486
  - The browser closes the socket with a normal close (1000): the node sends END, then discards whatever the page still sends until its END.
@@ -488,11 +488,23 @@ Only browsers the user named are listed: the one seven runs in, `--cdp` and `--c
488
488
  - END from the page: the node closes the socket with a normal close, then sends END.
489
489
  - RESET from the page, or the link going down: the socket is closed at once.
490
490
 
491
+ **Seven's origin is off limits.** The node relays CDP through a filter, so seven's browser control never navigates to, opens or attaches to a target on seven's own origin, and never reads or writes its cookies or storage. That holds for every listed browser, not only the one seven runs in. What is protected comes from [slicc-browsers](https://github.com/ai-ecoverse/slicc-browsers#protected-origins)' `protectedOrigins`: every `sliccy.ai` host (the apex and `www` included, any port, `https` and `http`), `vault.sliccy.ai` by name (the vault is never a CDP target for seven's tools), `blob:`, `filesystem:` and `view-source:` URLs by the URL inside them, `devtools:` URLs, and the extra origins: `--origin` for `attach`, and `--origin` and the `--page` origin for `slicc`. `follow` has none. `*.kernel.localhost` is not protected. URLs are parsed the way the browser parses them (WHATWG), and the node forwards its own re-encoding of each command, so the browser runs exactly what was checked: a key given twice counts once, as its last value, and a message that isn't a JSON object with an integer `id` and a string `method` is refused (or dropped, without an `id`).
492
+ - **Targets.** Before the stream opens, the node attaches its own session to the browser target and calls `Target.setDiscoverTargets` and `Target.getTargets` on it with ids of its own. Neither the session nor its messages ever reach the page. From then on it knows every target's URL and opener. A target on an inheriting URL (`about:blank`, `about:srcdoc`, none) is protected when it was protected before or when its opener is protected or unknown, so a blank popup that seven opens counts as seven. On a page session, the main frame's `securityOrigin` (`Page.frameNavigated`) and the default context's `origin` (`Runtime.executionContextCreated`) count too.
493
+ - **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.
494
+ - **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.
495
+ - **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`.
496
+ - **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. 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. Continuing, failing or fulfilling it is allowed.
497
+ - **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.
498
+ - **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`.
499
+ - **Navigation by other means.** A script's `location = …`, a link, `window.open` or a server redirect can't be stopped: the node sees the target arrive (`Target.targetInfoChanged`) only after the browser committed it. Then the node detaches every page session on it, drops their events and results, and refuses further commands on them; the page gets `Target.detachedFromTarget`. Commands that were already on their way may still have run in the new page.
500
+ - **Listing.** `Target.getTargets`, `Target.getTargetInfo`, `Target.targetCreated` and `Target.targetInfoChanged` still show protected targets, so seven knows its tab exists, but their `url` and `title` are only the origin (`https://seven.sliccy.ai`, or `about:blank`). Service worker registrations and versions on a protected origin are left out of `ServiceWorker` events, and `Storage`, `DOMStorage` and `BackgroundService` events that name a protected origin are dropped.
501
+ - **Limits.** The filter relies on Chrome's site isolation: a seven frame inside a page of another site is a target of its own (`iframe`), which the node protects, but a page can still frame it, and a screenshot of that page shows it. A same-site frame shares its parent's process and isn't a target. Every `sliccy.ai` host is protected, so this only matters for an extra origin, such as one port of `127.0.0.1` framed by a page on another. If the node loses its own session (`ECONNRESET: slicc lost track of the browser's targets`), it refuses every command and resets the stream unless the browser closes within 2 s. The node's own setup connection (see [Local setup](#local-setup-slicc-attach)) is not a `cdp` stream and isn't filtered.
502
+
491
503
  **List changes.** The node checks every listed browser's debugging port every 2 s. One that fails twice in a row is removed: its open streams get `RESET ECONNRESET: browser quit`, and a later OPEN for it gets `ENOENT`. Once its port answers again it is listed again under the same id. A browser removed through the API (`Registry.Remove`, for the TUI) has its streams reset with `ECONNRESET: browser removed`.
492
504
 
493
505
  **`browsers` updates** (page cap `browsers`), node → page. When the list changes while a link is up and the page's HELLO has `browsers` in `caps`, the node opens `OPEN { "kind": "browsers", "browsers": [ … ] }` on the control channel with the full current list in HELLO's shape. It replaces the previous list; there are no deltas. The page answers OPENED `{}` and END, and the node sends END. Updates are sent one at a time per link, a change that comes while one is in flight is sent after it, with the list as it is then, and an update the page doesn't finish within 10 s is reset with `ETIMEDOUT`. A change between the HELLO and the link coming up is sent as an update right away.
494
506
 
495
- `test/integration/testdata/link/link.js` is a page-side implementation of the link (framing, credit, both channel layouts, the violation rules, and `resolve` and raw-fetch helpers) that the integration tests run in Chrome against `slicc attach`. `cdp.js` next to it is a CDP client over `cdp` streams, `fs.js` an op-shaped client for `fs` streams (`call`, `list`, `read`, `write`, `watch`), and `page.js` answers `browsers` and `mounts` updates. `page.js` keeps one link per `node` id from the hello. For tray links (no hello `node`) it replaces an older link with the same fingerprint only when HELLO's `node` matches, as seven does. `agent.js` is a fake agent behind the page's `agent` cap: the tests queue scripted runs, emit transcript events, hold and release a run, reset watch streams, and turn the cap off. Loaded with `?kernel`, the test page lists `kernel-in` and answers `kernel` OPENs with `kernel.js`, a small HTTP and WebSocket echo server in the page.
507
+ `test/integration/testdata/link/link.js` is a page-side implementation of the link (framing, credit, both channel layouts, the violation rules, and `resolve` and raw-fetch helpers) that the integration tests run in Chrome against `slicc attach`. `cdp.js` next to it is a CDP client over `cdp` streams, `protect.js` probes the filter that keeps seven's origin out of reach, `fs.js` an op-shaped client for `fs` streams (`call`, `list`, `read`, `write`, `watch`), and `page.js` answers `browsers` and `mounts` updates. `page.js` keeps one link per `node` id from the hello. For tray links (no hello `node`) it replaces an older link with the same fingerprint only when HELLO's `node` matches, as seven does. `agent.js` is a fake agent behind the page's `agent` cap: the tests queue scripted runs, emit transcript events, hold and release a run, reset watch streams, and turn the cap off. Loaded with `?kernel`, the test page lists `kernel-in` and answers `kernel` OPENs with `kernel.js`, a small HTTP and WebSocket echo server in the page.
496
508
 
497
509
  ### Kernel services
498
510
 
@@ -539,6 +551,14 @@ The browser's connection waits unread for `OPENED`.
539
551
  - Names never reveal host paths, and neither does anything else on the link.
540
552
  - Without a folder, the node doesn't advertise `fs`, and an `fs` OPEN gets `EOPNOTSUPP`.
541
553
 
554
+ **Private paths.** Some folders are never shared, even inside a folder that is:
555
+ - slicc's own config, data and cache folders (`<config>/slicc`, which holds the DTLS certificates, the SSH host key, the tray state and the vault pairing keys);
556
+ - browser profiles: slicc's `seven-profiles` and `profiles`, SLICC six's profiles and `SLICC_USER_DATA_DIR`, and the user data folders of the browsers slicc knows, since the vault's storage lives there;
557
+ - slicc-jerk's files: `$XDG_CONFIG_HOME/slicc-jerk` and `$XDG_STATE_HOME/slicc-jerk` (`~/.config` and `~/.local/state` when unset, macOS included), `/etc/slicc-jerk`, and `SLICC_JERK_CONFIG`; and on Windows `slicc-jerk` under `%APPDATA%`, `%LOCALAPPDATA%` and `%ProgramData%`;
558
+ - host fnox's files: `FNOX_CONFIG_DIR` and `FNOX_STATE_DIR` with fnox's own defaults (`$XDG_CONFIG_HOME/fnox` and `$XDG_STATE_HOME/fnox`, else `~/.config/fnox` and `~/.local/state/fnox`, or `~\AppData\Local\fnox` on Windows), `FNOX_AGE_KEY_FILE`, and the daemon's socket folders.
559
+
560
+ The paths are read from slicc's own environment at start. A `--mount` of one of them, or of a folder inside one, is skipped with `--mount <spec>: slicc never shares this folder, which holds its own keys or a credential tool's files, skipping`. In a folder that contains one, every operation on a private path or below it is `EACCES` with `slicc never shares this path`. That holds when the path is reached through a symlink, through a Windows 8.3 short name, or, on macOS and Windows, typed with a different case. A `rename`, `rmdir`, `unlink` or `symlink` of a folder that holds a private path (`.config`, for example) is refused too, so a private folder can't be moved out of the fence or replaced. `list` still shows a private folder's name. `watch` drops a change inside a private folder before it is batched, so it adds no line, no parent folder and no `all`.
561
+
542
562
  **HELLO.** `caps` lists `fs`, and `"mounts"` lists the folders:
543
563
 
544
564
  ```json
@@ -886,6 +906,8 @@ In the same process, probe ports, dirs and a process list passed in explicitly (
886
906
 
887
907
  On macOS, a headless Chrome started with `HOME` pointed at a temporary dir may never load a page (seen on a developer Mac, not on CI). So on macOS the test that has `slicc` launch Chrome for seven runs it with the real `HOME` and a unique `--profile`, which it deletes afterwards.
888
908
 
909
+ 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.
910
+
889
911
  The real-Chrome tests in `test/integration/` launch headless, so they run the executable directly. A windowed launch on macOS goes through `open -n -W -a`, which CI doesn't cover: on GitHub's macOS runners, Chrome started that way never writes `DevToolsActivePort`.
890
912
 
891
913
  ## Releases
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc",
3
- "version": "1.30.0",
3
+ "version": "1.31.0",
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,11 +18,11 @@
18
18
  "node": ">=18"
19
19
  },
20
20
  "optionalDependencies": {
21
- "@ai-ecoverse/slicc-darwin-arm64": "1.30.0",
22
- "@ai-ecoverse/slicc-darwin-amd64": "1.30.0",
23
- "@ai-ecoverse/slicc-linux-arm64": "1.30.0",
24
- "@ai-ecoverse/slicc-linux-amd64": "1.30.0",
25
- "@ai-ecoverse/slicc-windows-arm64": "1.30.0",
26
- "@ai-ecoverse/slicc-windows-amd64": "1.30.0"
21
+ "@ai-ecoverse/slicc-darwin-arm64": "1.31.0",
22
+ "@ai-ecoverse/slicc-darwin-amd64": "1.31.0",
23
+ "@ai-ecoverse/slicc-linux-arm64": "1.31.0",
24
+ "@ai-ecoverse/slicc-linux-amd64": "1.31.0",
25
+ "@ai-ecoverse/slicc-windows-arm64": "1.31.0",
26
+ "@ai-ecoverse/slicc-windows-amd64": "1.31.0"
27
27
  }
28
28
  }