fix(central-ui): resolve CentralUI-001 — enforce script trust model before sandbox execution
ScriptAnalysisService.RunInSandboxAsync compiled and executed arbitrary user C# in the central host process with no trust-model enforcement — the forbidden-API set was only a Monaco editor diagnostic. A Design-role user could run System.IO/Process/Reflection/network code on the central node. Added a Roslyn semantic gate (EnforceTrustModel) invoked after compilation and before script.RunAsync, and on nested shared scripts in callSharedFunc; a script referencing any forbidden API is rejected before it runs. Reworked FindForbiddenApiUsages: it now resolves every identifier against the semantic model and checks types and members, so a fully-qualified call (System.IO.File.WriteAllText) is caught — the pre-fix check only inspected the leftmost identifier and missed that shape. This is a static semantic gate, not a process sandbox. Adds gate regression tests that fail against the pre-fix code, plus a clean-script test guarding against over-blocking.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
| Last reviewed | 2026-05-16 |
|
||||
| Reviewer | claude-agent |
|
||||
| Commit reviewed | `9c60592` |
|
||||
| Open findings | 19 |
|
||||
| Open findings | 18 |
|
||||
|
||||
## Summary
|
||||
|
||||
@@ -55,7 +55,7 @@ pages and the auth bridge are untested.
|
||||
|--|--|
|
||||
| Severity | Critical |
|
||||
| Category | Security |
|
||||
| Status | Open |
|
||||
| Status | Resolved |
|
||||
| Location | `src/ScadaLink.CentralUI/ScriptAnalysis/ScriptAnalysisService.cs:171-424` |
|
||||
|
||||
**Description**
|
||||
@@ -85,7 +85,22 @@ an editor hint.
|
||||
|
||||
**Resolution**
|
||||
|
||||
_Unresolved._
|
||||
Resolved 2026-05-16. A Roslyn semantic trust-model gate was added. `RunInSandboxAsync`
|
||||
now calls `EnforceTrustModel` after compilation and before `script.RunAsync`; if the
|
||||
script references any forbidden API the run is rejected (`SandboxErrorKind.CompileError`)
|
||||
with the offending markers, and the same gate is applied to nested shared scripts in
|
||||
`callSharedFunc`. `FindForbiddenApiUsages` was reworked so it resolves every identifier
|
||||
(not just the leftmost) against the semantic model and checks types **and** members —
|
||||
so a fully-qualified call such as `System.IO.File.WriteAllText(...)` is now caught, not
|
||||
only `using`-directive or bare-type forms. This is a static semantic gate consistent
|
||||
with the documented trust model; it is not a process sandbox — reflection-based
|
||||
indirection remains out of its reach, and full isolation would require running scripts
|
||||
in a separate constrained process (a larger change deliberately not taken here).
|
||||
Regression tests `RunInSandbox_FullyQualifiedForbiddenApi_IsBlockedBeforeExecution`,
|
||||
`RunInSandbox_ForbiddenUsingDirective_IsBlockedBeforeExecution` and
|
||||
`Diagnose_FullyQualifiedForbiddenCall_RaisesSCADA002` fail against the pre-fix code and
|
||||
pass after; `RunInSandbox_CleanScript_StillRuns` guards against over-blocking. Fixed by
|
||||
the commit whose message references `CentralUI-001`.
|
||||
|
||||
### CentralUI-002 — Site-scoped Deployment permissions are issued but never enforced
|
||||
|
||||
|
||||
Reference in New Issue
Block a user