Commit 95c6b5f
committed
fix(security): fail closed when an object's security posture can't be resolved (#3545)
#3545 assessed the API-exposure gate's fail-open on unresolvable metadata and
accepted it, resting on one load-bearing premise: the gate is a SURFACE-AREA
control, while the real authorization boundary — auth + the ObjectQL security
middleware (CRUD/FLS/RLS) — enforces unconditionally on the data call whatever
the gate answers.
Verifying that premise instead of assuming it shows it did not hold. The
middleware does run unconditionally, but two of its INPUTS were read from the
same object metadata and defaulted permissively when it could not be resolved,
so the very trigger this issue is about reached one layer PAST the gate, into
the boundary itself:
* `access.default: 'private'` -> `isPrivate` defaulted to false. ADR-0066 D2
deliberately excludes a private object from a plain (non-superuser) `'*'`
wildcard; read as public it IS covered — a grant nobody authored.
* `requiredPermissions` -> defaulted to `[]`, which skips the ADR-0066 D3
capability AND-gate entirely (`if (required.length > 0)`).
`getObjectSecurityMeta` now flags `unresolved`, and the three consumers that
turn posture into an access decision fail closed on it: the middleware denies
(with an error log, so a persistent metadata outage is observable rather than a
silent blanket-allow), `canExport` denies, `getReadableFields` exposes no
columns — the same stance already taken for a permission-resolution failure and
a dangling delegator. `computeLayeredRlsFilter` keeps consuming the defaults on
purpose: there the permissive value WITHHOLDS the cross-tenant exemption, so it
is already the closed direction.
Blast radius is bounded to the risky case. System/boot writes (`isSystem`) and
principal-less/anonymous contexts short-circuit earlier in the middleware, so
reaching the new check means an authenticated principal with resolved grants
asking for an object whose declaration is missing. The cold-start window is
served by those short-circuits, not by the permissive default — which is why
the tiered decision recorded for the exposure gate (transient unavailability ->
fail open) stands unchanged now that the boundary underneath it actually holds.
The explain engine reports the denial on its existing `object_crud` layer
naming the real cause, so the "why am I denied?" surface cannot drift from
enforcement.
Regression-pinned in metadata-unresolvable-posture.test.ts: both directions of
each axis (resolvable -> denied per ADR-0066; unresolvable -> still denied),
the unaffected anonymous / system / public-object paths, the error log, and
explain parity. Verified green: plugin-security (645), runtime, rest, objectql,
and the dogfood suite that boots the real showcase app (369).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019288JyDfHtCiYVgAJLxmsg1 parent b098b0e commit 95c6b5f
4 files changed
Lines changed: 324 additions & 16 deletions
File tree
- packages
- plugins/plugin-security/src
- runtime/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
146 | 146 | | |
147 | 147 | | |
148 | 148 | | |
| 149 | + | |
| 150 | + | |
149 | 151 | | |
150 | 152 | | |
151 | 153 | | |
| |||
840 | 842 | | |
841 | 843 | | |
842 | 844 | | |
843 | | - | |
844 | | - | |
845 | | - | |
846 | | - | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
847 | 858 | | |
848 | 859 | | |
849 | 860 | | |
850 | 861 | | |
851 | 862 | | |
852 | 863 | | |
853 | | - | |
854 | | - | |
855 | | - | |
856 | | - | |
857 | | - | |
858 | | - | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
859 | 874 | | |
860 | 875 | | |
861 | 876 | | |
| |||
Lines changed: 219 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
149 | 149 | | |
150 | 150 | | |
151 | 151 | | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
152 | 165 | | |
153 | 166 | | |
154 | 167 | | |
| |||
909 | 922 | | |
910 | 923 | | |
911 | 924 | | |
912 | | - | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
| 948 | + | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
913 | 960 | | |
914 | 961 | | |
915 | 962 | | |
| |||
2233 | 2280 | | |
2234 | 2281 | | |
2235 | 2282 | | |
| 2283 | + | |
| 2284 | + | |
| 2285 | + | |
| 2286 | + | |
| 2287 | + | |
2236 | 2288 | | |
2237 | 2289 | | |
2238 | 2290 | | |
| |||
2287 | 2339 | | |
2288 | 2340 | | |
2289 | 2341 | | |
2290 | | - | |
| 2342 | + | |
| 2343 | + | |
| 2344 | + | |
| 2345 | + | |
| 2346 | + | |
2291 | 2347 | | |
2292 | 2348 | | |
2293 | 2349 | | |
| |||
3159 | 3215 | | |
3160 | 3216 | | |
3161 | 3217 | | |
3162 | | - | |
3163 | | - | |
| 3218 | + | |
| 3219 | + | |
| 3220 | + | |
| 3221 | + | |
| 3222 | + | |
| 3223 | + | |
| 3224 | + | |
3164 | 3225 | | |
3165 | 3226 | | |
3166 | 3227 | | |
| |||
3203 | 3264 | | |
3204 | 3265 | | |
3205 | 3266 | | |
| 3267 | + | |
3206 | 3268 | | |
3207 | 3269 | | |
3208 | 3270 | | |
| |||
0 commit comments