@argszero/cordis-plugin-sandbox-grant-advisor 0.10.0 → 0.12.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.
- package/README.md +192 -25
- package/cordis.patch.yml +46 -2
- package/lib/advice.js +198 -8
- package/lib/index.js +128 -24
- package/lib/mode.js +60 -8
- package/lib/signature.js +202 -1
- package/lib/types/advice.d.ts +56 -3
- package/lib/types/index.d.ts +48 -9
- package/lib/types/mode.d.ts +34 -0
- package/lib/types/signature.d.ts +189 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# @argszero/cordis-plugin-sandbox-grant-advisor
|
|
2
2
|
|
|
3
3
|
Turns a sandbox environment failure that has **no path forward** into a
|
|
4
|
-
diagnosis the model — and the user reading the transcript — can act on.
|
|
4
|
+
diagnosis the model — and the user reading the transcript — can act on. Four
|
|
5
5
|
signatures, one mechanism:
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
SetNamedSecurityInfoW failed (Win32 5): grantWrite(D:\ws) # Windows workspace ACL
|
|
9
9
|
PTY shell exited during startup # persistent shell × confining mode
|
|
10
10
|
[exit code: -1073741502] (0xC0000142) # a confined child that never started
|
|
11
|
+
[exit code: 1] sandbox: { mode: "workspace-write", denied: true }
|
|
12
|
+
# denied INSIDE the workspace
|
|
11
13
|
```
|
|
12
14
|
|
|
13
15
|
**This plugin is the stopgap for "the error does not name the outstanding
|
|
@@ -15,7 +17,7 @@ condition".** It repairs nothing: no ACL is written, no privilege is requested,
|
|
|
15
17
|
nothing is elevated, no environment variable is set for another process, no
|
|
16
18
|
preset is installed and no mode is changed.
|
|
17
19
|
|
|
18
|
-
## The
|
|
20
|
+
## The four failures it recognizes
|
|
19
21
|
|
|
20
22
|
The first two are recognized on the public **`tools/post-execute`** waterfall
|
|
21
23
|
(`@deepseek-ai/dsh-tools`) from the failure text. That seam is the one that has
|
|
@@ -24,9 +26,9 @@ all three of what a diagnosis needs: the failure
|
|
|
24
26
|
`isError` result), an agent identity to attribute it to (`exec.agent`), and a
|
|
25
27
|
channel that speaks to the model in the same step (`PostToolDecision`'s
|
|
26
28
|
`additionalContexts`, which the agent loop turns into a durable user-role message
|
|
27
|
-
— `packages/core/agent-loop/src/tool-calls.ts`). The third
|
|
28
|
-
**same seam** from the canonical value of a result the pipeline
|
|
29
|
-
*success*, for
|
|
29
|
+
— `packages/core/agent-loop/src/tool-calls.ts`). The third and fourth are
|
|
30
|
+
recognized at the **same seam** from the canonical value of a result the pipeline
|
|
31
|
+
calls a *success*, for reasons §3 and §4 give in full.
|
|
30
32
|
|
|
31
33
|
That seam, not `ctx.sandbox.confine`: `confine(argv, policy, signal)` sees the
|
|
32
34
|
confinement failure too, but its signature carries no agent, so a wrapper could
|
|
@@ -437,10 +439,13 @@ the advisory never names the dead directory.
|
|
|
437
439
|
|
|
438
440
|
### 3. A confined child that never started (`native-init`)
|
|
439
441
|
|
|
440
|
-
|
|
442
|
+
Seven reports of one exit code: [`#7876`] and [`#8193`] (the packaged desktop
|
|
441
443
|
app), [`#8313`] (the same version and the same mode run as the desktop app versus
|
|
442
|
-
the Web UI launched from a terminal, which works)
|
|
443
|
-
|
|
444
|
+
the Web UI launched from a terminal, which works), [`#8334`] (the same code with
|
|
445
|
+
the authorization side attached: the grant **succeeded** and every confined child
|
|
446
|
+
still died) and [`#7877`] (MSYS2 / Git
|
|
447
|
+
Bash) — and [`#8208`], which found the mechanism the console cases share, and
|
|
448
|
+
[`#8336`], which measured the creation flags that mechanism turns on. All are `0xC0000142`
|
|
444
449
|
`STATUS_DLL_INIT_FAILED` — the Windows
|
|
445
450
|
loader terminated the process while it was initializing its native images, i.e.
|
|
446
451
|
**before the program's entry point**. A command that ran and then failed exits
|
|
@@ -546,10 +551,37 @@ Two producers have been measured under a confining mode:
|
|
|
546
551
|
ordinary path (`process.ts:567`, i.e. `0x404`); `CREATE_NO_WINDOW`
|
|
547
552
|
(`0x08000000`) is **not a constant anywhere in that source**. Those flags are
|
|
548
553
|
fatal under a console-less runner and harmless under one that owns a console —
|
|
549
|
-
so
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
554
|
+
so **there** the console decides. `0.7.x` wrote the two-set version of that
|
|
555
|
+
list and called the flags "a necessary ingredient ... the host process image is
|
|
556
|
+
what turns it fatal"; both halves were wrong, and `0.8.0` replaces them.
|
|
557
|
+
|
|
558
|
+
**`0.11.0` and earlier concluded too much from those three sets** — "it is the
|
|
559
|
+
console and not the flag list that decides" — and [`#8336`] measured the case
|
|
560
|
+
that falsifies it: with a console-owning host, a restricted token and the Low
|
|
561
|
+
integrity level, varying only the creation flags, `CREATE_NO_WINDOW` and
|
|
562
|
+
`CREATE_NEW_CONSOLE` both died with `0xC0000142`, while `0`, `DETACHED_PROCESS`
|
|
563
|
+
and `CREATE_NEW_PROCESS_GROUP` reached the program. So the console decides
|
|
564
|
+
**whether a flag that merely shares the inherited console is fatal**, and a
|
|
565
|
+
flag that forces the child to create one of its own is fatal regardless. The
|
|
566
|
+
pair inside that matrix is what makes it a rule rather than a list of forbidden
|
|
567
|
+
flags: the same `CREATE_NO_WINDOW` on an *unrestricted* token reached the
|
|
568
|
+
program, and `STARTF_USESHOWWINDOW` with `SW_HIDE` — how the harness hides a
|
|
569
|
+
window without isolating a console — was harmless on the restricted one.
|
|
570
|
+
`0.12.0` replaces the withdrawn sentence with the rule and that matrix.
|
|
571
|
+
|
|
572
|
+
**The `windowsHide` suspicion, answered.** It is the first thing a search turns
|
|
573
|
+
up for this failure, and it points at the wrong component: the flag appears
|
|
574
|
+
once on the *ordinary* subprocess path
|
|
575
|
+
(`packages/subprocess/subprocess-local/src/spawn.ts:472`,
|
|
576
|
+
`windowsHide: platform === 'win32'`), which starts the runner rather than the
|
|
577
|
+
confined child, and the restricted spawn defines no `CREATE_NO_WINDOW` constant
|
|
578
|
+
at all. It is **not** set in `dsh-jobs` — a search there finds nothing, and
|
|
579
|
+
every `windowsHide` in the tree sits on a host-side or ordinary spawn. And
|
|
580
|
+
where it *is* set, [`#8208`] measured it both ways on a host that works: with
|
|
581
|
+
and without `windowsHide`, the confined `pwsh` reached exit `0` with its own
|
|
582
|
+
stdout intact. The reason is the rule again — a windowless console is still a
|
|
583
|
+
console, and that is what the child inherits; what decides is whether the host
|
|
584
|
+
owns a console **object**, not whether it owns a window.
|
|
553
585
|
|
|
554
586
|
**One arm was applied, measured, and rejected.** Putting `DETACHED_PROCESS` on
|
|
555
587
|
the *restricted child* removes its console request and does stop the crash —
|
|
@@ -621,6 +653,110 @@ the single shape that happened to be measured first. It never
|
|
|
621
653
|
offers `danger-full-access` as a fix and never suggests a sandbox setting be
|
|
622
654
|
relaxed.
|
|
623
655
|
|
|
656
|
+
### 4. Denied inside the workspace (`workspace-denial`, added in 0.11.0)
|
|
657
|
+
|
|
658
|
+
[#423] is one report and its own follow-up, and it is the **other end of the
|
|
659
|
+
backend §1 is about**. There the workspace grant could not be applied at all and
|
|
660
|
+
every command died before it ran; here the grant **was** applied — on the
|
|
661
|
+
workspace root, once — and part of the tree still refuses writes, forever. The
|
|
662
|
+
report's shape: under `workspace-write` on Windows, a command writing into a
|
|
663
|
+
subdirectory that was created or **moved in from outside** the session (an
|
|
664
|
+
installer, an editor, another harness running under its own account) is denied,
|
|
665
|
+
while the same command against a directory the harness itself created succeeds.
|
|
666
|
+
|
|
667
|
+
```
|
|
668
|
+
[exit code: 1] sandbox: { mode: "workspace-write", denied: true }
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
**The signature is a value, not a message**, and this family is invisible from
|
|
672
|
+
the error path for the same structural reason §3 is: a denied command exits
|
|
673
|
+
nonzero, and the shipped shell tools report a nonzero exit as a finished run
|
|
674
|
+
rather than as `isError`
|
|
675
|
+
(`packages/shell/tool-pwsh/src/render.ts` reports `[exit code: N]` and drops a
|
|
676
|
+
denial marker). The fact therefore arrives in `ToolExecutionSuccess.value`,
|
|
677
|
+
where `tool-bash` / `tool-pwsh` project what the sandbox executor stamped
|
|
678
|
+
(`packages/shell/bash-sandbox/src/index.ts`, `pwsh-sandbox`): the mode the call
|
|
679
|
+
actually ran under, whether the backend's own refusal dialect appears in the
|
|
680
|
+
**captured stderr**, and the enforcement that applied. Reading the executors'
|
|
681
|
+
own stamp rather than a sentence means this plugin is reporting the harness's
|
|
682
|
+
reading of its own sandbox, not a guess about a line of output.
|
|
683
|
+
|
|
684
|
+
**What the advisory says.** Four things, and one it refuses:
|
|
685
|
+
|
|
686
|
+
- **That retrying is provably useless.** The host-side grant is written once, on
|
|
687
|
+
the workspace **root**, and relies on Windows ACE inheritance to reach the
|
|
688
|
+
tree beneath it. Writing an inherited ACE into an *already-existing* child
|
|
689
|
+
needs `WRITE_DAC` on that child; where the caller does not hold it, Windows
|
|
690
|
+
skips the child silently — no error, no return value, no log line. The backend
|
|
691
|
+
then checks only the root (`hasExactGrant(workspaceRoot)` in
|
|
692
|
+
`packages/sandbox/sandbox-windows-acl/src/acl.ts`) and returns early once the
|
|
693
|
+
grant is there, which it is from the first call onwards. The descendants that
|
|
694
|
+
missed the propagation are never revisited — not later in this session, not in
|
|
695
|
+
any later one.
|
|
696
|
+
- **Which objects miss it, and how many.** It is a fact about *who created
|
|
697
|
+
them*: objects the harness creates inherit the ACE, and objects that already
|
|
698
|
+
existed do not. [#423] measured 170 of 729 objects missing it, **including
|
|
699
|
+
root-level files** — so "write at the workspace root instead" is not a safe
|
|
700
|
+
move either.
|
|
701
|
+
- **The discriminator, and its second half.** The advisory prints the path it
|
|
702
|
+
keyed on beside the root it tested it against, so the reader can audit the
|
|
703
|
+
claim instead of taking a statement about two strings on faith. Then the
|
|
704
|
+
measurement a single check gets wrong: reading and listing use the **normal**
|
|
705
|
+
token while writing and deleting use the **restricted** (low-integrity) one,
|
|
706
|
+
and both sides must pass — so an object whose DACL names only
|
|
707
|
+
`Administrators`/`SYSTEM` plus the capability SID is refused on the read side
|
|
708
|
+
too, and looks fine to a check that merely greps for the capability SID.
|
|
709
|
+
[#423] measured exactly that on a `.cache` directory.
|
|
710
|
+
- **The second measured variant of the same shape.** The coverage that is
|
|
711
|
+
missing can be the mandatory-integrity **label** rather than a DACL entry —
|
|
712
|
+
reported in the same thread on 2026-09-29, against a `0.2.0-rc.1` install,
|
|
713
|
+
under the same root-only short-circuit. From inside a session the two are
|
|
714
|
+
indistinguishable; from outside, the repository's own diagnosis skill
|
|
715
|
+
separates them (`diagnose-windows-sandbox-acl`, 0.2.0 and later, reports
|
|
716
|
+
`hasExactDeny()` for the DACL half and `LOW_LABEL` — `S-1-16-4096` — for the
|
|
717
|
+
label half).
|
|
718
|
+
- **No repair command.** The obvious one, a recursive `icacls /grant` for the
|
|
719
|
+
capability SID, is refused by Windows itself with `ERROR_NONE_MAPPED` (1332) —
|
|
720
|
+
the tool cannot map that SID to a name, so a grant that must name it never
|
|
721
|
+
reaches the child. The line that *would* work needs `WRITE_DAC` on the object,
|
|
722
|
+
which is the right in question. The advisory states the mechanism, names the
|
|
723
|
+
ceiling, and says out loud that it prints no command because this project has
|
|
724
|
+
no Windows host to verify one on — the same standard §1's standing-grant
|
|
725
|
+
section is held to, and for the same reason.
|
|
726
|
+
|
|
727
|
+
**What it refuses to explain, and why that is the design.** A denial is the
|
|
728
|
+
*sanctioned* outcome in three other situations, and advising about a missing
|
|
729
|
+
inherited grant in any of them would be a confidently wrong cause:
|
|
730
|
+
|
|
731
|
+
- **Outside the workspace** — a confining sandbox denying a path outside its
|
|
732
|
+
writable roots is the whole point, and the denial surface's one-shot escalation
|
|
733
|
+
offer is correct there.
|
|
734
|
+
- **Under `read-only`** — that mode denies every write by construction, so an
|
|
735
|
+
in-workspace denial under it is the mode working.
|
|
736
|
+
- **A runner failure** — the executor refuses to call a run denied when the
|
|
737
|
+
runner itself failed, and such a value is left alone for the same reason.
|
|
738
|
+
|
|
739
|
+
What is left is exactly the anomaly: a denial under `workspace-write` of a path
|
|
740
|
+
inside the session's own workspace. That is why the family reads the mode off
|
|
741
|
+
the **value** (the executor stamped the mode it actually ran under, so no policy
|
|
742
|
+
lookup can disagree with it), tests containment against the root the policy
|
|
743
|
+
resolver reports, and speaks only when **every** absolute path the command's own
|
|
744
|
+
arguments name lies under that root. A command that names an outside path as
|
|
745
|
+
well — an interpreter under `C:\Program Files`, an output directory on another
|
|
746
|
+
volume — is refused rather than guessed at, and so is a command naming only
|
|
747
|
+
relative paths: in both cases the plugin cannot say *which* path was denied, and
|
|
748
|
+
silence is the fail-closed direction. The platform gate is real here and cannot
|
|
749
|
+
be dropped: the mechanism is ACE inheritance, which no other backend has.
|
|
750
|
+
|
|
751
|
+
**On a denial it cannot finish placing** — a root the policy resolver does not
|
|
752
|
+
report, or no mounted policy service at all — the plugin withholds the advisory
|
|
753
|
+
and says so once on the host log. That is the disclosure rule §1's mode gate
|
|
754
|
+
follows as well: silence alone would make "the sandbox is not the cause"
|
|
755
|
+
indistinguishable from "this plugin could not tell".
|
|
756
|
+
|
|
757
|
+
[#423] is a Discussion (the repository has issues disabled), and the reply
|
|
758
|
+
covering this family is posted there.
|
|
759
|
+
|
|
624
760
|
## What it does with a recognized failure
|
|
625
761
|
|
|
626
762
|
1. **One durable advisory per agent, per family.** An agent that hits two
|
|
@@ -631,10 +767,12 @@ relaxed.
|
|
|
631
767
|
`warn` line, so the fact survives outside the transcript too.
|
|
632
768
|
2. **A disclosure when it withholds.** The PTY and native-init advisories are
|
|
633
769
|
only sent when the
|
|
634
|
-
resolved mode actually confines
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
770
|
+
resolved mode actually confines, and the workspace-denial advisory only when
|
|
771
|
+
the workspace root is resolvable — the fact its containment claim is tested
|
|
772
|
+
against. If the mode is `danger-full-access`, or either fact cannot be
|
|
773
|
+
resolved at all (no `sandboxPolicy` service mounted, no agent session, a
|
|
774
|
+
resolver that throws, a policy without a root), the failure is left exactly as
|
|
775
|
+
it was **and the host log says so once**. Silence alone would make "the sandbox is
|
|
638
776
|
not the cause" and "this plugin could not tell" indistinguishable from the
|
|
639
777
|
outside. Withholding is never a guess: an unresolvable mode is *not* an
|
|
640
778
|
invitation to fall back to the deployment default.
|
|
@@ -649,8 +787,8 @@ relaxed.
|
|
|
649
787
|
refused twice — while a session can always make progress by spending the
|
|
650
788
|
budget it has.
|
|
651
789
|
|
|
652
|
-
**Why the blocking half
|
|
653
|
-
|
|
790
|
+
**Why the blocking half covers one family only** (it is ACL-only by
|
|
791
|
+
construction, in the parameter type): the ACL remedy is a
|
|
654
792
|
command
|
|
655
793
|
the user can run *while the session continues*, so refusing further identical
|
|
656
794
|
calls cannot make the session unfinishable — spending the budget always lets
|
|
@@ -659,8 +797,11 @@ relaxed.
|
|
|
659
797
|
native-init remedy is a launch fix on the user's side — whose one in-session
|
|
660
798
|
part, rewriting an MSYS2 command, the model does by calling a *different*
|
|
661
799
|
command, which has a different call key and is therefore never the call being
|
|
662
|
-
refused.
|
|
663
|
-
|
|
800
|
+
refused. The workspace-internal denial is not covered either, and for a
|
|
801
|
+
stronger version of the same reason: its remedy is not a command at all — the
|
|
802
|
+
object was skipped when the grant was written and nothing revisited it — so
|
|
803
|
+
refusing calls could only pad a session that is already unable to do the thing
|
|
804
|
+
being refused.
|
|
664
805
|
|
|
665
806
|
## Install
|
|
666
807
|
|
|
@@ -734,6 +875,15 @@ than one that stays silent.
|
|
|
734
875
|
`[exit code: -1073741502]`, or any value that is not the shipped shell
|
|
735
876
|
projection (`kind: 'foreground'`), is not this family — a line of text can
|
|
736
877
|
never be mistaken for a loader status.
|
|
878
|
+
- **A denial is not this family unless the plugin can place it.** A denial under
|
|
879
|
+
`read-only`, under `danger-full-access`, or on a host that is not Windows; a
|
|
880
|
+
value the executor marked as a runner failure (`denied` is not set when the
|
|
881
|
+
runner itself failed); a command naming a path outside the workspace; a command
|
|
882
|
+
naming an outside path as well as an inside one; and a command naming only
|
|
883
|
+
relative paths — all six are refused, and the first three are the *sanctioned*
|
|
884
|
+
outcomes rather than puzzles. The plugin reads the executors' own stamp rather
|
|
885
|
+
than a sentence, so a command whose output contains `denied: true` is not this
|
|
886
|
+
family either.
|
|
737
887
|
- **Only one advisory per agent, per family.** The environment is explained
|
|
738
888
|
once; repeating it per failed command would be noise competing with the
|
|
739
889
|
failure itself.
|
|
@@ -742,9 +892,11 @@ than one that stays silent.
|
|
|
742
892
|
|
|
743
893
|
- **The Windows path itself cannot be witnessed on macOS**, where this plugin
|
|
744
894
|
was built. What the test suite proves is the decision layer — classification
|
|
745
|
-
of all
|
|
895
|
+
of all four families (the third from the producer's own canonical value,
|
|
746
896
|
built by the suite with the reported `-1073741502` and the report's stderr
|
|
747
|
-
line
|
|
897
|
+
line; the fourth from the executors' own stamp, built by the suite with the
|
|
898
|
+
mode, the `denied` flag and the refusal dialect the executor matches), the
|
|
899
|
+
once-per-agent-per-family rule, the sandbox-mode gate
|
|
748
900
|
and its fail-closed behaviour, the fail-fast budget and its self-feeding
|
|
749
901
|
guard, and the wiring to a real cordis `Context` and the real `ToolRuntime` —
|
|
750
902
|
driven by fixtures that throw the producers' exact error shapes
|
|
@@ -754,7 +906,14 @@ than one that stays silent.
|
|
|
754
906
|
a given Windows host reproduces the PTY startup failure; those are the user's
|
|
755
907
|
one-line experiment and the reporter's own control, and both advisories say
|
|
756
908
|
where they stop. The native-init family is the one that needs no Windows to be
|
|
757
|
-
faithful, because what it reads is a number inside a JSON value.
|
|
909
|
+
faithful, because what it reads is a number inside a JSON value. The
|
|
910
|
+
workspace-denial family is exercised the same way and **does** need the
|
|
911
|
+
platform fact, which the suite supplies by stubbing `process.platform` for the
|
|
912
|
+
arms that need `win32` and restoring it — the plugin reads the real fact rather
|
|
913
|
+
than a config knob, because a knob would be a backdoor into a shipped decision.
|
|
914
|
+
What that proves is the decision layer against the producers' stamped values;
|
|
915
|
+
the ACE-inheritance path itself is still unwitnessed here, and the advisory
|
|
916
|
+
says as much by shipping no repair command.
|
|
758
917
|
- **The standing-grant section is source-level, and the out-of-tree reach is the
|
|
759
918
|
reporter's measurement.** What this section states about the backend's own
|
|
760
919
|
behaviour — that the workspace grant is standing, that nothing in the dispose or
|
|
@@ -785,7 +944,7 @@ than one that stays silent.
|
|
|
785
944
|
outside the seam this plugin subscribes to. The report and its proposed fix
|
|
786
945
|
stay with the maintainers; all this plugin can do is explain the provisioning
|
|
787
946
|
failure that shares its root.
|
|
788
|
-
- **The real fix is upstream, in all
|
|
947
|
+
- **The real fix is upstream, in all four families.** For the ACL failure,
|
|
789
948
|
`grantWrite` already computes `hasExactGrant` / `hasExactDeny` /
|
|
790
949
|
`hasExactLabel` and discards which one was false, so the diagnostic that turns
|
|
791
950
|
a 52-minute detour into one line belongs at that site. For the PTY failure,
|
|
@@ -794,7 +953,12 @@ than one that stays silent.
|
|
|
794
953
|
the runner should be launched with the environment its own execution needs
|
|
795
954
|
(`ELECTRON_RUN_AS_NODE=1` when `argv[0]` is an Electron binary — [`#7876`]'s
|
|
796
955
|
three candidate fixes) or refuse, in a checkable way, an MSYS2 program under a
|
|
797
|
-
restricted token.
|
|
956
|
+
restricted token. For the workspace-internal denial the site is the same
|
|
957
|
+
`grantWrite`: its early return asks only whether the **root** already carries
|
|
958
|
+
the ACE, so the descendants that missed the propagation are never repaired —
|
|
959
|
+
the check would have to look past the root, or the denial surface would have to
|
|
960
|
+
say *which* path was refused instead of only that one was. This plugin is the
|
|
961
|
+
stopgap for all four.
|
|
798
962
|
|
|
799
963
|
## Compatibility
|
|
800
964
|
|
|
@@ -885,6 +1049,7 @@ the current runtime cannot distinguish rather than counting it as a pass.
|
|
|
885
1049
|
[discussion #7876]: https://github.com/deepseek-ai/deepseek-harness/discussions/7876
|
|
886
1050
|
[discussion #7877]: https://github.com/deepseek-ai/deepseek-harness/discussions/7877
|
|
887
1051
|
[discussion #8208]: https://github.com/deepseek-ai/deepseek-harness/discussions/8208
|
|
1052
|
+
[#423]: https://github.com/deepseek-ai/deepseek-harness/discussions/423
|
|
888
1053
|
[#7750]: https://github.com/deepseek-ai/deepseek-harness/discussions/7750
|
|
889
1054
|
[#7771]: https://github.com/deepseek-ai/deepseek-harness/discussions/7771
|
|
890
1055
|
[#7804]: https://github.com/deepseek-ai/deepseek-harness/discussions/7804
|
|
@@ -906,3 +1071,5 @@ the current runtime cannot distinguish rather than counting it as a pass.
|
|
|
906
1071
|
[#8313]: https://github.com/deepseek-ai/deepseek-harness/discussions/8313
|
|
907
1072
|
[#8314]: https://github.com/deepseek-ai/deepseek-harness/discussions/8314
|
|
908
1073
|
[#8322]: https://github.com/deepseek-ai/deepseek-harness/discussions/8322
|
|
1074
|
+
[#8334]: https://github.com/deepseek-ai/deepseek-harness/discussions/8334
|
|
1075
|
+
[#8336]: https://github.com/deepseek-ai/deepseek-harness/discussions/8336
|
package/cordis.patch.yml
CHANGED
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
# running one.
|
|
106
106
|
#
|
|
107
107
|
# A THIRD family is recognized from a value, not from text (#7876, #7877,
|
|
108
|
-
# #8193, #8208, #8313):
|
|
108
|
+
# #8193, #8208, #8313, #8336, #8334):
|
|
109
109
|
#
|
|
110
110
|
# [exit code: -1073741502] (0xC0000142 STATUS_DLL_INIT_FAILED)
|
|
111
111
|
#
|
|
@@ -124,7 +124,51 @@
|
|
|
124
124
|
# or spawned without a console), carries the one conversion the model can make
|
|
125
125
|
# itself (rewrite the work as PowerShell or `cmd`), names the remedy #8193
|
|
126
126
|
# measured — a real node.exe host, which the desktop ships — and says plainly
|
|
127
|
-
# which producers it does not know.
|
|
127
|
+
# which producers it does not know. It also states the one rule the whole family
|
|
128
|
+
# follows from, because a reader without it reaches for the wrong flag: in a
|
|
129
|
+
# restricted token a console can be INHERITED but not CREATED, so a creation
|
|
130
|
+
# flag that forces the child to make one of its own — `CREATE_NO_WINDOW`,
|
|
131
|
+
# `CREATE_NEW_CONSOLE` — is fatal on its own, while `DETACHED_PROCESS` (which
|
|
132
|
+
# declines a console rather than creating one) is not; #8336 measured that
|
|
133
|
+
# matrix on one machine, and #8208 measured `windowsHide` both ways on a host
|
|
134
|
+
# that works, so the advisory answers that suspicion with where the flag
|
|
135
|
+
# actually appears — the ordinary subprocess path, not the confined one — and
|
|
136
|
+
# with why a windowless console is still an inheritable console. Like the second
|
|
137
|
+
# family, it is mode-gated.
|
|
138
|
+
#
|
|
139
|
+
# A FOURTH family is the other half of the FIRST one's backend (#423). There the
|
|
140
|
+
# grant could not be applied at all; here it WAS applied — on the workspace root,
|
|
141
|
+
# once — and Windows ACE inheritance silently skipped the objects whose DACL the
|
|
142
|
+
# caller could not write, so commands writing into a subdirectory created or moved
|
|
143
|
+
# in from outside (an installer, an editor, another harness under its own account)
|
|
144
|
+
# are denied forever while the same command against a directory the harness itself
|
|
145
|
+
# created succeeds. The backend's provisioning check short-circuits on the root
|
|
146
|
+
# (`hasExactGrant` returns early once the root carries the ACE), so those
|
|
147
|
+
# descendants are never revisited. It is read from a value rather than from text,
|
|
148
|
+
# like the third family and for the same reason (a denial exits nonzero and the
|
|
149
|
+
# shipped shell tools report that as a finished run), but it needs no bespoke code:
|
|
150
|
+
# the executors stamp the denial onto the value as
|
|
151
|
+
#
|
|
152
|
+
# sandbox: { mode: "workspace-write", denied: true }
|
|
153
|
+
#
|
|
154
|
+
# produced by matching the backend's own refusal dialect in the captured stderr —
|
|
155
|
+
# so this plugin reads the harness's own reading of its own sandbox. It speaks
|
|
156
|
+
# only when the host is Windows, the stamped mode is `workspace-write`, and EVERY
|
|
157
|
+
# absolute path the command names lies inside the session's workspace: a denial
|
|
158
|
+
# anywhere else (outside the workspace, under `read-only`, a runner failure) is
|
|
159
|
+
# the sandbox working as designed and is left alone. The advisory prints the path
|
|
160
|
+
# it keyed on beside the root it tested it against, says that retrying is provably
|
|
161
|
+
# useless, gives the DISCRIMINATOR — reading/listing use the normal token while
|
|
162
|
+
# writing/deleting use the restricted one, and both sides must pass, so an object
|
|
163
|
+
# whose DACL names only Administrators/SYSTEM plus the capability SID looks granted
|
|
164
|
+
# to a check that just greps for the SID — names the second measured variant of
|
|
165
|
+
# the same shape (the coverage missing on the mandatory-integrity LABEL rather
|
|
166
|
+
# than on the DACL, separated from outside a session by the repository's own
|
|
167
|
+
# `diagnose-windows-sandbox-acl`), and states the Windows ceiling that closes the
|
|
168
|
+
# obvious repair (a recursive `icacls /grant` for a capability SID is refused with
|
|
169
|
+
# ERROR_NONE_MAPPED (1332), because that SID has no name to map). It ships NO
|
|
170
|
+
# repair command, for the reason the standing-grant section ships none: this
|
|
171
|
+
# project has no Windows host to verify a line on.
|
|
128
172
|
|
|
129
173
|
- insert:
|
|
130
174
|
- id: sandbox-grant-advisor
|