Read an unwritten guard mode as enforce when merging, not as the weakest
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
83e1444981
commit
2cc52fd1a7
2 files changed
+15
-4
No files matched your search
@@ -189,7 +189,13 @@ func Merge(names []string, ps []Policy) Policy {
|
||||
var allowSets [][]string
|
||||
var prompts []string
|
||||
for _, p := range ps {
|
||||
out.Mode = stricterOf(out.Mode, p.Mode, []string{"", "off", "shadow", "enforce"})
|
||||
// Unwritten is enforce, not the weakest: a policy that says nothing
|
||||
// of its mode, merged with one in shadow, must still act.
|
||||
mode := p.Mode
|
||||
if mode == "" {
|
||||
mode = "enforce"
|
||||
}
|
||||
out.Mode = stricterOf(out.Mode, mode, []string{"", "off", "shadow", "enforce"})
|
||||
out.Fail = stricterOf(out.Fail, p.Fail, []string{"", "open", "closed"})
|
||||
out.Stream = stricterOf(out.Stream, p.Stream, []string{"", "sentence", "buffer_all"})
|
||||
out.NoStore = out.NoStore || p.NoStore
|
||||
@@ -212,9 +218,6 @@ func Merge(names []string, ps []Policy) Policy {
|
||||
out.Tools.MaxCallsPerTurn = minSet(out.Tools.MaxCallsPerTurn, t.MaxCallsPerTurn)
|
||||
out.Tools.ValidateArguments = out.Tools.ValidateArguments || t.ValidateArguments
|
||||
}
|
||||
if out.Mode == "" && len(ps) > 0 {
|
||||
out.Mode = "enforce"
|
||||
}
|
||||
for i, s := range allowSets {
|
||||
if i == 0 {
|
||||
out.Tools.Allow = slices.Clone(s)
|
||||
|
||||
@@ -37,6 +37,14 @@ func TestPoliciesNarrowAndNeverLoosen(t *testing.T) {
|
||||
if len(none.Tools.Allow) != 1 || none.Tools.Allow[0] == "a" || none.Tools.Allow[0] == "b" {
|
||||
t.Errorf("disjoint allow lists: %v", none.Tools.Allow)
|
||||
}
|
||||
// Found on the PoC: a shadow default merged with an attached policy that
|
||||
// did not write its mode left the attached one in shadow too.
|
||||
if m := Merge(nil, []Policy{{Mode: "shadow"}, {}}); m.Mode != "enforce" {
|
||||
t.Errorf("shadow and an unwritten mode: %q", m.Mode)
|
||||
}
|
||||
if m := Merge(nil, []Policy{{Mode: "shadow"}}); m.Mode != "shadow" {
|
||||
t.Errorf("shadow alone: %q", m.Mode)
|
||||
}
|
||||
if Merge(nil, nil).active() || !Merge(nil, []Policy{{}}).active() || Merge(nil, []Policy{{Mode: "off"}}).active() {
|
||||
t.Error("activeness")
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user