@@ -40,6 +40,18 @@ describe('resolveAccessControlBlockType', () => {
4040 it ( 'accepts the dashed spelling the registry also normalizes' , ( ) => {
4141 expect ( resolveAccessControlBlockType ( 'google-sheets' ) ) . toBe ( 'google_sheets_v2' )
4242 } )
43+
44+ /**
45+ * `allowedIntegrations` is admin-supplied jsonb and `ALLOWED_INTEGRATIONS` is
46+ * hand-written, so an arbitrary string reaches the successor map. An
47+ * inherited key must stay an ordinary unresolved id rather than answering
48+ * with `Object.prototype`'s function.
49+ */
50+ it ( 'leaves an object-prototype key alone' , ( ) => {
51+ expect ( resolveAccessControlBlockType ( 'constructor' ) ) . toBe ( 'constructor' )
52+ expect ( resolveAccessControlBlockType ( 'toString' ) ) . toBe ( 'toString' )
53+ expect ( resolveAccessControlBlockType ( '__proto__' ) ) . toBe ( '__proto__' )
54+ } )
4355} )
4456
4557describe ( 'toAccessControlAllowlist' , ( ) => {
@@ -61,6 +73,18 @@ describe('toAccessControlAllowlist', () => {
6173 it ( 'denies everything for an empty allowlist' , ( ) => {
6274 expect ( toAccessControlAllowlist ( [ ] ) ?. size ) . toBe ( 0 )
6375 } )
76+
77+ /**
78+ * A prototype key used to resolve to an inherited function and throw on
79+ * `.toLowerCase()`, turning one configured string into a 500 on every
80+ * enforcement path that read the group.
81+ */
82+ it ( 'indexes an object-prototype entry as an ordinary block type' , ( ) => {
83+ const allowlist = toAccessControlAllowlist ( [ 'constructor' , 'slack' ] )
84+
85+ expect ( allowlist ?. has ( 'constructor' ) ) . toBe ( true )
86+ expect ( allowlist ?. has ( 'slack_v2' ) ) . toBe ( true )
87+ } )
6488} )
6589
6690describe ( 'intersectAccessControlAllowlists' , ( ) => {
0 commit comments