@ai-ecoverse/slicc-browsers 1.16.0 → 1.16.1
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.
- package/README.md +2 -2
- package/guard-vectors.json +11 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -187,7 +187,7 @@ Every CDP guard runs the vectors in `guard-vectors.json` (schema `schema/guard-v
|
|
|
187
187
|
- the `C8` rows for privileged pages: `C8.navigate` (a page navigates to `chrome://settings`, `chrome://password-manager`, an extension page or `file:///`; refused), `C8.view-source` (the same through `view-source:`; refused), `C8.create` (`Target.createTarget` straight on those pages; refused), `C8.browser-ui-listed` (`Target.getTargets` lists no `browser_ui` target) and `C8.browser-ui-attach` (`Target.attachToTarget` by a `browser_ui` target's id; refused). All five have an unguarded control, since the guard refuses them only on the privileged target. Two cases aren't rows, because Chrome itself blocks them, so an unguarded client can't tell a guard from none: a page's `window.open('chrome://settings')`, and an `about:` alias such as `about:settings`, which `Page.navigate` and `Target.createTarget` both turn into `about:blank#blocked`. The `about:` aliases are in `protected.json` instead.
|
|
188
188
|
- slicc-cdp's owner vectors in `test/integration/guard-native.test.mjs` at `d85ac3c`: `C5.script`, a protected script subresource under the client's own `Fetch.enable` `*` at both stages (the guard neither pauses it for the client nor lets the client fulfil it, and the page runs the stand-in's real `/script`, while the control's paused request carries its headers as an object with `User-Agent` and runs the forged script), and `X1.after-exit`, the client lifecycle row below.
|
|
189
189
|
|
|
190
|
-
`X1.after-exit` (family `X`, client lifecycle) needs `clientExit`. Through the guard, the client opens an ordinary tab, registers `Page.addScriptToEvaluateOnNewDocument` with `{beacon}`, `Network.setExtraHTTPHeaders` with `x-probe: {tag}` and `Fetch.enable` `*` with a rule that fulfils the destination with a forged `FULFILLED` page, then loads the `/page` trigger whose `go()` navigates to `{target}/canary/{tag}`. Before the exit it must see its init-script beacon, its header on the trigger request and the trigger's `Fetch.requestPaused
|
|
190
|
+
`X1.after-exit` (family `X`, client lifecycle) needs `clientExit`. Through the guard, the client opens an ordinary tab, registers `Page.addScriptToEvaluateOnNewDocument` with `{beacon}`, `Network.setExtraHTTPHeaders` with `x-probe: {tag}` and `Fetch.enable` `*` with a rule that fulfils the destination with a forged `FULFILLED` page, then loads the `/page?k=href&tag={tag}&to={target}/canary/{tag}` trigger whose `go()` navigates to `{target}/canary/{tag}`. Before the exit it must see its init-script beacon, its header on the trigger request and the trigger's `Fetch.requestPaused`, matched up to `&to=`, so a guard that redacts the embedded protected URL to its origin still matches: those are the positive evidence on both legs. Then the client exits, the unguarded observer calls `go()`, and the destination must be served and read as the real `canary` document, with no beacon from `{target}`, no `x-probe` on its request, no forged body and no `Fetch.requestPaused` for it reaching the client: nothing the client registered may outlive it. The control runs the same on `{plain}` through the guard, and expects the same, since an ordinary navigation after the exit must be just as clean. A guard that keeps its upstream session, or its own init scripts, headers or interception, past the client's exit fails the row.
|
|
191
191
|
|
|
192
192
|
The `C9` foreign extension isolated-world family requires `extensionWorld`: a browser hosting a foreign content-script extension on the ordinary fixture page. `C9.world-hidden` requires the page default context to remain visible after `Runtime.enable`, while the extension context and Runtime/Debugger identifiers remain hidden without cutting or detaching the session. `C9.world-select` probes numeric and unique context selectors, object and argument handles, promises, properties, named bindings and DOM node resolution; each command selecting the hidden world must fail with the `slicc: refused:` prefix, never an ordinary browser error. Numeric guesses also sweep ids 1–32: an id not exposed to this client must be refused, while every exposed numeric context must remain usable; none of those guarded probes may reach the fixture content-script marker. The marker combines the content script’s global lexical `root` binding with its extension-id DOM marker and `chrome.runtime.id`, and is independently required to be absent from the page default world. `C9.world-debugger` pauses inside that content script: the control must reach its frame, while the guard must refuse or hide it. The control waits up to 5000 ms (scaled by `settleScale`) for `Debugger.paused`; when it never pauses, `reachable` records `"incomplete"`, not `false`, and the row fails with `extensionWorld debugger: no Debugger.paused within <ms>ms`. The guarded leg waits up to 1500 ms, scaled by `refusalScale`. `C9.page-drivable` evaluates `self.origin`, captures a DOM snapshot and dispatches an Input click on the same ordinary page; cutting the entire session fails this regression row. All four use an unguarded control, the default browser context and observer discovery of the real extension world, not an invented isolated world. Protected default contexts remain session-cutting evidence; hiding a foreign isolated world does not weaken any seven-origin row.
|
|
193
193
|
|
|
@@ -207,7 +207,7 @@ The `C8.newtab` reachability control attaches through the guard to a settled ord
|
|
|
207
207
|
|
|
208
208
|
`C8.network-error` and `C8.iframe-error` are ordinary-error reachability controls: request the configured `network-error` URL (default `http://nonexistent.invalid/`) directly or in an ordinary iframe, observe a failed Document request, reattach to the settled tab, evaluate and snapshot its document, then navigate the same tab to an ordinary document. Both control and guarded legs must pass. The failing URL is unchanged on the control, rather than replaced with a healthy origin, and the rows require `browserSession` but not `chromeUrlsAttach`. With Chrome for Testing 156.0.8078.4, scheme-wide `chrome-error` protection made the direct-error row fail both legs because reattachment was refused; removing it passed both rows, with readable DOM and successful recovery. The old emulator still allowed the cross-process iframe parent because the iframe TargetInfo kept the failing HTTP URL, but that layout-specific behavior is not grounds for protecting the error scheme. Plain-client controls and reachability legs also passed both rows.
|
|
209
209
|
|
|
210
|
-
`E4` and the `E6` rows are runnable, each with a guarded-through control on the ordinary origin that must show the effect. `E4` sets a `Debugger.setBreakpointByUrl` on line 0 of the `listener=1` document's `/listener.js?n=<tag>` with a condition that sends `{beacon}` and returns `false`; the control needs that beacon, and the guarded leg needs neither the beacon nor a `Debugger.paused` in the protected document. `E4.instrumentation` sets `Debugger.setInstrumentationBreakpoint` with `beforeScriptWithSourceMapExecution`, so only `/listener.js`, whose `SourceMap` header names a source map, pauses: `beforeScriptExecution` would also pause the runner's own `Runtime.evaluate` and any extension's content script first. `E4.event-listener` sets `DOMDebugger.setEventListenerBreakpoint` for `load`. Both set up before the trigger, need a `Debugger.paused` on the control (in `/listener.js`, or for `E4.event-listener` with `listener:load`, which only that document registers, since a listener pause reports no script URL), none on the guarded leg, and end with `Debugger.disable`
|
|
210
|
+
`E4` and the `E6` rows are runnable, each with a guarded-through control on the ordinary origin that must show the effect. `E4` sets a `Debugger.setBreakpointByUrl` on line 0 of the `listener=1` document's `/listener.js?n=<tag>` with a condition that sends `{beacon}` and returns `false`; the control needs that beacon, and the guarded leg needs neither the beacon nor a `Debugger.paused` in the protected document. `E4.instrumentation` sets `Debugger.setInstrumentationBreakpoint` with `beforeScriptWithSourceMapExecution`, so only `/listener.js`, whose `SourceMap` header names a source map, pauses: `beforeScriptExecution` would also pause the runner's own `Runtime.evaluate` and any extension's content script first. `E4.event-listener` sets `DOMDebugger.setEventListenerBreakpoint` for `load`. Both set up before the trigger, need a `Debugger.paused` on the control (in `/listener.js`, or for `E4.event-listener` with `listener:load`, which only that document registers, since a listener pause reports no script URL), none on the guarded leg, and end with `Debugger.resume` and then `Debugger.disable` on the page session: Chrome doesn't answer `Debugger.disable` while the page sits in a pause, so a client that never times calls out would hang there. The resume can't hide a pause, since the `Debugger.paused` it ends was already seen, and every call in these rows must answer before the client's call timeout. The `E6` overrides are set on the page session before the trigger: `E6.headers` (`x-probe`), `E6.ua-network` and `E6.ua-emulation` (`User-Agent: slicc-probe-<tag>`) and `E6.cache-disabled` (`Pragma: no-cache`) are read from the stand-in's request log; `E6.network-conditions` (1500 ms latency) needs a navigation `duration` of at least 1000 ms, since Chrome delays the body rather than `responseStart`; `E6.locale` (`fr-CH`), `E6.timezone` (`Pacific/Chatham`) and `E6.network-state` (`navigator.onLine` false) are read by the unguarded observer in the destination document, and `E6.network-state` starts on `{cross}`, because Chrome drops that override on a same-site navigation once a second session is attached to the page. A guard that keeps its own session on the page, as the test emulator's Fetch shield does, can still lose it, and then fails that control rather than passing it; `E6.blocked-urls` has the observer fetch a blocked `/data` subresource there. Observer reads first check that the page is the exact destination URL, so a blocked or replaced document never shows the effect. The five overrides Chrome also applies inside a cross-site iframe have an `.iframe` row, triggered through `/framed`; `E6.network-conditions.iframe` reads the iframe's `duration` from the parent's resource timing. Each override is refusable at registration, with its observation depending on that refusal. These rows settle on the destination's load or request rather than on the detach variant, because each effect lands when the request is made or the script runs.
|
|
211
211
|
|
|
212
212
|
A client may register `Fetch.enable` patterns naming a protected origin in either of two conformant ways: the guard allows registration but never pauses or forwards protected requests to the client and refuses continue, fulfil or fail calls for request ids it did not hand out; or the guard refuses registration with its declared refusal text. Setup calls explicitly naming a protected placeholder are refusable with `refusal.onlyProtected: true`, and interception-dependent observations depend on that refusal. Wildcard and ordinary-only patterns do not receive this exemption. The ordinary-origin control still runs through the guard and must succeed.
|
|
213
213
|
|
package/guard-vectors.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"setVersion": "1.16.
|
|
3
|
+
"setVersion": "1.16.1",
|
|
4
4
|
"sources": [
|
|
5
5
|
{
|
|
6
6
|
"repo": "ai-ecoverse/slicc-cli",
|
|
@@ -14967,6 +14967,9 @@
|
|
|
14967
14967
|
{
|
|
14968
14968
|
"wait": 2000
|
|
14969
14969
|
},
|
|
14970
|
+
{
|
|
14971
|
+
"cdp": "Debugger.resume"
|
|
14972
|
+
},
|
|
14970
14973
|
{
|
|
14971
14974
|
"cdp": "Debugger.disable"
|
|
14972
14975
|
}
|
|
@@ -15121,6 +15124,9 @@
|
|
|
15121
15124
|
{
|
|
15122
15125
|
"wait": 2000
|
|
15123
15126
|
},
|
|
15127
|
+
{
|
|
15128
|
+
"cdp": "Debugger.resume"
|
|
15129
|
+
},
|
|
15124
15130
|
{
|
|
15125
15131
|
"cdp": "Debugger.disable"
|
|
15126
15132
|
}
|
|
@@ -18041,7 +18047,7 @@
|
|
|
18041
18047
|
"trigger": [
|
|
18042
18048
|
{
|
|
18043
18049
|
"page": "navigate",
|
|
18044
|
-
"url": "{ordinary}/page?k=href&to={target}/canary/{tag}
|
|
18050
|
+
"url": "{ordinary}/page?k=href&tag={tag}&to={target}/canary/{tag}"
|
|
18045
18051
|
},
|
|
18046
18052
|
{
|
|
18047
18053
|
"settle": {
|
|
@@ -18089,7 +18095,9 @@
|
|
|
18089
18095
|
"where": {
|
|
18090
18096
|
"params": {
|
|
18091
18097
|
"request": {
|
|
18092
|
-
"url":
|
|
18098
|
+
"url": {
|
|
18099
|
+
"$regex": "^{ordinary}/page\\?k=href&tag={tag}&to="
|
|
18100
|
+
}
|
|
18093
18101
|
}
|
|
18094
18102
|
}
|
|
18095
18103
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc-browsers",
|
|
3
|
-
"version": "1.16.
|
|
3
|
+
"version": "1.16.1",
|
|
4
4
|
"description": "SLICC's shared browser catalog, JSON schemas and discovery conformance corpus",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"test:unit:guard": "mkdir -p coverage/unit && node --experimental-vm-modules --no-warnings --experimental-test-coverage --test --test-coverage-include=guard-runner.mjs --test-coverage-include=fixture-server.mjs --test-coverage-include=fixture-client.mjs --test-coverage-include=observer-target.mjs --test-coverage-include=protected-error-page.mjs --test-coverage-include=unparseable-url.mjs --test-coverage-include=scripts/browser-runner.mjs --test-coverage-include=scripts/validate.mjs --test-reporter=lcov --test-reporter-destination=coverage/unit/guard.lcov test/unit/guard-*.test.mjs && slicc-diff-cover coverage/unit/guard.lcov"
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
|
-
"@ai-ecoverse/slicc-shared-web": "2.7.
|
|
84
|
+
"@ai-ecoverse/slicc-shared-web": "2.7.4",
|
|
85
85
|
"@biomejs/biome": "2.5.15",
|
|
86
86
|
"ajv": "8.20.0",
|
|
87
87
|
"ajv-formats": "3.0.1",
|