Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ Standard-Invocations (`dotnet build|test`, in `src/nodepilot-ui` die `package.js

**Der Nightly ist kein verlässlicher zweiter Boden.** Er läuft als Windows-Task um 22:00 gegen den ausgecheckten Baum und wird verpasst, sobald die Maschine dann aus ist. Wer sich auf ihn beruft, prüft vorher `C:\temp\nodepilot-nightly\latest.md` auf sein Datum.

**Markdown-Ausnahme:** Ein PR, der **ausschließlich** `*.md` oder `docs/images/**` anfasst, überspringt Frontend, Desktop und E2E (`changes`-Job). **Backend und docs-ui laufen immer**, weil Markdown für sie eine Eingabe ist (`DocumentationCountsTests`, `SettingsSchemaDocumentationTests`, `MonitoringDeploymentSecurityTests`, Sprach-Parity-Guard). Pushes auf `main` laufen **immer** vollständig; jeder Fehlerpfad der Erkennung endet bei „alles ausführen".
**Markdown-Ausnahme:** Ein PR, der **ausschließlich** `*.md` oder `docs/images/**` anfasst, überspringt Frontend, Desktop, Database und E2E (`changes`-Job). **Backend und docs-ui laufen immer**, weil Markdown für sie eine Eingabe ist (`DocumentationCountsTests`, `SettingsSchemaDocumentationTests`, `MonitoringDeploymentSecurityTests`, Sprach-Parity-Guard). Pushes auf `main` laufen **immer** vollständig; jeder Fehlerpfad der Erkennung endet bei „alles ausführen".

Default bei Feature-Arbeit:

Expand Down
2 changes: 1 addition & 1 deletion docs/claude-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1046,7 +1046,7 @@ Die Guard-Flags sind **hardened by default**: appsettings.json shippt sie als `t
|---|---|---|
| `Remote:RequireWinRmSsl` | `true` | WinRM ohne SSL → Exception (Dev: `false`) |
| `RestApi:BlockPrivateNetworks` | `true` | Blockiert RFC1918/Loopback in `restApi` (Dev: `false`) |
| `RestApi:AllowedHosts` | `[]` | Exakte Host-/IP-Allow-Liste für tatsächlich proxied `restApi`-Ziele/Redirects — die Ausnahme von `BlockPrivateNetworks`. Link-Local/Cloud-Metadata bleibt immer gesperrt (Dev: `localhost`/`127.0.0.1`/`::1`). **Die Sperre gilt der Adresse, nicht dem Namen:** löst ein Host auf mehrere Adressen auf, genügt **eine** brauchbare (`NetworkGuard.AssertAnyAddressUsable`) — ein domänengebundener Windows-Host registriert seine IPv6-Link-Local-Adressen neben den routbaren im DNS und wäre sonst dauerhaft unerreichbar, ohne Möglichkeit ihn freizuschalten. Verbunden wird trotzdem nie zu einer gesperrten Adresse: `EnforceConnect` wendet dieselbe Regel im `ConnectCallback` pro Adresse an und öffnet den Socket nur zu einer, die dort überlebt |
| `RestApi:AllowedHosts` | `[]` | Exakte Host-/IP-Allow-Liste für tatsächlich proxied `restApi`-Ziele/Redirects — die Ausnahme von `BlockPrivateNetworks`. Link-Local/Cloud-Metadata bleibt immer gesperrt (Dev: `localhost`/`127.0.0.1`/`::1`). **Die Sperre gilt der Adresse, nicht dem Namen:** löst ein Host auf mehrere Adressen auf, genügt bei einem **direkt** verbundenen Ziel **eine** brauchbare (`NetworkGuard.AssertAddressesUsable`) — ein domänengebundener Windows-Host registriert seine IPv6-Link-Local-Adressen neben den routbaren im DNS und wäre sonst dauerhaft unerreichbar, ohne Möglichkeit ihn freizuschalten. Verbunden wird trotzdem nie zu einer gesperrten Adresse: `EnforceConnect` wendet dieselbe Regel im `ConnectCallback` pro Adresse an und öffnet den Socket nur zu einer, die dort überlebt. **Läuft das Ziel über einen Proxy, müssen alle aufgelösten Adressen passieren** (`requireAllAddresses`, gesetzt von `RestApiHttpClientProvider.UsesProxyForDestination`): der Proxy löst das Ziel-DNS selbst auf, `EnforceConnect` sieht die Ziel-Adressen nie, und diese Vorprüfung ist damit der einzige verbliebene Adressfilter |
| `WaitForCondition:AllowedHosts` | `["localhost"]` | **Eigene** Liste für die PowerShell-Probes `portOpen`/`httpOk`. Diese können das Ziel beim Connect nicht erneut prüfen (kein `ConnectCallback`), akzeptieren deshalb nur exakt gelistete Hosts; leere Liste lehnt jede Probe ab. Bewusst getrennt von `RestApi:AllowedHosts`, damit „eigenen Dienst prüfen" nicht zugleich `restApi` zu Loopback öffnet — dessen URLs können aus Trigger-Payloads stammen. **Alleinige Autorität für beide Probe-Typen:** `httpOk` lief bis 2026-08-07 zusätzlich durch `NetworkGuard.ValidateUrl` (den restApi-SSRF-Guard) und war damit auf Loopback/RFC1918 unabhängig von dieser Liste blockiert — der ausgelieferte `localhost`-Default war auf jeder Nicht-Dev-Instanz wirkungslos und die Fehlermeldung nannte den falschen Key (`RestApi:BlockPrivateNetworks`, dazu restart-pflichtig). Heute prüft `NetworkGuard.ValidateProbeUrl` nur URL-Form, Scheme und diese Liste. Link-Local/Cloud-Metadata bleibt für beide Typen ungeachtet der Liste gesperrt. Vergleich exakt: `127.0.0.1` deckt `localhost` nicht ab (Dev: alle drei Schreibweisen) |
| `FileSystemOperation:RejectTraversal` | `true` | Lehnt `..` in File-System-Op-Paths ab (Dev: `false`). Zusammen mit `FileSystemOperation:AllowedRoots` (Root-Containment + Reparse-Point-Sperre, aktiv auch bei leerer Root-Liste) gilt die Prüfung **zweimal**: lokal in `PathGuard` und noch einmal im PowerShell-Kontext des tatsächlichen WinRM-Ziels (`TargetPathGuardScript`, injiziert von den pfadführenden Activities `fileOperation`/`folderOperation`, `textFileEdit`, `fileHash`, `zipOperation`, `startProgram`). Ein nicht-leerer konfigurierter Root muss auf dem Ziel existieren, sonst schlägt der Step fehl |
| `SqlActivity:RequireConnectionRef` | `true` | Nur benannte `connectionRef` statt inline `connectionString` (Dev: `false`) |
Expand Down
Loading