You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
gate-7 clears a #[NoAdminRequired] method that reaches storage through ObjectService / a *Mapper on the stated reasoning that OpenRegister's
register RBAC enforces per-object authorisation one layer down
(check_no_admin_idor.py Pattern 2, and the runner's own FAIL guidance: "If the endpoint reaches storage through a service or mapper, check whether the
guard is enforced THERE").
For most of the fleet that layer does not exist. OpenRegister's PermissionHandler::hasGroupPermission() returns true for any schema whose authorization block is empty or null, and the opt-in that would close it
defaults to false.
isDefaultClosedEnforced() reads appConfig->getValueBool('openregister', 'enforce_default_closed', default: false),
and its own docblock states the reason: "the fleet ships ~15 leaf apps whose *_register.json files do not yet declare authorization blocks. Flipping the
default would brick them overnight."
This is already known and tracked on the product side as ConductionNL/openregister#1955 and #2011. What is not tracked is that gate-7
encodes the opposite assumption, and therefore issues a clean verdict over
exactly the endpoints those issues describe as open.
Measured — how many fleet schemas actually declare authorization
Walked every register/schema JSON shipped by each app at origin/development:
app
schemas
with authorization
shillinq
871
0
scholiq
191
0
openconnector
87
0
nldesign
50
0
doriath
1
0
zaakafhandelapp
ships no register config at all
0
pipelinq
164
1
hermiq
69
1
docudesk
72
1
procest
299
6
larpingapp
23
2
openregister
145
15
opencatalogi
74
15
openbuild
39
15
decidesk
172
24
softwarecatalog
27
21
Positive control on the lookup (an empty lookup manufactures the most
alarming possible answer for free): the same walker finds 21/27 in
softwarecatalog and 26 literal "authorization" occurrences in softwarecatalog/lib/Settings/softwarecatalogus_register.json. The zeros are
measurements, not a bad key.
zaakafhandelapp is the sharpest case: it ships no register config, and its own exported production register (docs/json/zaken_2026-03-27_102152.json)
carries "authorization": null on the zaken register and on all twelve ZGW
schemas. empty(null) === true → return true.
Why this matters here and not only on #2011
Combined with #365 (gate-7 accepts a no user → 401 preamble as an
authorisation guard), the two produce a gate that is silent in both directions
at once:
the reviewer is told to look one layer down → Pattern 2 says OR handles it;
OR grants the action because the schema declares no rules.
Measured consequence: gate-7 reports 0 in all 18 fleet apps. With #365's
proposed fix applied, the same runs over the same trees report 423 findings.
What I am asking for
Not a Pattern-2 removal — the pattern is correct where an authorization block
exists. Two smaller things:
Make the assumption checkable. Pattern 2 currently applies on the namespace (OCA\OpenRegister) or on the presence of an ObjectService
call. It should be conditional on the touched schema actually declaring an authorization block, or — if that is too much resolution for a regex gate —
the runner's FAIL/PASS guidance should say plainly that OR is default-OPEN
for schemas without an authorization block, so "the guard is enforced
THERE" stops being the default reading.
⚠️ Sequencing: like #365, #347, #356 and #358, any fix here has the false-RED
shape and will redden repos simultaneously. Filing, not merging.
Note on #2011's audit command
#2011 suggests grep -L '"authorization"' apps-extra/*/registers/*.json. No
fleet app has a registers/ directory — the configs live under lib/Settings/*_register.json and lib/Settings/register.d/*.json. As written
that command matches nothing and exits reporting nothing to do, which is the
same absence-claim shape this programme keeps paying for.
Summary
gate-7 clears a
#[NoAdminRequired]method that reaches storage throughObjectService/ a*Mapperon the stated reasoning that OpenRegister'sregister RBAC enforces per-object authorisation one layer down
(
check_no_admin_idor.pyPattern 2, and the runner's own FAIL guidance:"If the endpoint reaches storage through a service or mapper, check whether the
guard is enforced THERE").
For most of the fleet that layer does not exist. OpenRegister's
PermissionHandler::hasGroupPermission()returnstruefor any schema whoseauthorizationblock is empty or null, and the opt-in that would close itdefaults to
false.openregister/lib/Service/Object/PermissionHandler.php:1207—isDefaultClosedEnforced()readsappConfig->getValueBool('openregister', 'enforce_default_closed', default: false),and its own docblock states the reason: "the fleet ships ~15 leaf apps whose
*_register.jsonfiles do not yet declare authorization blocks. Flipping thedefault would brick them overnight."
This is already known and tracked on the product side as
ConductionNL/openregister#1955 and #2011. What is not tracked is that gate-7
encodes the opposite assumption, and therefore issues a clean verdict over
exactly the endpoints those issues describe as open.
Measured — how many fleet schemas actually declare
authorizationWalked every register/schema JSON shipped by each app at
origin/development:authorizationPositive control on the lookup (an empty lookup manufactures the most
alarming possible answer for free): the same walker finds 21/27 in
softwarecatalog and 26 literal
"authorization"occurrences insoftwarecatalog/lib/Settings/softwarecatalogus_register.json. The zeros aremeasurements, not a bad key.
zaakafhandelapp is the sharpest case: it ships no register config, and its own
exported production register (
docs/json/zaken_2026-03-27_102152.json)carries
"authorization": nullon thezakenregister and on all twelve ZGWschemas.
empty(null) === true→return true.Why this matters here and not only on #2011
Combined with #365 (gate-7 accepts a
no user → 401preamble as anauthorisation guard), the two produce a gate that is silent in both directions
at once:
Measured consequence: gate-7 reports
0in all 18 fleet apps. With #365'sproposed fix applied, the same runs over the same trees report 423 findings.
What I am asking for
Not a Pattern-2 removal — the pattern is correct where an
authorizationblockexists. Two smaller things:
namespace (
OCA\OpenRegister) or on the presence of an ObjectServicecall. It should be conditional on the touched schema actually declaring an
authorizationblock, or — if that is too much resolution for a regex gate —the runner's FAIL/PASS guidance should say plainly that OR is default-OPEN
for schemas without an
authorizationblock, so "the guard is enforcedTHERE" stops being the default reading.
the three halves are not closed independently.
shape and will redden repos simultaneously. Filing, not merging.
Note on #2011's audit command
#2011suggestsgrep -L '"authorization"' apps-extra/*/registers/*.json. Nofleet app has a
registers/directory — the configs live underlib/Settings/*_register.jsonandlib/Settings/register.d/*.json. As writtenthat command matches nothing and exits reporting nothing to do, which is the
same absence-claim shape this programme keeps paying for.
Confirmed by: canonical
ConductionNL/.github@112d4c9(post-#368);openregister@origin/development9628dc5d0; per-app refs listed in/home/rubenlinde/fleet-board/findings/gate7-fleet-reaudit.md.