dsh-permission-rules 0.6.18 → 0.6.20
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/CHANGELOG.md +26 -0
- package/README.es.md +3 -1
- package/README.hi.md +3 -1
- package/README.md +3 -1
- package/README.pt.md +3 -1
- package/README.zh.md +3 -1
- package/lib/index.js +137 -6
- package/lib/types/proxy.d.ts +12 -3
- package/lib/types/proxy.d.ts.map +1 -1
- package/lib/types/rules.d.ts.map +1 -1
- package/lib/types/runtime.d.ts +53 -0
- package/lib/types/runtime.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/proxy.ts +13 -4
- package/src/rules.ts +21 -1
- package/src/runtime.ts +114 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
## v0.6.20 - 2026-09-10
|
|
2
|
+
|
|
3
|
+
### Fixed
|
|
4
|
+
|
|
5
|
+
- **Corrected the mechanism by which this plugin participates in host networking (issue #22).** The five READMEs, `AGENTS.md` and the v0.6.19 note claimed that the process-wide injected proxy environment also placed the harness's own LLM transport under this policy. Measurement on 2026-09-10 (Node 22; `scripts/host-egress-probe.mjs`) shows it does not: the launcher installs undici's global dispatcher from the **launch environment** before the first plugin mounts, that dispatcher routes by its policy rather than by the environment, and Node samples the proxy environment at start — so a mid-process `process.env` write reaches neither `fetch` nor `node:http`. The injection covers spawned shell children, which is what it was always for. The READMEs' known-limitations bullet now says so, and the `llm/stream` annotation shipped in v0.6.19 is recorded as inert: it can only fire when a blocked child-process connection coincides within its window with an unrelated model failure, so it misattributes rather than diagnoses — it has been **removed in this release**, along with its registration, its block-window helper, the type import it needed, and its four tests.
|
|
6
|
+
|
|
7
|
+
## v0.6.19 - 2026-09-10
|
|
8
|
+
|
|
9
|
+
### Security
|
|
10
|
+
|
|
11
|
+
- A CONNECT tunnel refuses to dial a hostname when the adjudication resolved no address: `connectUpstream` now fails closed (logged, 502 to the client) instead of falling back to `connect(port, target.host)` — a second DNS resolution whose answer the rules never saw, and the one remaining path governed by Node's 250 ms `autoSelectFamilyAttemptTimeout`. The reported path itself was already fixed in 0.6.17 (`connect` dials the addresses `decideWithResolution` returned, and an IP literal skips the family race entirely); this closes the residual (issue #21).
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Session-less host-level traffic is judged against the CONFIGURED chain instead of an empty map. `proxyChains()` consulted only `byCwd`, which `rulesFor(cwd)` populates from a session or tool call, so at boot the harness's own host-level fetches met the whitelist default and were blocked as `[network: blocked pending approval]` even with a matching allow rule already configured. `hostChain()` loads the chain for the host process's own working directory (project file → absolute `rulesFile` → configured fallback → shipped baseline) while no per-cwd chain is loaded; it never becomes a `byCwd` member, so a session workspace chain always outranks it, and an unusable configured chain warns once and degrades to the mode default (issue #18).
|
|
16
|
+
- Rule files are normalized before parsing: CRLF maps onto LF, a stray CR inside a line is dropped, and every CR is a line separator in a CR-only file. A lone CR is not a line break to the YAML parser in every position — it survived into the scalar it terminated (`domains: [registry.npmjs.org\r]`, or a final line ending in a bare CR), compiling a pattern that silently never matched its target (issue #19 item 4).
|
|
17
|
+
- Rule-file watches poll on WSL drvfs mounts: `watchPollingFor` switches a watch to `usePolling` (300 ms interval) when the watched rule file is under `/mnt/<drive>` or `/proc/version` reports a Microsoft kernel, because chokidar's native change events are unreliable on drvfs/9p and a rule edit otherwise stopped hot-reloading silently with no error. Detection is per watch, so every other host keeps the native watcher, and `/rules reload` stays the manual fallback (issue #19 item 1).
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- A failing model call now names the policy. The injected proxy environment is process-wide, so the harness's own LLM transport is adjudicated by this policy too, and a blocked provider endpoint surfaced as a bare `Connection error. / TRANSPORT`. A transparent `llm/stream` listener appends the `[network: …]` marker — blocked target, mode/rule, remediation — to the ORIGINAL error object (its class, code and retry facts stay intact) and logs it, so a turn can be attributed to the policy rather than reading as a provider outage. It registers only when `network.enabled`. It does NOT auto-allow provider endpoints: the two other resolutions the issue offers are not reachable from a plugin (`ctx.llm.listProviders()` exposes provider ids/names only, configured base URLs are adapter-owned, and there is no per-spawn environment seam for shell children), which the five READMEs record as a known limitation (issue #22).
|
|
22
|
+
|
|
23
|
+
### Tests
|
|
24
|
+
|
|
25
|
+
- Gate chain green: 23 files / 302 tests, coverage 92.27% statements / 87.29% branches / 93.62% functions.
|
|
26
|
+
|
|
1
27
|
## v0.6.18 - 2026-09-10
|
|
2
28
|
|
|
3
29
|
### Docs
|
package/README.es.md
CHANGED
|
@@ -45,7 +45,7 @@ Cada acierto **y** cada paso directo se registra como un evento de sesión `perm
|
|
|
45
45
|
- **Línea base de alto riesgo integrada** — un conjunto deny/ask embarcado (comandos destructivos, escalada de privilegios, descarga-y-ejecución, rutas sensibles) habilitado por defecto y añadido después de las reglas de usuario (una regla de usuario más cercana puede sobrescribirlo); se alterna con `builtin.enabled`.
|
|
46
46
|
- **Archivos de reglas jerárquicos** — `searchUp` opcional fusiona cada `.dsh/rules.yaml` desde el cwd de la sesión hasta la raíz del sistema de archivos, el más cercano primero.
|
|
47
47
|
- **Despliegue en dry-run** — `enforce: false` audita lo que la política *haría* mientras deja pasar cada llamada.
|
|
48
|
-
- **Recarga en caliente** — vigilancia Chokidar con debounce; una edición rota conserva las reglas anteriores, nunca falla.
|
|
48
|
+
- **Recarga en caliente** — vigilancia Chokidar con debounce; una edición rota conserva las reglas anteriores, nunca falla. En un host WSL, o para un archivo de reglas bajo `/mnt/<unidad>`, la vigilancia pasa a sondeo (polling) porque allí los eventos nativos de cambio no son fiables.
|
|
49
49
|
- **Fallo ruidoso** — YAML inválido, acciones/campos desconocidos, globs/regexes malos, patrones propensos a backtracking o más de `maxRules` reglas fallan la carga.
|
|
50
50
|
|
|
51
51
|
## Rule syntax
|
|
@@ -78,6 +78,7 @@ Una **política de red a nivel de proceso** estilo Codex: el tráfico de subproc
|
|
|
78
78
|
|
|
79
79
|
- **Emparejamiento** — `match.network` con `domains` / `ips` / `ports` / `schemes` (globs, comodines, CIDR, rangos de puertos; se aceptan puertos YAML numéricos). La extracción de candidatos URL en la ruta caliente `tools/pre-execute` se dispara sobre argumentos de herramientas web y URLs embebidas en texto de comandos bash/pwsh; los destinos de loopback pueden cortocircuitar reglas según la política `loopback`. Los literales IPv6 mapeados a IPv4 se normalizan a su forma IPv4 antes de comparar, y el proxy se conecta a las direcciones con las que se tomó la decisión, sin una segunda resolución DNS.
|
|
80
80
|
- **Auditoría** — las conexiones denegadas anexan `permissionRules/network` a la sesión propietaria (la misma puerta adaptativa `ignorable`), con contadores de bloqueo e intercepciones recientes en `/rules network` y la página de settings.
|
|
81
|
+
- **Diagnóstico** — las conexiones bloqueadas llevan un mensaje `[network: …]` que nombra el destino bloqueado, el modo o la regla que decidió y la solución.
|
|
81
82
|
|
|
82
83
|
## Quick start
|
|
83
84
|
|
|
@@ -174,6 +175,7 @@ Todos los parámetros son campos Schemastery `Config` (modificables desde cordis
|
|
|
174
175
|
- **Los candidatos de ruta son heurísticos.** Solo las claves de argumento documentadas alimentan el emparejamiento de rutas, y el emparejamiento relativo al workspace es insensible a mayúsculas ASCII solo con `caseInsensitivePaths` activado.
|
|
175
176
|
- **Los globs son un subconjunto conservador.** Sin expansión de llaves — escribe dos patrones, o usa modo regex.
|
|
176
177
|
- **La guardia de backtracking de regex es estructural, no exhaustiva.** Prefiere el modo glob para archivos no confiables.
|
|
178
|
+
- **Las peticiones salientes del propio host no pasan por este proxy.** El entorno de proxy inyectado cubre los **subprocesos de shell derivados** —que es para lo que sirve la inyección— y cualquier consumidor que lea los nombres de proxy en el momento de la petición. **No** cubre el tráfico basado en `fetch` del propio proceso del host: el launcher instala el dispatcher global de undici desde el **entorno de lanzamiento** antes de que se monte el primer plugin, ese dispatcher enruta por su política y no por el entorno, y Node muestrea el entorno de proxy al arrancar, así que un plugin que se monte después no puede redirigirlo. Consecuencias: los endpoints del proveedor **no** necesitan una regla allow, y `network.injectEnv: false` no saca al proceso del host de nada. Medido el 2026-09-10 en Node 22; reproducible con `scripts/host-egress-probe.mjs`.
|
|
177
179
|
|
|
178
180
|
## Collaborating with dsh-auto-review
|
|
179
181
|
|
package/README.hi.md
CHANGED
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
- **अंतर्निहित उच्च-जोखिम आधाररेखा** — एक साथ भेजा गया deny/ask नियम-समूह (विनाशकारी कमांड, विशेषाधिकार वृद्धि, डाउनलोड-और-निष्पादन, संवेदनशील पथ) डिफ़ॉल्ट रूप से सक्षम और उपयोगकर्ता नियमों के बाद जोड़ा गया (निकटतम उपयोगकर्ता नियम इसे अधिरोहित कर सकता है); `builtin.enabled` से टॉगल करें।
|
|
46
46
|
- **पदानुक्रमित नियम फ़ाइलें** — वैकल्पिक `searchUp` सत्र cwd से फ़ाइल-सिस्टम रूट तक हर `.dsh/rules.yaml` को मर्ज करता है, निकटतम पहले।
|
|
47
47
|
- **dry-run रोलआउट** — `enforce: false` ऑडिट करता है कि नीति *क्या* करती, हर कॉल को पास करते हुए।
|
|
48
|
-
- **हॉट रीलोड** — debounce सहित Chokidar निगरानी; टूटा संपादन पिछले नियम रखता है, कभी क्रैश नहीं।
|
|
48
|
+
- **हॉट रीलोड** — debounce सहित Chokidar निगरानी; टूटा संपादन पिछले नियम रखता है, कभी क्रैश नहीं। WSL होस्ट पर, या `/mnt/<drive>` के नीचे रखी नियम फ़ाइल के लिए, निगरानी polling पर चली जाती है क्योंकि वहाँ मूल परिवर्तन इवेंट भरोसेमंद नहीं होते।
|
|
49
49
|
- **ज़ोर से विफल** — अमान्य YAML, अज्ञात action/फ़ील्ड, ख़राब globs/regex, बैकट्रैकिंग-प्रवण पैटर्न या `maxRules` से अधिक नियम लोड को विफल करते हैं।
|
|
50
50
|
|
|
51
51
|
## Rule syntax
|
|
@@ -78,6 +78,7 @@ Codex-शैली की **प्रक्रिया-स्तरीय न
|
|
|
78
78
|
|
|
79
79
|
- **मिलान** — `match.network` `domains` / `ips` / `ports` / `schemes` के साथ (globs, वाइल्डकार्ड, CIDR, पोर्ट श्रेणियाँ; संख्यात्मक YAML पोर्ट स्वीकृत)। `tools/pre-execute` हॉट पथ पर URL-उम्मीदवार निष्कर्षण वेब-टूल तर्कों और bash/pwsh कमांड टेक्स्ट में एम्बेडेड URLs पर चलता है; लूपबैक लक्ष्य `loopback` नीति के अनुसार नियमों को शॉर्ट-सर्किट कर सकते हैं। IPv4-मैप्ड IPv6 लिटरल तुलना से पहले IPv4 रूप में सामान्यीकृत होते हैं, और प्रॉक्सी उन्हीं पतों पर कनेक्ट करता है जिन पर निर्णय लिया गया — दूसरा DNS रिज़ॉल्यूशन नहीं।
|
|
80
80
|
- **ऑडिट** — अस्वीकृत कनेक्शन स्वामी सत्र में `permissionRules/network` जोड़ते हैं (वही अनुकूली `ignorable` द्वार), `/rules network` और settings पृष्ठ में ब्लॉक काउंटर व हाल की अवरोधन के साथ।
|
|
81
|
+
- **निदान** — अवरुद्ध कनेक्शन `[network: …]` संदेश लेकर आते हैं जो अवरुद्ध लक्ष्य, निर्णय लेने वाला मोड या नियम, और समाधान बताता है।
|
|
81
82
|
|
|
82
83
|
## Quick start
|
|
83
84
|
|
|
@@ -174,6 +175,7 @@ dsh --profile web --dump-config | grep -A4 'id: permission-rules'
|
|
|
174
175
|
- **पथ उम्मीदवार अनुमानी हैं।** केवल दस्तावेज़ित तर्क कुंजियाँ पथ मिलान को खिलाती हैं, और कार्यक्षेत्र-सापेक्ष मिलान केवल `caseInsensitivePaths` चालू होने पर ASCII-केस-असंवेदी है।
|
|
175
176
|
- **globs एक रूढ़िवादी उपसमुच्चय हैं।** कोई ब्रेस विस्तार नहीं — दो पैटर्न लिखें, या regex मोड उपयोग करें।
|
|
176
177
|
- **regex बैकट्रैकिंग गार्ड संरचनात्मक है, संपूर्ण नहीं।** अविश्वसनीय फ़ाइलों के लिए glob मोड पसंद करें।
|
|
178
|
+
- **होस्ट के अपने आउटबाउंड अनुरोध इस प्रॉक्सी से नहीं जाते।** इंजेक्ट किया गया प्रॉक्सी वातावरण **उत्पन्न shell उप-प्रक्रियाओं** को कवर करता है — इंजेक्शन इसी के लिए है — और उन उपभोक्ताओं को जो अनुरोध के समय प्रॉक्सी नाम पढ़ते हैं। यह होस्ट प्रोसेस के अपने `fetch`-आधारित ट्रैफ़िक को **नहीं** कवर करता: launcher पहले प्लगइन के माउंट होने से पहले **लॉन्च वातावरण** से undici का ग्लोबल dispatcher स्थापित कर देता है, वह dispatcher वातावरण से नहीं बल्कि अपनी नीति से रूट करता है, और Node प्रॉक्सी वातावरण को प्रारंभ पर सैंपल करता है — इसलिए बाद में माउंट होने वाला प्लगइन उसे नहीं मोड़ सकता। परिणाम: प्रदाता endpoints के लिए allow नियम की **आवश्यकता नहीं** है, और `network.injectEnv: false` होस्ट प्रोसेस को किसी चीज़ से बाहर नहीं करता। 2026-09-10 को Node 22 पर मापा गया; `scripts/host-egress-probe.mjs` से दोहराएँ।
|
|
177
179
|
|
|
178
180
|
## Collaborating with dsh-auto-review
|
|
179
181
|
|
package/README.md
CHANGED
|
@@ -46,7 +46,7 @@ Every hit **and** every passthrough is audit-logged as a `permissionRules/decisi
|
|
|
46
46
|
- **Built-in high-risk baseline** — a shipped deny/ask ruleset (destructive commands, privilege escalation, download-and-execute, sensitive paths) enabled by default and appended after user rules so a nearer user rule can override it; toggle with `builtin.enabled`.
|
|
47
47
|
- **Hierarchical rule files** — optional `searchUp` merges every `.dsh/rules.yaml` from the session cwd to the filesystem root, nearest first.
|
|
48
48
|
- **Dry-run rollout** — `enforce: false` audits what the policy *would* do while passing every call through.
|
|
49
|
-
- **Hot reload** — Chokidar watch with debounce; a broken edit keeps the previous rules, never crashes.
|
|
49
|
+
- **Hot reload** — Chokidar watch with debounce; a broken edit keeps the previous rules, never crashes. On a WSL host, or for a rule file under `/mnt/<drive>`, the watch switches to polling because native change events are unreliable there.
|
|
50
50
|
- **Fail loud** — invalid YAML, unknown actions/fields, bad globs/regexes, backtracking-prone patterns, or more than `maxRules` rules fail the load.
|
|
51
51
|
|
|
52
52
|
## Rule syntax
|
|
@@ -79,6 +79,7 @@ A Codex-style **process-level network policy**: shell subprocess traffic flows t
|
|
|
79
79
|
|
|
80
80
|
- **Matching** — `match.network` with `domains` / `ips` / `ports` / `schemes` (globs, wildcards, CIDRs, port ranges; numeric YAML ports are accepted). URL-candidate extraction on the `tools/pre-execute` hot path fires on web-tool arguments and URLs embedded in bash/pwsh command text; loopback targets can short-circuit rules per `loopback` policy. IPv4-mapped IPv6 literals are normalized to their IPv4 form before matching, and the proxy connects on the addresses the decision was made on — never a second DNS resolution.
|
|
81
81
|
- **Audit** — denied connections append `permissionRules/network` to the owning session (same adaptive `ignorable` gate), with block counters and recent interceptions in `/rules network` and the settings page.
|
|
82
|
+
- **Diagnosis** — blocked connections carry a `[network: …]` message naming the blocked target, the mode or rule that decided, and the remediation.
|
|
82
83
|
|
|
83
84
|
## Quick start
|
|
84
85
|
|
|
@@ -175,6 +176,7 @@ All tunables are Schemastery `Config` fields (changeable from cordis.yml). An id
|
|
|
175
176
|
- **Path candidates are heuristic.** Only the documented argument keys feed path matching, and workspace-relative matching is ASCII-case-insensitive only when `caseInsensitivePaths` is on.
|
|
176
177
|
- **Globs are a conservative subset.** No brace expansion — write two patterns, or use regex mode.
|
|
177
178
|
- **The regex backtracking guard is structural, not exhaustive.** Prefer glob mode for untrusted files.
|
|
179
|
+
- **The host's own outbound requests do not go through this proxy.** The injected proxy environment covers **spawned shell children** — which is what the injection is for — and any consumer that reads the proxy names at request time. It does **not** cover the host process's own `fetch`-based traffic: the launcher installs undici's global dispatcher from the **launch environment** before the first plugin mounts, that dispatcher routes by its policy rather than by the environment, and Node samples the proxy environment at start — so a plugin mounting later cannot redirect it. Consequences: provider endpoints do **not** need an allow rule, and `network.injectEnv: false` does not take the host process out of anything. Measured 2026-09-10 on Node 22; reproduce with `scripts/host-egress-probe.mjs`.
|
|
178
180
|
|
|
179
181
|
## Collaborating with dsh-auto-review
|
|
180
182
|
|
package/README.pt.md
CHANGED
|
@@ -45,7 +45,7 @@ Cada acerto **e** cada passagem direta é registrada como um evento de sessão `
|
|
|
45
45
|
- **Linha de base de alto risco integrada** — um conjunto deny/ask embarcado (comandos destrutivos, escalada de privilégios, baixar-e-executar, caminhos sensíveis) habilitado por padrão e anexado após as regras de usuário (uma regra de usuário mais próxima pode sobrescrevê-lo); alterna com `builtin.enabled`.
|
|
46
46
|
- **Arquivos de regras hierárquicos** — `searchUp` opcional mescla cada `.dsh/rules.yaml` do cwd da sessão até a raiz do sistema de arquivos, o mais próximo primeiro.
|
|
47
47
|
- **Implantação em dry-run** — `enforce: false` audita o que a política *faria* enquanto deixa cada chamada passar.
|
|
48
|
-
- **Recarga a quente** — vigilância Chokidar com debounce; uma edição quebrada mantém as regras anteriores, nunca falha.
|
|
48
|
+
- **Recarga a quente** — vigilância Chokidar com debounce; uma edição quebrada mantém as regras anteriores, nunca falha. Num host WSL, ou para um arquivo de regras sob `/mnt/<unidade>`, a vigilância passa a polling porque os eventos nativos de mudança não são confiáveis ali.
|
|
49
49
|
- **Falha ruidosa** — YAML inválido, ações/campos desconhecidos, globs/regexes ruins, padrões propensos a backtracking ou mais de `maxRules` regras falham a carga.
|
|
50
50
|
|
|
51
51
|
## Rule syntax
|
|
@@ -78,6 +78,7 @@ Uma **política de rede em nível de processo** estilo Codex: o tráfego de subp
|
|
|
78
78
|
|
|
79
79
|
- **Correspondência** — `match.network` com `domains` / `ips` / `ports` / `schemes` (globs, curingas, CIDR, faixas de porta; portas YAML numéricas são aceitas). A extração de candidatos URL na rota quente `tools/pre-execute` dispara sobre argumentos de ferramentas web e URLs embutidas em texto de comando bash/pwsh; destinos de loopback podem curto-circuitar regras conforme a política `loopback`. Literais IPv6 mapeados em IPv4 são normalizados para a forma IPv4 antes da comparação, e o proxy conecta nos endereços usados na decisão, sem uma segunda resolução DNS.
|
|
80
80
|
- **Auditoria** — conexões negadas anexam `permissionRules/network` à sessão proprietária (a mesma porta adaptativa `ignorable`), com contadores de bloqueio e intercepções recentes em `/rules network` e na página de settings.
|
|
81
|
+
- **Diagnóstico** — conexões bloqueadas trazem uma mensagem `[network: …]` nomeando o destino bloqueado, o modo ou a regra que decidiu e a solução.
|
|
81
82
|
|
|
82
83
|
## Quick start
|
|
83
84
|
|
|
@@ -174,6 +175,7 @@ Todos os parâmetros são campos Schemastery `Config` (alteráveis pelo cordis.y
|
|
|
174
175
|
- **Candidatos de caminho são heurísticos.** Somente as chaves de argumento documentadas alimentam a correspondência de caminho, e a correspondência relativa ao workspace é insensível a maiúsculas ASCII apenas com `caseInsensitivePaths` ativado.
|
|
175
176
|
- **Globs são um subconjunto conservador.** Sem expansão de chaves — escreva dois padrões, ou use o modo regex.
|
|
176
177
|
- **A guarda de backtracking de regex é estrutural, não exaustiva.** Prefira o modo glob para arquivos não confiáveis.
|
|
178
|
+
- **As requisições de saída do próprio host não passam por este proxy.** O ambiente de proxy injetado cobre os **subprocessos de shell derivados** — que é para isso que a injeção serve — e qualquer consumidor que leia os nomes de proxy no momento da requisição. **Não** cobre o tráfego baseado em `fetch` do próprio processo do host: o launcher instala o dispatcher global do undici a partir do **ambiente de lançamento** antes de o primeiro plugin ser montado, esse dispatcher roteia pela sua política e não pelo ambiente, e o Node amostra o ambiente de proxy na inicialização, então um plugin montado depois não consegue redirecioná-lo. Consequências: os endpoints do provedor **não** precisam de uma regra allow, e `network.injectEnv: false` não tira o processo do host de nada. Medido em 2026-09-10 no Node 22; reproduza com `scripts/host-egress-probe.mjs`.
|
|
177
179
|
|
|
178
180
|
## Collaborating with dsh-auto-review
|
|
179
181
|
|
package/README.zh.md
CHANGED
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
- **内置高危基线** —— 随附的 deny/ask 规则集(破坏性命令、权限提升、下载即执行、敏感路径),默认开启并追加在用户规则之后(更近的用户规则可覆盖);用 `builtin.enabled` 开关。
|
|
46
46
|
- **分层规则文件** —— 可选 `searchUp` 从会话 cwd 到文件系统根合并每个 `.dsh/rules.yaml`,就近优先。
|
|
47
47
|
- **试运行上线** —— `enforce: false` 审计策略*会*做什么,同时放行每个调用。
|
|
48
|
-
- **热重载** —— Chokidar
|
|
48
|
+
- **热重载** —— Chokidar 监听带去抖;损坏的编辑保留旧规则、绝不崩溃。在 WSL 主机上(或规则文件位于 `/mnt/<盘符>` 下时)监听切换为轮询,因为该处的原生变更事件不可靠。
|
|
49
49
|
- **失败大声** —— 非法 YAML、未知 action/字段、坏 glob/正则、易回溯模式或超过 `maxRules` 的规则在加载期失败。
|
|
50
50
|
|
|
51
51
|
## Rule syntax
|
|
@@ -78,6 +78,7 @@ Codex 风格的**进程级网络策略**:shell 子进程流量经内置本地
|
|
|
78
78
|
|
|
79
79
|
- **匹配** —— `match.network` 用 `domains` / `ips` / `ports` / `schemes`(glob、通配符、CIDR、端口范围;数值型 YAML 端口可接受)。`tools/pre-execute` 热路径上的 URL 候选抽取作用于 web 工具参数与嵌入 bash/pwsh 命令文本的 URL;回环目标可按 `loopback` 策略短路规则。IPv4 映射的 IPv6 字面量在匹配前归一化为 IPv4 形式;代理按裁决到的地址建连,不做二次 DNS 解析。
|
|
80
80
|
- **审计** —— 被拒连接向所属会话追加 `permissionRules/network`(同样的自适应 `ignorable` 门),块计数器与近期拦截在 `/rules network` 与设置页展示。
|
|
81
|
+
- **诊断** —— 被拦截的连接带 `[network: …]` 消息,点名被拦目标、做出裁决的模式或规则,以及处置办法。
|
|
81
82
|
|
|
82
83
|
## Quick start
|
|
83
84
|
|
|
@@ -174,6 +175,7 @@ dsh --profile web --dump-config | grep -A4 'id: permission-rules'
|
|
|
174
175
|
- **路径候选是启发式的。** 只有文档化的参数键参与路径匹配,且工作区相对匹配仅在 `caseInsensitivePaths` 开启时忽略 ASCII 大小写。
|
|
175
176
|
- **glob 是保守子集。** 无花括号展开——写两个模式,或用正则模式。
|
|
176
177
|
- **正则回溯守卫是结构性的、非穷尽的。** 对不可信文件优先用 glob 模式。
|
|
178
|
+
- **宿主自身的出站请求不经过本代理。** 注入的代理环境覆盖**派生的 shell 子进程**(这正是注入的用途),以及在请求时读取代理变量名的消费者;它**不覆盖**宿主进程自身基于 `fetch` 的流量——launcher 在第一个插件挂载之前就用**启动环境**装好了 undici 的全局 dispatcher,该 dispatcher 按策略而非按环境路由,且 Node 在启动时采样代理环境,因此后挂载的插件无法改变它。结论:供应商端点**不需要**允许规则,`network.injectEnv: false` 也不会把宿主进程移出任何东西。2026-09-10 实测于 Node 22;用 `scripts/host-egress-probe.mjs` 可复现。
|
|
177
179
|
|
|
178
180
|
## Collaborating with dsh-auto-review
|
|
179
181
|
|
package/lib/index.js
CHANGED
|
@@ -516,7 +516,7 @@ var RuleError = class extends Error {
|
|
|
516
516
|
* @returns the validated document.
|
|
517
517
|
*/
|
|
518
518
|
function parseRulesDocument(text) {
|
|
519
|
-
const parsed = parseYaml(text);
|
|
519
|
+
const parsed = parseYaml(normalizeLineEndings(text));
|
|
520
520
|
if (parsed === null || parsed === void 0) return { rules: [] };
|
|
521
521
|
const root = asRecord(parsed, "rules document root");
|
|
522
522
|
const unknownRoot = Object.keys(root).filter((key) => key !== "rules");
|
|
@@ -875,6 +875,25 @@ function compileParamPatterns(key, patterns, options) {
|
|
|
875
875
|
negative
|
|
876
876
|
};
|
|
877
877
|
}
|
|
878
|
+
/**
|
|
879
|
+
* Normalize the line endings of one rule-file body before parsing. A file
|
|
880
|
+
* authored or checked out on the Windows side arrives with CRLF, and a lone
|
|
881
|
+
* CR — one not paired with an LF — is NOT a line break to the YAML parser in
|
|
882
|
+
* every position: it survives into the scalar it terminates, so a pattern
|
|
883
|
+
* spelled `domains: [registry.npmjs.org<CR>]`, or a final line ending in a
|
|
884
|
+
* bare CR, compiled a pattern that could never match its target (issue #19
|
|
885
|
+
* item 4). CRLF becomes LF; a stray CR inside a line is dropped (it is junk
|
|
886
|
+
* there — a deliberate CR is written as the YAML escape `\r` and never
|
|
887
|
+
* reaches this text); and a CR-only file (classic Mac line endings, no LF
|
|
888
|
+
* anywhere) treats every CR as its line separator. Every line-ending style
|
|
889
|
+
* therefore parses to the same document.
|
|
890
|
+
* @param text - the raw rule-file text.
|
|
891
|
+
* @returns the same text with LF line breaks and no stray CR.
|
|
892
|
+
*/
|
|
893
|
+
function normalizeLineEndings(text) {
|
|
894
|
+
if (!text.includes("\n")) return text.replace(/\r/g, "\n");
|
|
895
|
+
return text.replace(/\r\n/g, "\n").replace(/\r/g, "");
|
|
896
|
+
}
|
|
878
897
|
/** Parse YAML through the `yaml` dependency, mapping parse failures onto {@link RuleError}. */
|
|
879
898
|
function parseYaml(text) {
|
|
880
899
|
try {
|
|
@@ -2187,13 +2206,22 @@ var NetworkProxy = class {
|
|
|
2187
2206
|
}
|
|
2188
2207
|
/**
|
|
2189
2208
|
* Connect to the first adjudicated address that accepts, so the tunnel lands
|
|
2190
|
-
* on an address the decision approved
|
|
2191
|
-
*
|
|
2192
|
-
*
|
|
2209
|
+
* on an address the decision approved. Each candidate is tried in order so a
|
|
2210
|
+
* multi-address host does not lose its fallback.
|
|
2211
|
+
*
|
|
2212
|
+
* A target whose adjudication resolved no address FAILS here instead of
|
|
2213
|
+
* dialing the hostname (issue #21): dialing the name would be a second DNS
|
|
2214
|
+
* resolution — the answer could differ from the one the rules were evaluated
|
|
2215
|
+
* against — and it is the one remaining path where Node's happy-eyeballs
|
|
2216
|
+
* race applies, with its 250 ms `autoSelectFamilyAttemptTimeout` default
|
|
2217
|
+
* that kills any endpoint further away than that. Dialing an already-
|
|
2218
|
+
* resolved literal skips that algorithm entirely (net.js connects an IP
|
|
2219
|
+
* without a lookup), so the tunnel only ever reaches an adjudicated
|
|
2220
|
+
* address; the client's retry resolves and adjudicates again.
|
|
2193
2221
|
*/
|
|
2194
2222
|
async connectUpstream(target, port) {
|
|
2195
2223
|
const pinned = pinnedAddresses(target);
|
|
2196
|
-
if (pinned.length === 0)
|
|
2224
|
+
if (pinned.length === 0) throw new Error(`no adjudicated address for ${target.host}`);
|
|
2197
2225
|
let lastError;
|
|
2198
2226
|
for (const address of pinned) try {
|
|
2199
2227
|
return await new Promise((resolve, reject) => {
|
|
@@ -2547,6 +2575,53 @@ const WEB_TOOLS = ["web_fetch", "web_search"];
|
|
|
2547
2575
|
/** Stale in-flight entries are dropped after this many milliseconds (attribution is best-effort). */
|
|
2548
2576
|
const IN_FLIGHT_TTL_MS = 6e5;
|
|
2549
2577
|
/**
|
|
2578
|
+
* Chokidar polling interval used when the watched path lives on a filesystem
|
|
2579
|
+
* whose change events are unreliable (WSL drvfs/9p mounts): polling costs a
|
|
2580
|
+
* stat per interval, which is negligible for a rule file and far cheaper than
|
|
2581
|
+
* a rule edit that silently never hot-reloads.
|
|
2582
|
+
*/
|
|
2583
|
+
const POLLING_WATCH_INTERVAL_MS = 300;
|
|
2584
|
+
/**
|
|
2585
|
+
* Whether one watched path lies under a WSL drvfs mount (`/mnt/<drive>/…`),
|
|
2586
|
+
* where inotify-style change events are known to be unreliable — chokidar
|
|
2587
|
+
* then has to poll (issue #19 item 1). The separator is normalized first so
|
|
2588
|
+
* the check also recognizes the path as the Windows side spells it; a
|
|
2589
|
+
* Windows drive path (`D:\…`) never matches.
|
|
2590
|
+
* @param path - the watched file or directory path.
|
|
2591
|
+
* @returns true when the path addresses a drvfs mount.
|
|
2592
|
+
*/
|
|
2593
|
+
function isDvrfsPath(path) {
|
|
2594
|
+
return /^\/mnt\/[a-z](?:\/|$)/i.test(path.replace(/\\/g, "/"));
|
|
2595
|
+
}
|
|
2596
|
+
/**
|
|
2597
|
+
* Whether the running kernel is WSL's, as `/proc/version` reports it. Every
|
|
2598
|
+
* WSL kernel string carries `microsoft` (`…-microsoft-standard-WSL2`), which
|
|
2599
|
+
* is what the issue asks the detection to key on; a non-WSL Linux kernel
|
|
2600
|
+
* never does, and hosts without `/proc/version` (Windows, macOS) answer
|
|
2601
|
+
* false.
|
|
2602
|
+
* @param procVersion - the `/proc/version` text, or an empty string when it cannot be read.
|
|
2603
|
+
* @returns true when the kernel is Microsoft's.
|
|
2604
|
+
*/
|
|
2605
|
+
function isWslKernel(procVersion) {
|
|
2606
|
+
return procVersion.toLowerCase().includes("microsoft");
|
|
2607
|
+
}
|
|
2608
|
+
/** `/proc/version` is immutable for the process lifetime: read it at most once. */
|
|
2609
|
+
let procVersionText;
|
|
2610
|
+
/** Read `/proc/version`, or an empty string wherever the file is absent (Windows, macOS). */
|
|
2611
|
+
function readProcVersion() {
|
|
2612
|
+
if (procVersionText === void 0) try {
|
|
2613
|
+
procVersionText = readFileSync("/proc/version", "utf8");
|
|
2614
|
+
} catch {
|
|
2615
|
+
procVersionText = "";
|
|
2616
|
+
}
|
|
2617
|
+
return procVersionText;
|
|
2618
|
+
}
|
|
2619
|
+
/** Chokidar options that switch one watch to polling (drvfs mount or WSL host). */
|
|
2620
|
+
const POLLING_WATCH_OPTIONS = {
|
|
2621
|
+
usePolling: true,
|
|
2622
|
+
interval: POLLING_WATCH_INTERVAL_MS
|
|
2623
|
+
};
|
|
2624
|
+
/**
|
|
2550
2625
|
* State and behavior. One instance per plugin mount; disposals are owned by
|
|
2551
2626
|
* the watcher/timer/proxy effects registered in {@link apply}.
|
|
2552
2627
|
*/
|
|
@@ -2558,6 +2633,10 @@ var PermissionRulesRuntime = class {
|
|
|
2558
2633
|
compileCache = /* @__PURE__ */ new Map();
|
|
2559
2634
|
/** Live watchers per watched path (rule file or candidate ancestor directory), with the cwds each serves. */
|
|
2560
2635
|
watchers = /* @__PURE__ */ new Map();
|
|
2636
|
+
/** The configured chain session-less proxy connections are judged against (see {@link hostChain}); never a `byCwd` member. */
|
|
2637
|
+
hostLoaded;
|
|
2638
|
+
/** Whether the one-time "configured chain unusable" warning was already logged. */
|
|
2639
|
+
hostChainWarned = false;
|
|
2561
2640
|
/** Debounce timers per rule-file path. */
|
|
2562
2641
|
timers = /* @__PURE__ */ new Map();
|
|
2563
2642
|
/** Whether the host honors the audit envelope's `ignorable` marker: unknown until the first decision (or peer-version check). */
|
|
@@ -3015,8 +3094,44 @@ var PermissionRulesRuntime = class {
|
|
|
3015
3094
|
ruleset: loaded.compiled,
|
|
3016
3095
|
sources: loaded.sources
|
|
3017
3096
|
});
|
|
3097
|
+
if (chains.length === 0) {
|
|
3098
|
+
const host = this.hostChain();
|
|
3099
|
+
if (host !== void 0) chains.push(host);
|
|
3100
|
+
}
|
|
3018
3101
|
return chains;
|
|
3019
3102
|
}
|
|
3103
|
+
/**
|
|
3104
|
+
* The CONFIGURED chain a session-less connection is judged against: the
|
|
3105
|
+
* chain for the host process's own working directory (project rule file →
|
|
3106
|
+
* an absolute `rulesFile` → the configured fallback → the shipped
|
|
3107
|
+
* baseline), loaded on first use. Proxy traffic that carries no session —
|
|
3108
|
+
* the harness's own plugin-market catalog/update/npm lookups at boot — used
|
|
3109
|
+
* to be judged against an empty chain and therefore always hit the mode
|
|
3110
|
+
* default, so a target an already-configured allow rule permits stayed
|
|
3111
|
+
* blocked until some session had run a tool call (issue #18). The chain is
|
|
3112
|
+
* kept OUT of `byCwd` on purpose: it must never outrank a session workspace
|
|
3113
|
+
* chain, and it stops being consulted as soon as one is loaded (a host-level
|
|
3114
|
+
* connection is then judged exactly as before, against the loaded workspace
|
|
3115
|
+
* chains). It is not watched either: the session-less window is the boot
|
|
3116
|
+
* window, and the first tool call of any session takes over with the normal
|
|
3117
|
+
* per-workspace chain, which is watched.
|
|
3118
|
+
* @returns the configured chain, or undefined when it cannot be loaded (the mode default then applies).
|
|
3119
|
+
*/
|
|
3120
|
+
hostChain() {
|
|
3121
|
+
if (this.hostLoaded === void 0) try {
|
|
3122
|
+
this.hostLoaded = this.load(process.cwd());
|
|
3123
|
+
} catch (error) {
|
|
3124
|
+
if (!this.hostChainWarned) {
|
|
3125
|
+
this.hostChainWarned = true;
|
|
3126
|
+
this.ctx.logger.warn(`permission-rules: cannot load the configured rules for session-less connections at ${process.cwd()}: ${String(error)} (the network mode default applies)`);
|
|
3127
|
+
}
|
|
3128
|
+
return;
|
|
3129
|
+
}
|
|
3130
|
+
return {
|
|
3131
|
+
ruleset: this.hostLoaded.compiled,
|
|
3132
|
+
sources: this.hostLoaded.sources
|
|
3133
|
+
};
|
|
3134
|
+
}
|
|
3020
3135
|
/** Mark one delegated shell execution as in-flight (newest attribution wins). */
|
|
3021
3136
|
markShell(exec) {
|
|
3022
3137
|
this.inFlight.set(String(exec.callId), {
|
|
@@ -3534,6 +3649,19 @@ var PermissionRulesRuntime = class {
|
|
|
3534
3649
|
throw error instanceof RuleError ? error : new RuleError(`permission-rules: cannot load ${filePath}: ${message}`);
|
|
3535
3650
|
}
|
|
3536
3651
|
}
|
|
3652
|
+
/**
|
|
3653
|
+
* Whether one watched path must be polled instead of trusting the platform's
|
|
3654
|
+
* change events. WSL is the case issue #19 item 1 reports: a rule file under
|
|
3655
|
+
* `/mnt/<drive>` (drvfs/9p) or any file on a WSL host can stop delivering
|
|
3656
|
+
* chokidar change events with no error at all, so the watcher edits would
|
|
3657
|
+
* silently stop hot-reloading. Polling is the documented chokidar remedy;
|
|
3658
|
+
* everywhere else the native watcher stays in place.
|
|
3659
|
+
* @param path - the watched rule file or candidate directory.
|
|
3660
|
+
* @returns true when the watch should run in polling mode.
|
|
3661
|
+
*/
|
|
3662
|
+
watchPollingFor(path) {
|
|
3663
|
+
return isDvrfsPath(path) || isWslKernel(readProcVersion());
|
|
3664
|
+
}
|
|
3537
3665
|
/** Attach (once per file path) the Chokidar watcher feeding {@link reload}. */
|
|
3538
3666
|
attachWatch(cwd, source) {
|
|
3539
3667
|
if (!this.config.watch || source === "" || this.config.builtin.enabled && source === this.config.builtin.path) return;
|
|
@@ -3543,9 +3671,11 @@ var PermissionRulesRuntime = class {
|
|
|
3543
3671
|
return;
|
|
3544
3672
|
}
|
|
3545
3673
|
const cwds = /* @__PURE__ */ new Set([cwd]);
|
|
3674
|
+
const polling = this.watchPollingFor(source);
|
|
3546
3675
|
const watcher = chokidar.watch(source, {
|
|
3547
3676
|
persistent: true,
|
|
3548
|
-
ignoreInitial: true
|
|
3677
|
+
ignoreInitial: true,
|
|
3678
|
+
...polling ? POLLING_WATCH_OPTIONS : {}
|
|
3549
3679
|
});
|
|
3550
3680
|
const onEvent = () => this.scheduleReload(source);
|
|
3551
3681
|
watcher.on("add", onEvent);
|
|
@@ -3641,6 +3771,7 @@ var PermissionRulesRuntime = class {
|
|
|
3641
3771
|
const watchOptions = {
|
|
3642
3772
|
persistent: true,
|
|
3643
3773
|
ignoreInitial: true,
|
|
3774
|
+
...this.watchPollingFor(candidate) ? POLLING_WATCH_OPTIONS : {},
|
|
3644
3775
|
ignored: (path) => path.split(sep).includes("node_modules") || path.split(sep).includes(".git")
|
|
3645
3776
|
};
|
|
3646
3777
|
const watcher = dir === parent ? chokidar.watch(dir, watchOptions) : chokidar.watch(dir, {
|
package/lib/types/proxy.d.ts
CHANGED
|
@@ -101,9 +101,18 @@ export declare class NetworkProxy {
|
|
|
101
101
|
private handleRequest;
|
|
102
102
|
/**
|
|
103
103
|
* Connect to the first adjudicated address that accepts, so the tunnel lands
|
|
104
|
-
* on an address the decision approved
|
|
105
|
-
*
|
|
106
|
-
*
|
|
104
|
+
* on an address the decision approved. Each candidate is tried in order so a
|
|
105
|
+
* multi-address host does not lose its fallback.
|
|
106
|
+
*
|
|
107
|
+
* A target whose adjudication resolved no address FAILS here instead of
|
|
108
|
+
* dialing the hostname (issue #21): dialing the name would be a second DNS
|
|
109
|
+
* resolution — the answer could differ from the one the rules were evaluated
|
|
110
|
+
* against — and it is the one remaining path where Node's happy-eyeballs
|
|
111
|
+
* race applies, with its 250 ms `autoSelectFamilyAttemptTimeout` default
|
|
112
|
+
* that kills any endpoint further away than that. Dialing an already-
|
|
113
|
+
* resolved literal skips that algorithm entirely (net.js connects an IP
|
|
114
|
+
* without a lookup), so the tunnel only ever reaches an adjudicated
|
|
115
|
+
* address; the client's retry resolves and adjudicates again.
|
|
107
116
|
*/
|
|
108
117
|
private connectUpstream;
|
|
109
118
|
/** CONNECT tunneling (HTTPS and friends): adjudicate, then either 403 or an established TCP tunnel. */
|
package/lib/types/proxy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/proxy.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/proxy.ts"],"names":[],"mappings":"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"}
|
package/lib/types/rules.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/rules.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/rules.ts"],"names":[],"mappings":"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"}
|
package/lib/types/runtime.d.ts
CHANGED
|
@@ -33,6 +33,26 @@ interface LoadedRules {
|
|
|
33
33
|
/** `true` when the last initial load threw under `badFilePolicy: 'fail'`. */
|
|
34
34
|
readonly failed?: true;
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Whether one watched path lies under a WSL drvfs mount (`/mnt/<drive>/…`),
|
|
38
|
+
* where inotify-style change events are known to be unreliable — chokidar
|
|
39
|
+
* then has to poll (issue #19 item 1). The separator is normalized first so
|
|
40
|
+
* the check also recognizes the path as the Windows side spells it; a
|
|
41
|
+
* Windows drive path (`D:\…`) never matches.
|
|
42
|
+
* @param path - the watched file or directory path.
|
|
43
|
+
* @returns true when the path addresses a drvfs mount.
|
|
44
|
+
*/
|
|
45
|
+
export declare function isDvrfsPath(path: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Whether the running kernel is WSL's, as `/proc/version` reports it. Every
|
|
48
|
+
* WSL kernel string carries `microsoft` (`…-microsoft-standard-WSL2`), which
|
|
49
|
+
* is what the issue asks the detection to key on; a non-WSL Linux kernel
|
|
50
|
+
* never does, and hosts without `/proc/version` (Windows, macOS) answer
|
|
51
|
+
* false.
|
|
52
|
+
* @param procVersion - the `/proc/version` text, or an empty string when it cannot be read.
|
|
53
|
+
* @returns true when the kernel is Microsoft's.
|
|
54
|
+
*/
|
|
55
|
+
export declare function isWslKernel(procVersion: string): boolean;
|
|
36
56
|
/**
|
|
37
57
|
* State and behavior. One instance per plugin mount; disposals are owned by
|
|
38
58
|
* the watcher/timer/proxy effects registered in {@link apply}.
|
|
@@ -45,6 +65,10 @@ export declare class PermissionRulesRuntime {
|
|
|
45
65
|
private readonly compileCache;
|
|
46
66
|
/** Live watchers per watched path (rule file or candidate ancestor directory), with the cwds each serves. */
|
|
47
67
|
private readonly watchers;
|
|
68
|
+
/** The configured chain session-less proxy connections are judged against (see {@link hostChain}); never a `byCwd` member. */
|
|
69
|
+
private hostLoaded;
|
|
70
|
+
/** Whether the one-time "configured chain unusable" warning was already logged. */
|
|
71
|
+
private hostChainWarned;
|
|
48
72
|
/** Debounce timers per rule-file path. */
|
|
49
73
|
private readonly timers;
|
|
50
74
|
/** Whether the host honors the audit envelope's `ignorable` marker: unknown until the first decision (or peer-version check). */
|
|
@@ -222,6 +246,24 @@ export declare class PermissionRulesRuntime {
|
|
|
222
246
|
private decideProxyTarget;
|
|
223
247
|
/** The loaded rule chains in cache order, nearest workspace first. */
|
|
224
248
|
private proxyChains;
|
|
249
|
+
/**
|
|
250
|
+
* The CONFIGURED chain a session-less connection is judged against: the
|
|
251
|
+
* chain for the host process's own working directory (project rule file →
|
|
252
|
+
* an absolute `rulesFile` → the configured fallback → the shipped
|
|
253
|
+
* baseline), loaded on first use. Proxy traffic that carries no session —
|
|
254
|
+
* the harness's own plugin-market catalog/update/npm lookups at boot — used
|
|
255
|
+
* to be judged against an empty chain and therefore always hit the mode
|
|
256
|
+
* default, so a target an already-configured allow rule permits stayed
|
|
257
|
+
* blocked until some session had run a tool call (issue #18). The chain is
|
|
258
|
+
* kept OUT of `byCwd` on purpose: it must never outrank a session workspace
|
|
259
|
+
* chain, and it stops being consulted as soon as one is loaded (a host-level
|
|
260
|
+
* connection is then judged exactly as before, against the loaded workspace
|
|
261
|
+
* chains). It is not watched either: the session-less window is the boot
|
|
262
|
+
* window, and the first tool call of any session takes over with the normal
|
|
263
|
+
* per-workspace chain, which is watched.
|
|
264
|
+
* @returns the configured chain, or undefined when it cannot be loaded (the mode default then applies).
|
|
265
|
+
*/
|
|
266
|
+
private hostChain;
|
|
225
267
|
/** Mark one delegated shell execution as in-flight (newest attribution wins). */
|
|
226
268
|
private markShell;
|
|
227
269
|
/** Drop one shell execution when it settles. */
|
|
@@ -344,6 +386,17 @@ export declare class PermissionRulesRuntime {
|
|
|
344
386
|
validateDeploymentFiles(): void;
|
|
345
387
|
/** Parse and compile one mandated file, rethrowing as a mount failure. */
|
|
346
388
|
private loadForValidation;
|
|
389
|
+
/**
|
|
390
|
+
* Whether one watched path must be polled instead of trusting the platform's
|
|
391
|
+
* change events. WSL is the case issue #19 item 1 reports: a rule file under
|
|
392
|
+
* `/mnt/<drive>` (drvfs/9p) or any file on a WSL host can stop delivering
|
|
393
|
+
* chokidar change events with no error at all, so the watcher edits would
|
|
394
|
+
* silently stop hot-reloading. Polling is the documented chokidar remedy;
|
|
395
|
+
* everywhere else the native watcher stays in place.
|
|
396
|
+
* @param path - the watched rule file or candidate directory.
|
|
397
|
+
* @returns true when the watch should run in polling mode.
|
|
398
|
+
*/
|
|
399
|
+
watchPollingFor(path: string): boolean;
|
|
347
400
|
/** Attach (once per file path) the Chokidar watcher feeding {@link reload}. */
|
|
348
401
|
private attachWatch;
|
|
349
402
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAG5E,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAGzD,OAAO,KAAK,EAAgC,eAAe,EAA+B,OAAO,EAAE,MAAM,YAAY,CAAA;AAIrH,OAAO,KAAK,EAAiC,WAAW,EAAE,MAAM,cAAc,CAAA;AAQ9E,OAAO,KAAK,EAAE,kBAAkB,EAAoB,MAAM,YAAY,CAAA;AAItE,OAAO,KAAK,EAAiD,eAAe,EAAE,MAAM,aAAa,CAAA;AAEjG,eAAO,MAAM,IAAI,qBAAqB,CAAA;AAEtC,kDAAkD;AAClD,eAAO,MAAM,MAAM,UAAwB,CAAA;AAE3C,iDAAiD;AACjD,UAAU,WAAW;IACnB,wDAAwD;IACxD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,wFAAwF;IACxF,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAA;IAClC,iGAAiG;IACjG,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAA;CACvB;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-permission-rules",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.20",
|
|
4
4
|
"description": "Declarative Claude Code-style permission rules plus a Codex-style process-level network policy for DeepSeek Harness: ordered allow/deny/ask rules with tool-name, argument (glob/regex), workspace-path, and network-target (domain/ip/port/scheme) matching on the tools/pre-execute waterfall, a built-in local HTTP/CONNECT proxy governing shell subprocess traffic, three network modes mapped onto the official sandbox presets, full session-log audit, HMR rule reload, and a settings page with a rule editor, block counters, and recent interception lists.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
package/src/proxy.ts
CHANGED
|
@@ -199,13 +199,22 @@ export class NetworkProxy {
|
|
|
199
199
|
|
|
200
200
|
/**
|
|
201
201
|
* Connect to the first adjudicated address that accepts, so the tunnel lands
|
|
202
|
-
* on an address the decision approved
|
|
203
|
-
*
|
|
204
|
-
*
|
|
202
|
+
* on an address the decision approved. Each candidate is tried in order so a
|
|
203
|
+
* multi-address host does not lose its fallback.
|
|
204
|
+
*
|
|
205
|
+
* A target whose adjudication resolved no address FAILS here instead of
|
|
206
|
+
* dialing the hostname (issue #21): dialing the name would be a second DNS
|
|
207
|
+
* resolution — the answer could differ from the one the rules were evaluated
|
|
208
|
+
* against — and it is the one remaining path where Node's happy-eyeballs
|
|
209
|
+
* race applies, with its 250 ms `autoSelectFamilyAttemptTimeout` default
|
|
210
|
+
* that kills any endpoint further away than that. Dialing an already-
|
|
211
|
+
* resolved literal skips that algorithm entirely (net.js connects an IP
|
|
212
|
+
* without a lookup), so the tunnel only ever reaches an adjudicated
|
|
213
|
+
* address; the client's retry resolves and adjudicates again.
|
|
205
214
|
*/
|
|
206
215
|
private async connectUpstream(target: NetworkTarget, port: number): Promise<Duplex> {
|
|
207
216
|
const pinned = pinnedAddresses(target)
|
|
208
|
-
if (pinned.length === 0)
|
|
217
|
+
if (pinned.length === 0) throw new Error(`no adjudicated address for ${target.host}`)
|
|
209
218
|
let lastError: unknown
|
|
210
219
|
for (const address of pinned) {
|
|
211
220
|
try {
|
package/src/rules.ts
CHANGED
|
@@ -291,7 +291,7 @@ export interface MatchContext {
|
|
|
291
291
|
* @returns the validated document.
|
|
292
292
|
*/
|
|
293
293
|
export function parseRulesDocument(text: string): RulesFileDoc {
|
|
294
|
-
const parsed = parseYaml(text)
|
|
294
|
+
const parsed = parseYaml(normalizeLineEndings(text))
|
|
295
295
|
// An empty (or comment-only) file is a valid empty rule set.
|
|
296
296
|
if (parsed === null || parsed === undefined) return { rules: [] }
|
|
297
297
|
const root = asRecord(parsed, 'rules document root')
|
|
@@ -714,6 +714,26 @@ function compileParamPatterns(key: string, patterns: readonly string[], options:
|
|
|
714
714
|
|
|
715
715
|
// --- YAML/shape validation -------------------------------------------------
|
|
716
716
|
|
|
717
|
+
/**
|
|
718
|
+
* Normalize the line endings of one rule-file body before parsing. A file
|
|
719
|
+
* authored or checked out on the Windows side arrives with CRLF, and a lone
|
|
720
|
+
* CR — one not paired with an LF — is NOT a line break to the YAML parser in
|
|
721
|
+
* every position: it survives into the scalar it terminates, so a pattern
|
|
722
|
+
* spelled `domains: [registry.npmjs.org<CR>]`, or a final line ending in a
|
|
723
|
+
* bare CR, compiled a pattern that could never match its target (issue #19
|
|
724
|
+
* item 4). CRLF becomes LF; a stray CR inside a line is dropped (it is junk
|
|
725
|
+
* there — a deliberate CR is written as the YAML escape `\r` and never
|
|
726
|
+
* reaches this text); and a CR-only file (classic Mac line endings, no LF
|
|
727
|
+
* anywhere) treats every CR as its line separator. Every line-ending style
|
|
728
|
+
* therefore parses to the same document.
|
|
729
|
+
* @param text - the raw rule-file text.
|
|
730
|
+
* @returns the same text with LF line breaks and no stray CR.
|
|
731
|
+
*/
|
|
732
|
+
function normalizeLineEndings(text: string): string {
|
|
733
|
+
if (!text.includes('\n')) return text.replace(/\r/g, '\n')
|
|
734
|
+
return text.replace(/\r\n/g, '\n').replace(/\r/g, '')
|
|
735
|
+
}
|
|
736
|
+
|
|
717
737
|
/** Parse YAML through the `yaml` dependency, mapping parse failures onto {@link RuleError}. */
|
|
718
738
|
function parseYaml(text: string): unknown {
|
|
719
739
|
try {
|
package/src/runtime.ts
CHANGED
|
@@ -81,6 +81,58 @@ const WEB_TOOLS: readonly string[] = ['web_fetch', 'web_search']
|
|
|
81
81
|
/** Stale in-flight entries are dropped after this many milliseconds (attribution is best-effort). */
|
|
82
82
|
const IN_FLIGHT_TTL_MS = 10 * 60 * 1000
|
|
83
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Chokidar polling interval used when the watched path lives on a filesystem
|
|
86
|
+
* whose change events are unreliable (WSL drvfs/9p mounts): polling costs a
|
|
87
|
+
* stat per interval, which is negligible for a rule file and far cheaper than
|
|
88
|
+
* a rule edit that silently never hot-reloads.
|
|
89
|
+
*/
|
|
90
|
+
const POLLING_WATCH_INTERVAL_MS = 300
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Whether one watched path lies under a WSL drvfs mount (`/mnt/<drive>/…`),
|
|
94
|
+
* where inotify-style change events are known to be unreliable — chokidar
|
|
95
|
+
* then has to poll (issue #19 item 1). The separator is normalized first so
|
|
96
|
+
* the check also recognizes the path as the Windows side spells it; a
|
|
97
|
+
* Windows drive path (`D:\…`) never matches.
|
|
98
|
+
* @param path - the watched file or directory path.
|
|
99
|
+
* @returns true when the path addresses a drvfs mount.
|
|
100
|
+
*/
|
|
101
|
+
export function isDvrfsPath(path: string): boolean {
|
|
102
|
+
return /^\/mnt\/[a-z](?:\/|$)/i.test(path.replace(/\\/g, '/'))
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Whether the running kernel is WSL's, as `/proc/version` reports it. Every
|
|
107
|
+
* WSL kernel string carries `microsoft` (`…-microsoft-standard-WSL2`), which
|
|
108
|
+
* is what the issue asks the detection to key on; a non-WSL Linux kernel
|
|
109
|
+
* never does, and hosts without `/proc/version` (Windows, macOS) answer
|
|
110
|
+
* false.
|
|
111
|
+
* @param procVersion - the `/proc/version` text, or an empty string when it cannot be read.
|
|
112
|
+
* @returns true when the kernel is Microsoft's.
|
|
113
|
+
*/
|
|
114
|
+
export function isWslKernel(procVersion: string): boolean {
|
|
115
|
+
return procVersion.toLowerCase().includes('microsoft')
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** `/proc/version` is immutable for the process lifetime: read it at most once. */
|
|
119
|
+
let procVersionText: string | undefined
|
|
120
|
+
|
|
121
|
+
/** Read `/proc/version`, or an empty string wherever the file is absent (Windows, macOS). */
|
|
122
|
+
function readProcVersion(): string {
|
|
123
|
+
if (procVersionText === undefined) {
|
|
124
|
+
try {
|
|
125
|
+
procVersionText = readFileSync('/proc/version', 'utf8')
|
|
126
|
+
} catch {
|
|
127
|
+
procVersionText = ''
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return procVersionText
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Chokidar options that switch one watch to polling (drvfs mount or WSL host). */
|
|
134
|
+
const POLLING_WATCH_OPTIONS = { usePolling: true, interval: POLLING_WATCH_INTERVAL_MS } as const
|
|
135
|
+
|
|
84
136
|
/**
|
|
85
137
|
* State and behavior. One instance per plugin mount; disposals are owned by
|
|
86
138
|
* the watcher/timer/proxy effects registered in {@link apply}.
|
|
@@ -95,6 +147,12 @@ export class PermissionRulesRuntime {
|
|
|
95
147
|
/** Live watchers per watched path (rule file or candidate ancestor directory), with the cwds each serves. */
|
|
96
148
|
private readonly watchers = new Map<string, WatcherEntry>()
|
|
97
149
|
|
|
150
|
+
/** The configured chain session-less proxy connections are judged against (see {@link hostChain}); never a `byCwd` member. */
|
|
151
|
+
private hostLoaded: LoadedRules | undefined
|
|
152
|
+
|
|
153
|
+
/** Whether the one-time "configured chain unusable" warning was already logged. */
|
|
154
|
+
private hostChainWarned = false
|
|
155
|
+
|
|
98
156
|
/** Debounce timers per rule-file path. */
|
|
99
157
|
private readonly timers = new Map<string, ReturnType<typeof setTimeout>>()
|
|
100
158
|
|
|
@@ -525,9 +583,47 @@ export class PermissionRulesRuntime {
|
|
|
525
583
|
for (const loaded of this.byCwd.values()) {
|
|
526
584
|
chains.push({ ruleset: loaded.compiled, sources: loaded.sources })
|
|
527
585
|
}
|
|
586
|
+
if (chains.length === 0) {
|
|
587
|
+
const host = this.hostChain()
|
|
588
|
+
if (host !== undefined) chains.push(host)
|
|
589
|
+
}
|
|
528
590
|
return chains
|
|
529
591
|
}
|
|
530
592
|
|
|
593
|
+
/**
|
|
594
|
+
* The CONFIGURED chain a session-less connection is judged against: the
|
|
595
|
+
* chain for the host process's own working directory (project rule file →
|
|
596
|
+
* an absolute `rulesFile` → the configured fallback → the shipped
|
|
597
|
+
* baseline), loaded on first use. Proxy traffic that carries no session —
|
|
598
|
+
* the harness's own plugin-market catalog/update/npm lookups at boot — used
|
|
599
|
+
* to be judged against an empty chain and therefore always hit the mode
|
|
600
|
+
* default, so a target an already-configured allow rule permits stayed
|
|
601
|
+
* blocked until some session had run a tool call (issue #18). The chain is
|
|
602
|
+
* kept OUT of `byCwd` on purpose: it must never outrank a session workspace
|
|
603
|
+
* chain, and it stops being consulted as soon as one is loaded (a host-level
|
|
604
|
+
* connection is then judged exactly as before, against the loaded workspace
|
|
605
|
+
* chains). It is not watched either: the session-less window is the boot
|
|
606
|
+
* window, and the first tool call of any session takes over with the normal
|
|
607
|
+
* per-workspace chain, which is watched.
|
|
608
|
+
* @returns the configured chain, or undefined when it cannot be loaded (the mode default then applies).
|
|
609
|
+
*/
|
|
610
|
+
private hostChain(): NetworkChain | undefined {
|
|
611
|
+
if (this.hostLoaded === undefined) {
|
|
612
|
+
try {
|
|
613
|
+
this.hostLoaded = this.load(process.cwd())
|
|
614
|
+
} catch (error: unknown) {
|
|
615
|
+
// Never throw into the proxy: an unusable configured chain degrades to
|
|
616
|
+
// the mode default (fail closed), with one warning per mount.
|
|
617
|
+
if (!this.hostChainWarned) {
|
|
618
|
+
this.hostChainWarned = true
|
|
619
|
+
this.ctx.logger.warn(`permission-rules: cannot load the configured rules for session-less connections at ${process.cwd()}: ${String(error)} (the network mode default applies)`)
|
|
620
|
+
}
|
|
621
|
+
return undefined
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
return { ruleset: this.hostLoaded.compiled, sources: this.hostLoaded.sources }
|
|
625
|
+
}
|
|
626
|
+
|
|
531
627
|
/** Mark one delegated shell execution as in-flight (newest attribution wins). */
|
|
532
628
|
private markShell(exec: ToolExecution): void {
|
|
533
629
|
this.inFlight.set(String(exec.callId), { tool: exec.name, callId: exec.callId, startedAt: Date.now(), agent: exec.agent })
|
|
@@ -1014,6 +1110,20 @@ export class PermissionRulesRuntime {
|
|
|
1014
1110
|
}
|
|
1015
1111
|
}
|
|
1016
1112
|
|
|
1113
|
+
/**
|
|
1114
|
+
* Whether one watched path must be polled instead of trusting the platform's
|
|
1115
|
+
* change events. WSL is the case issue #19 item 1 reports: a rule file under
|
|
1116
|
+
* `/mnt/<drive>` (drvfs/9p) or any file on a WSL host can stop delivering
|
|
1117
|
+
* chokidar change events with no error at all, so the watcher edits would
|
|
1118
|
+
* silently stop hot-reloading. Polling is the documented chokidar remedy;
|
|
1119
|
+
* everywhere else the native watcher stays in place.
|
|
1120
|
+
* @param path - the watched rule file or candidate directory.
|
|
1121
|
+
* @returns true when the watch should run in polling mode.
|
|
1122
|
+
*/
|
|
1123
|
+
watchPollingFor(path: string): boolean {
|
|
1124
|
+
return isDvrfsPath(path) || isWslKernel(readProcVersion())
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1017
1127
|
/** Attach (once per file path) the Chokidar watcher feeding {@link reload}. */
|
|
1018
1128
|
private attachWatch(cwd: string, source: string): void {
|
|
1019
1129
|
if (!this.config.watch || source === '' || (this.config.builtin.enabled && source === this.config.builtin.path)) return
|
|
@@ -1023,7 +1133,8 @@ export class PermissionRulesRuntime {
|
|
|
1023
1133
|
return
|
|
1024
1134
|
}
|
|
1025
1135
|
const cwds = new Set([cwd])
|
|
1026
|
-
const
|
|
1136
|
+
const polling = this.watchPollingFor(source)
|
|
1137
|
+
const watcher = chokidar.watch(source, { persistent: true, ignoreInitial: true, ...(polling ? POLLING_WATCH_OPTIONS : {}) })
|
|
1027
1138
|
const onEvent = (): void => this.scheduleReload(source)
|
|
1028
1139
|
watcher.on('add', onEvent)
|
|
1029
1140
|
watcher.on('change', onEvent)
|
|
@@ -1120,9 +1231,11 @@ export class PermissionRulesRuntime {
|
|
|
1120
1231
|
}
|
|
1121
1232
|
const cwds = new Set([cwd])
|
|
1122
1233
|
const candidates = new Map([[cwd, candidate]])
|
|
1234
|
+
const polling = this.watchPollingFor(candidate)
|
|
1123
1235
|
const watchOptions = {
|
|
1124
1236
|
persistent: true,
|
|
1125
1237
|
ignoreInitial: true,
|
|
1238
|
+
...(polling ? POLLING_WATCH_OPTIONS : {}),
|
|
1126
1239
|
ignored: (path: string): boolean => path.split(sep).includes('node_modules') || path.split(sep).includes('.git'),
|
|
1127
1240
|
}
|
|
1128
1241
|
const watcher = dir === parent
|