@memberjunction/react-runtime 5.51.0 → 5.51.1

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.
@@ -1,25 +1,25 @@
1
1
 
2
- > @memberjunction/react-runtime@5.51.0 build
2
+ > @memberjunction/react-runtime@5.51.1 build
3
3
  > npm run build:node && npm run build:umd
4
4
 
5
5
 
6
- > @memberjunction/react-runtime@5.51.0 build:node
6
+ > @memberjunction/react-runtime@5.51.1 build:node
7
7
  > tsc && tsc-alias -f
8
8
 
9
9
 
10
- > @memberjunction/react-runtime@5.51.0 build:umd
10
+ > @memberjunction/react-runtime@5.51.1 build:umd
11
11
  > webpack --config webpack.umd.config.cjs
12
12
 
13
- Browserslist: browsers data (caniuse-lite) is 6 months old. Please run:
13
+ Browserslist: browsers data (caniuse-lite) is 7 months old. Please run:
14
14
  npx update-browserslist-db@latest
15
15
  Why you should do it regularly: https://github.com/browserslist/update-db#readme
16
16
  [BABEL] Note: The code generator has deoptimised the styling of /home/runner/work/MJ/MJ/packages/MJCoreEntities/dist/generated/entity_subclasses.js as it exceeds the max of 500KB.
17
- asset runtime.umd.js 8.78 MiB [compared for emit] [big] (name: main)
17
+ asset runtime.umd.js 8.79 MiB [compared for emit] [big] (name: main)
18
18
  asset 324.runtime.umd.js 218 KiB [compared for emit]
19
19
  asset 490.runtime.umd.js 182 KiB [compared for emit] (id hint: vendors)
20
20
  orphan modules 8.77 MiB [orphan] 571 modules
21
21
  runtime modules 6.94 KiB 10 modules
22
- cacheable modules 8.91 MiB
22
+ cacheable modules 8.92 MiB
23
23
  modules by path ../../../node_modules/ 781 KiB
24
24
  modules by path ../../../node_modules/rxjs/dist/esm5/internal/ 30.4 KiB 16 modules
25
25
  modules by path ../../../node_modules/debug/src/*.js 12.7 KiB 2 modules
@@ -29,6 +29,6 @@ cacheable modules 8.91 MiB
29
29
  ../../MJCoreEntities/dist/engines/UserViewEngine.js 19.6 KiB [built] [code generated]
30
30
  ./dist/index.js + 29 modules 440 KiB [built] [code generated]
31
31
  ../../MJCore/dist/index.js + 88 modules 1.8 MiB [built] [code generated]
32
- ../../MJGlobal/dist/index.js + 24 modules 312 KiB [built] [code generated]
32
+ ../../MJGlobal/dist/index.js + 24 modules 316 KiB [built] [code generated]
33
33
  ../../GraphQLDataProvider/dist/index.mjs 194 KiB [built] [code generated]
34
- webpack 5.105.0 compiled successfully in 70217 ms
34
+ webpack 5.105.0 compiled successfully in 70131 ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @memberjunction/react-runtime
2
2
 
3
+ ## 5.51.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [cc6f321]
8
+ - Updated dependencies [e10a71f]
9
+ - @memberjunction/global@5.51.1
10
+ - @memberjunction/core@5.51.1
11
+ - @memberjunction/graphql-dataprovider@5.51.1
12
+ - @memberjunction/core-entities@5.51.1
13
+ - @memberjunction/interactive-component-types@5.51.1
14
+
3
15
  ## 5.51.0
4
16
 
5
17
  ### Patch Changes
@@ -361,7 +361,7 @@ var se=Object.defineProperty;var d=(g,e)=>se(g,"name",{value:e,configurable:!0})
361
361
  }
362
362
  }
363
363
  }
364
- `,r={entityDocumentID:e.entityDocumentID};e.maxRecords!==void 0&&(r.maxRecords=e.maxRecords),e.filter!==void 0&&(r.filter=e.filter);const s=await this._dataProvider.ExecuteGQL(t,r);if(!s?.FetchEntityVectors)throw new Error("Invalid response from server");return s.FetchEntityVectors}catch(t){const r=t;return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogError */ .ZI8)("GraphQLAIClient.FetchEntityVectors failed",void 0,r),{Success:!1,Results:[],TotalCount:0,ElapsedMs:0,ErrorMessage:r.message||"Unknown error"}}}}const F="5.51.0",$="default";class X{static{d(this,"BrowserStorageProviderBase")}constructor(){this._storage=new Map}getCategoryMap(e){const t=e||$;let r=this._storage.get(t);return r||(r=new Map,this._storage.set(t,r)),r}async GetItem(e,t){const s=this.getCategoryMap(t||$).get(e);return s===void 0?null:s}async GetItems(e,t){const r=new Map;if(e.length===0)return r;const s=this.getCategoryMap(t||$);for(const n of new Set(e)){const a=s.get(n);r.set(n,a===void 0?null:a)}return r}async SetItem(e,t,r){this.getCategoryMap(r||$).set(e,t)}async Remove(e,t){this.getCategoryMap(t||$).delete(e)}async ClearCategory(e){const t=e||$;this._storage.delete(t)}async GetCategoryKeys(e){const t=this._storage.get(e||$);return t?Array.from(t.keys()):[]}}const $e="MJ_Metadata",Pe=0;function Me(){try{const g=F.split("."),e=parseInt(g[0],10),t=parseInt(g[1],10);if(!Number.isFinite(e)||!Number.isFinite(t))throw new Error(`Could not parse major.minor from version "${F}"`);return e*1e3+t+Pe}catch(g){return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:g,message:"Failed to derive IDB version from PACKAGE_VERSION; using fallback 99999"}),99999}}d(Me,"computeIdbVersion");const Ae=Me(),Y=["mj:default","mj:Metadata","mj:RunViewCache","mj:RunQueryCache","mj:DatasetCache"];class Z extends X{static{d(this,"BrowserIndexedDBStorageProvider")}constructor(){super(),this._dbReady=!1,this.dbPromise=(0,_tempfix_idb__WEBPACK_IMPORTED_MODULE_10__/* .openDB */ .P2)($e,Ae,{upgrade:d((e,t,r)=>{try{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)(`[IDBCache] Upgrading IndexedDB schema v${t} \u2192 v${r} (package ${F}). Dropping all stores; caches will repopulate on first use.`);for(const s of Array.from(e.objectStoreNames))e.deleteObjectStore(s);for(const s of Y)e.objectStoreNames.contains(s)||e.createObjectStore(s)}catch(s){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:s,message:s?.message})}},"upgrade"),blocked:d((e,t)=>{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)(`[IDBCache] Upgrade from v${e} to v${t} blocked by another tab. Close other tabs to allow the upgrade to proceed.`)},"blocked")}),this.dbPromise.then(e=>{this._dbReady=!0,e.onversionchange=()=>{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)("[IDBCache] DB schema upgraded in another tab \u2014 closing local connection."),e.close(),this._dbReady=!1}}).catch(e=>{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:e,message:"IndexedDB initialization failed: "+e?.message})})}get IsReady(){return this._dbReady}isKnownCategory(e){const t=`mj:${e}`;return Y.includes(t)}getStoreName(e){const t=e||$;return this.isKnownCategory(t)?`mj:${t}`:"mj:default"}getStoreKey(e,t){const r=t||$;return this.isKnownCategory(r)?e:`[${r}]:${e}`}async SetItem(e,t,r){try{const s=await this.dbPromise,n=this.getStoreName(r),a=this.getStoreKey(e,r),i=s.transaction(n,"readwrite");await i.objectStore(n).put(t,a),await i.done}catch(s){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:s,message:s?.message})}}async GetItem(e,t){try{const r=await this.dbPromise,s=this.getStoreName(t),n=this.getStoreKey(e,t),a=await r.transaction(s).objectStore(s).get(n);return a===void 0?null:a}catch(r){return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:r,message:r?.message}),null}}async GetItems(e,t){const r=new Map;if(e.length===0)return r;try{const s=await this.dbPromise,n=this.getStoreName(t),a=Array.from(new Set(e)),i=a.map(f=>this.getStoreKey(f,t)),o=s.transaction(n,"readonly"),m=o.objectStore(n),u=i.map(f=>m.get(f)),h=await Promise.all(u);await o.done;for(let f=0;f<a.length;f++){const y=h[f];r.set(a[f],y===void 0?null:y)}return r}catch(s){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:s,message:s?.message});for(const n of new Set(e))r.set(n,null);return r}}async Remove(e,t){try{const r=await this.dbPromise,s=this.getStoreName(t),n=this.getStoreKey(e,t),a=r.transaction(s,"readwrite");await a.objectStore(s).delete(n),await a.done}catch(r){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:r,message:r?.message})}}async ClearCategory(e){try{const t=await this.dbPromise,r=e||$,s=this.getStoreName(e);if(this.isKnownCategory(r)){const n=t.transaction(s,"readwrite");await n.objectStore(s).clear(),await n.done}else{const n=`[${r}]:`,a=t.transaction("mj:default","readwrite"),i=a.objectStore("mj:default"),o=await i.getAllKeys();for(const m of o)typeof m=="string"&&m.startsWith(n)&&await i.delete(m);await a.done}}catch(t){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:t,message:t?.message})}}async GetCategoryKeys(e){try{const t=await this.dbPromise,r=e||$,s=this.getStoreName(e),i=await t.transaction(s,"readonly").objectStore(s).getAllKeys();if(this.isKnownCategory(r))return i.map(m=>String(m));const o=`[${r}]:`;return i.map(m=>String(m)).filter(m=>m.startsWith(o)).map(m=>m.slice(o.length))}catch(t){return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:t,message:t?.message}),[]}}}const b=new A,Ne=(0,graphql_request__WEBPACK_IMPORTED_MODULE_0__/* .gql */ .J1)`subscription RemoteOperationProgress($channelId: ID!) {
364
+ `,r={entityDocumentID:e.entityDocumentID};e.maxRecords!==void 0&&(r.maxRecords=e.maxRecords),e.filter!==void 0&&(r.filter=e.filter);const s=await this._dataProvider.ExecuteGQL(t,r);if(!s?.FetchEntityVectors)throw new Error("Invalid response from server");return s.FetchEntityVectors}catch(t){const r=t;return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogError */ .ZI8)("GraphQLAIClient.FetchEntityVectors failed",void 0,r),{Success:!1,Results:[],TotalCount:0,ElapsedMs:0,ErrorMessage:r.message||"Unknown error"}}}}const F="5.51.1",$="default";class X{static{d(this,"BrowserStorageProviderBase")}constructor(){this._storage=new Map}getCategoryMap(e){const t=e||$;let r=this._storage.get(t);return r||(r=new Map,this._storage.set(t,r)),r}async GetItem(e,t){const s=this.getCategoryMap(t||$).get(e);return s===void 0?null:s}async GetItems(e,t){const r=new Map;if(e.length===0)return r;const s=this.getCategoryMap(t||$);for(const n of new Set(e)){const a=s.get(n);r.set(n,a===void 0?null:a)}return r}async SetItem(e,t,r){this.getCategoryMap(r||$).set(e,t)}async Remove(e,t){this.getCategoryMap(t||$).delete(e)}async ClearCategory(e){const t=e||$;this._storage.delete(t)}async GetCategoryKeys(e){const t=this._storage.get(e||$);return t?Array.from(t.keys()):[]}}const $e="MJ_Metadata",Pe=0;function Me(){try{const g=F.split("."),e=parseInt(g[0],10),t=parseInt(g[1],10);if(!Number.isFinite(e)||!Number.isFinite(t))throw new Error(`Could not parse major.minor from version "${F}"`);return e*1e3+t+Pe}catch(g){return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:g,message:"Failed to derive IDB version from PACKAGE_VERSION; using fallback 99999"}),99999}}d(Me,"computeIdbVersion");const Ae=Me(),Y=["mj:default","mj:Metadata","mj:RunViewCache","mj:RunQueryCache","mj:DatasetCache"];class Z extends X{static{d(this,"BrowserIndexedDBStorageProvider")}constructor(){super(),this._dbReady=!1,this.dbPromise=(0,_tempfix_idb__WEBPACK_IMPORTED_MODULE_10__/* .openDB */ .P2)($e,Ae,{upgrade:d((e,t,r)=>{try{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)(`[IDBCache] Upgrading IndexedDB schema v${t} \u2192 v${r} (package ${F}). Dropping all stores; caches will repopulate on first use.`);for(const s of Array.from(e.objectStoreNames))e.deleteObjectStore(s);for(const s of Y)e.objectStoreNames.contains(s)||e.createObjectStore(s)}catch(s){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:s,message:s?.message})}},"upgrade"),blocked:d((e,t)=>{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)(`[IDBCache] Upgrade from v${e} to v${t} blocked by another tab. Close other tabs to allow the upgrade to proceed.`)},"blocked")}),this.dbPromise.then(e=>{this._dbReady=!0,e.onversionchange=()=>{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)("[IDBCache] DB schema upgraded in another tab \u2014 closing local connection."),e.close(),this._dbReady=!1}}).catch(e=>{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:e,message:"IndexedDB initialization failed: "+e?.message})})}get IsReady(){return this._dbReady}isKnownCategory(e){const t=`mj:${e}`;return Y.includes(t)}getStoreName(e){const t=e||$;return this.isKnownCategory(t)?`mj:${t}`:"mj:default"}getStoreKey(e,t){const r=t||$;return this.isKnownCategory(r)?e:`[${r}]:${e}`}async SetItem(e,t,r){try{const s=await this.dbPromise,n=this.getStoreName(r),a=this.getStoreKey(e,r),i=s.transaction(n,"readwrite");await i.objectStore(n).put(t,a),await i.done}catch(s){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:s,message:s?.message})}}async GetItem(e,t){try{const r=await this.dbPromise,s=this.getStoreName(t),n=this.getStoreKey(e,t),a=await r.transaction(s).objectStore(s).get(n);return a===void 0?null:a}catch(r){return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:r,message:r?.message}),null}}async GetItems(e,t){const r=new Map;if(e.length===0)return r;try{const s=await this.dbPromise,n=this.getStoreName(t),a=Array.from(new Set(e)),i=a.map(f=>this.getStoreKey(f,t)),o=s.transaction(n,"readonly"),m=o.objectStore(n),u=i.map(f=>m.get(f)),h=await Promise.all(u);await o.done;for(let f=0;f<a.length;f++){const y=h[f];r.set(a[f],y===void 0?null:y)}return r}catch(s){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:s,message:s?.message});for(const n of new Set(e))r.set(n,null);return r}}async Remove(e,t){try{const r=await this.dbPromise,s=this.getStoreName(t),n=this.getStoreKey(e,t),a=r.transaction(s,"readwrite");await a.objectStore(s).delete(n),await a.done}catch(r){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:r,message:r?.message})}}async ClearCategory(e){try{const t=await this.dbPromise,r=e||$,s=this.getStoreName(e);if(this.isKnownCategory(r)){const n=t.transaction(s,"readwrite");await n.objectStore(s).clear(),await n.done}else{const n=`[${r}]:`,a=t.transaction("mj:default","readwrite"),i=a.objectStore("mj:default"),o=await i.getAllKeys();for(const m of o)typeof m=="string"&&m.startsWith(n)&&await i.delete(m);await a.done}}catch(t){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:t,message:t?.message})}}async GetCategoryKeys(e){try{const t=await this.dbPromise,r=e||$,s=this.getStoreName(e),i=await t.transaction(s,"readonly").objectStore(s).getAllKeys();if(this.isKnownCategory(r))return i.map(m=>String(m));const o=`[${r}]:`;return i.map(m=>String(m)).filter(m=>m.startsWith(o)).map(m=>m.slice(o.length))}catch(t){return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:t,message:t?.message}),[]}}}const b=new A,Ne=(0,graphql_request__WEBPACK_IMPORTED_MODULE_0__/* .gql */ .J1)`subscription RemoteOperationProgress($channelId: ID!) {
365
365
  RemoteOperationProgress(channelId: $channelId) {
366
366
  ChannelId
367
367
  ProgressJSON
@@ -23018,8 +23018,9 @@ var RowLevelSecurityFilterInfo = /*#__PURE__*/function (_BaseInfo4) {
23018
23018
  for (var i = 0; i < keys.length; i++) {
23019
23019
  var key = keys[i];
23020
23020
  var val = user[key];
23021
- if (val !== null && securityInfo_typeof(val) !== 'object') {
23022
- ret = ret.replace(new RegExp("{{User".concat(key, "}}"), 'g'), String(val));
23021
+ if (val !== null && val !== undefined && securityInfo_typeof(val) !== 'object') {
23022
+ var safeVal = String(val).replace(/'/g, "''");
23023
+ ret = ret.replace(new RegExp("{{User".concat(key, "}}"), 'g'), safeVal);
23023
23024
  }
23024
23025
  }
23025
23026
  // Per-session magic-link resource scope. Fail-closed: an absent scope resolves
@@ -55796,11 +55797,17 @@ var DatabaseProviderBase = /*#__PURE__*/function (_ProviderBase) {
55796
55797
  }, {
55797
55798
  key: "ValidateUserProvidedSQLClause",
55798
55799
  value: function ValidateUserProvidedSQLClause(clause) {
55799
- // Remove string literals to avoid false positives
55800
- var stringLiteralPattern = /(['"])(?:(?=(\\?))\2[\s\S])*?\1/g;
55801
- var clauseWithoutStrings = clause.replace(stringLiteralPattern, '');
55800
+ // Remove string literals to avoid false positives.
55801
+ //
55802
+ // 🚨 SECURITY: this uses the SHARED stripper in @memberjunction/global. It must match how
55803
+ // SQL Server / PostgreSQL actually parse literals — see StripSQLStringLiterals for the full
55804
+ // rationale and the backslash-escape bypass it exists to prevent. Do NOT inline a regex here;
55805
+ // an inline copy is exactly how this screen and SQLExpressionValidator drifted apart before.
55806
+ var clauseWithoutStrings = (0,dist/* StripSQLStringLiterals */.SN)(clause);
55802
55807
  var lowerClause = clauseWithoutStrings.toLowerCase();
55803
- var forbiddenPatterns = [/\binsert\b/, /\bupdate\b/, /\bdelete\b/, /\bexec\b/, /\bexecute\b/, /\bdrop\b/, /--/, /\/\*/, /\*\//, /\bunion\b/, /\bxp_/, /;/];
55808
+ var forbiddenPatterns = [/\binsert\b/, /\bupdate\b/, /\bdelete\b/, /\bexec\b/, /\bexecute\b/, /\bdrop\b/, /--/, /\/\*/, /\*\//, /\bunion\b/, /\bxp_/, /;/,
55809
+ // Time-based blind injection vector — no legitimate filter/order-by clause uses WAITFOR.
55810
+ /\bwaitfor\b/];
55804
55811
  for (var _i = 0, _forbiddenPatterns = forbiddenPatterns; _i < _forbiddenPatterns.length; _i++) {
55805
55812
  var pattern = _forbiddenPatterns[_i];
55806
55813
  if (pattern.test(lowerClause)) return false;
@@ -124267,6 +124274,7 @@ __webpack_require__.d(__webpack_exports__, {
124267
124274
  fK: () => (/* reexport */ RequiresSubclass),
124268
124275
  rH: () => (/* reexport */ SQLExpressionValidator),
124269
124276
  NG: () => (/* reexport */ SafeJSONParse),
124277
+ SN: () => (/* reexport */ StripSQLStringLiterals),
124270
124278
  jd: () => (/* reexport */ UUIDsEqual),
124271
124279
  Om: () => (/* reexport */ ValidationErrorInfo),
124272
124280
  wX: () => (/* reexport */ ValidationErrorType),
@@ -124275,7 +124283,7 @@ __webpack_require__.d(__webpack_exports__, {
124275
124283
  gZ: () => (/* reexport */ uuidv4)
124276
124284
  });
124277
124285
 
124278
- // UNUSED EXPORTS: ALLOWED_SQL_FUNCTIONS, BuildCronExpression, CRON_DAY_NAMES, ClassFactory, ClassIsOptionalKeyedSpecialization, ClassRegistration, ClassRequiresSubclass, CleanJSON, CleanJavaScript, ConvertMarkdownStringToHtmlList, CopyScalarsAndArrays, DANGEROUS_SQL_KEYWORDS, DEFAULT_RICH_TEXT_SCAN_LENGTH, DeepDiffer, DefaultCronSchedule, DeprecationWarningManager, DescribeCronExpression, DiffChangeType, ENCRYPTED_SENTINEL, EscapeHTML, FULL_QUERY_ALLOWED_KEYWORDS, FieldRulesEvaluator, FieldTransformEngine, FormatTimeOfDay, GetClassInheritance, GetClassName, GetFieldTransform, GetFullClassHierarchy, GetRootClass, GetSuperclass, HighlightSearchMatches, InvokeManualResize, IsClassConstructor, IsDescendantClassOf, IsEncryptedSentinel, IsOnlyTimezoneShift, IsPlausibleCronExpression, IsRootClass, IsSubclassOf, IsValidUUID, IsValueEncrypted, JSONValidator, KeyedSerialTaskQueue, MJEvent, MJGlobalProperty, OPTIONAL_KEYED_SPECIALIZATION_KEY, ObjectCache, ObjectCacheEntry, Ordinal, ParseCronExpression, ParseJSONRecursive, REQUIRES_SUBCLASS_KEY, RegisterClassEx, RegisterFieldTransform, SafeExpressionEvaluator, ShutdownRegistry, ToJSONSafe, adjustCasing, compareStringsByLine, convertCamelCaseToHaveSpaces, createDisplayName, defaultExpressionEvaluator, detectRichTextFormat, ensureRegExp, ensureRegExps, generatePluralName, getIrregularPlural, getValueAtPath, matchesAllPatterns, matchesAnyPattern, parsePattern, parsePatterns, replaceAllSpaces, resolveMappingRef, resolveValueMapping, stripTrailingChars, stripWhitespace
124286
+ // UNUSED EXPORTS: ALLOWED_SQL_FUNCTIONS, BLOCKED_SYSTEM_OBJECT_PATTERNS, BuildCronExpression, CRON_DAY_NAMES, ClassFactory, ClassIsOptionalKeyedSpecialization, ClassRegistration, ClassRequiresSubclass, CleanJSON, CleanJavaScript, ConvertMarkdownStringToHtmlList, CopyScalarsAndArrays, DANGEROUS_SQL_KEYWORDS, DEFAULT_RICH_TEXT_SCAN_LENGTH, DeepDiffer, DefaultCronSchedule, DeprecationWarningManager, DescribeCronExpression, DiffChangeType, ENCRYPTED_SENTINEL, EscapeHTML, FULL_QUERY_ALLOWED_KEYWORDS, FieldRulesEvaluator, FieldTransformEngine, FormatTimeOfDay, GetClassInheritance, GetClassName, GetFieldTransform, GetFullClassHierarchy, GetRootClass, GetSuperclass, HighlightSearchMatches, InvokeManualResize, IsClassConstructor, IsDescendantClassOf, IsEncryptedSentinel, IsOnlyTimezoneShift, IsPlausibleCronExpression, IsRootClass, IsSubclassOf, IsValidUUID, IsValueEncrypted, JSONValidator, KeyedSerialTaskQueue, MJEvent, MJGlobalProperty, OPTIONAL_KEYED_SPECIALIZATION_KEY, ObjectCache, ObjectCacheEntry, Ordinal, ParseCronExpression, ParseJSONRecursive, REQUIRES_SUBCLASS_KEY, RegisterClassEx, RegisterFieldTransform, SafeExpressionEvaluator, ShutdownRegistry, ToJSONSafe, adjustCasing, compareStringsByLine, convertCamelCaseToHaveSpaces, createDisplayName, defaultExpressionEvaluator, detectRichTextFormat, ensureRegExp, ensureRegExps, generatePluralName, getIrregularPlural, getValueAtPath, matchesAllPatterns, matchesAnyPattern, parsePattern, parsePatterns, replaceAllSpaces, resolveMappingRef, resolveValueMapping, stripTrailingChars, stripWhitespace
124279
124287
 
124280
124288
  ;// ../../MJGlobal/dist/ClassUtils.js
124281
124289
  /**
@@ -129136,6 +129144,63 @@ var FULL_QUERY_ALLOWED_KEYWORDS = [
129136
129144
  // standalone SELECT statement, so allowing FOR in full-query context is safe.
129137
129145
  // (FOR UPDATE remains blocked via the independent UPDATE keyword.)
129138
129146
  'FOR'];
129147
+ /**
129148
+ * System catalog / metadata objects that must never be referenced from a user-supplied
129149
+ * expression or ad-hoc query, in ANY context (including `full_query`). These sit outside
129150
+ * MemberJunction's entity-permission model, so allowing them turns a validated SELECT into
129151
+ * a schema-enumeration and credential-exfiltration primitive
129152
+ * (e.g. `SELECT name, password_hash FROM sys.sql_logins`,
129153
+ * `SELECT * FROM INFORMATION_SCHEMA.COLUMNS`, `SELECT * FROM pg_catalog.pg_authid`).
129154
+ * String literals are stripped before this check runs, so a literal value like `'sys.x'` is safe.
129155
+ */
129156
+ var BLOCKED_SYSTEM_OBJECT_PATTERNS = [/\bSYS\s*\.\s*\w/i,
129157
+ // SQL Server system catalog schema: sys.sql_logins, sys.objects, sys.fn_*, ...
129158
+ /\bINFORMATION_SCHEMA\b/i,
129159
+ // ANSI catalog views — schema/table/column enumeration
129160
+ /\bSYSLOGINS\b/i,
129161
+ // legacy SQL Server logins view
129162
+ /\bPG_CATALOG\s*\./i,
129163
+ // PostgreSQL system catalog schema
129164
+ /\bPG_(AUTHID|SHADOW|USER|ROLES)\b/i // PostgreSQL credential / role catalogs
129165
+ ];
129166
+ /**
129167
+ * Matches SQL string literals the way SQL Server and PostgreSQL (with the default
129168
+ * `standard_conforming_strings=on`) actually parse them: a literal is closed by the next
129169
+ * single quote, `''` is an embedded quote, and a backslash is an ORDINARY character that
129170
+ * does NOT escape the closing quote. Double-quoted runs are matched with the same doubling
129171
+ * rule so a delimited identifier can't hide a payload either.
129172
+ *
129173
+ * @see StripSQLStringLiterals — use that, not this constant, so every caller gets the
129174
+ * documented semantics and the two validators in MJ can never drift apart again.
129175
+ */
129176
+ var SQL_STRING_LITERAL_PATTERN = /'(?:[^']|'')*'|"(?:[^"]|"")*"/g;
129177
+ /**
129178
+ * Removes SQL string literals from a clause or expression so that a keyword denylist can be
129179
+ * applied to the *code* portion without tripping over keywords that appear inside quoted data
129180
+ * (e.g. `Comments LIKE '%--%'`).
129181
+ *
129182
+ * 🚨 SECURITY — this is the single implementation of literal-stripping for MJ's SQL screens, and
129183
+ * it MUST stay byte-for-byte consistent with how the database parses literals. If the stripper
129184
+ * removes a span the database does NOT treat as a literal, everything hidden inside that span
129185
+ * bypasses the denylist while the database still executes it.
129186
+ *
129187
+ * An earlier version of this logic (duplicated in two places, which is how it survived) honored
129188
+ * **backslash escaping** — `/(['"])(?:(?=(\\?))\2[\s\S])*?\1/g`. SQL Server and PostgreSQL do not
129189
+ * treat `\` as an escape character, so `x = 'a\') ; DROP TABLE Users; --'` was swallowed whole as
129190
+ * one "literal" and stripped to `x = `, which passed every denylist — while the database closed
129191
+ * the literal at the real quote and executed the stacked statement.
129192
+ *
129193
+ * **Do NOT reintroduce backslash-escape handling here, and do NOT inline a second copy of this
129194
+ * regex anywhere else — call this function.**
129195
+ *
129196
+ * @param sql The clause, expression, or query to strip literals from
129197
+ * @returns The input with every complete string literal removed. An UNTERMINATED literal is left
129198
+ * in place on purpose: the stray quote and everything after it stay visible to the
129199
+ * denylist rather than being silently swallowed.
129200
+ */
129201
+ function StripSQLStringLiterals(sql) {
129202
+ return sql.replace(SQL_STRING_LITERAL_PATTERN, '');
129203
+ }
129139
129204
  /**
129140
129205
  * Safe SQL functions allowed in expressions, organized by category
129141
129206
  */
@@ -129241,14 +129306,14 @@ var SQLExpressionValidator = /*#__PURE__*/function (_BaseSingleton) {
129241
129306
  }
129242
129307
  /**
129243
129308
  * Remove string literals to avoid false positives in keyword detection.
129244
- * Handles both single and double quoted strings with escaped quotes.
129309
+ *
129310
+ * 🚨 SECURITY: delegates to {@link StripSQLStringLiterals} — read the warning there before
129311
+ * changing anything about how literals are matched. This must never grow its own regex again.
129245
129312
  */
129246
129313
  }, {
129247
129314
  key: "removeStringLiterals",
129248
129315
  value: function removeStringLiterals(expression) {
129249
- // Match both single and double quoted strings, handling escaped quotes
129250
- var stringPattern = /(['"])(?:(?=(\\?))\2[\s\S])*?\1/g;
129251
- return expression.replace(stringPattern, '');
129316
+ return StripSQLStringLiterals(expression);
129252
129317
  }
129253
129318
  /**
129254
129319
  * Check for dangerous SQL patterns that indicate injection attempts
@@ -129308,15 +129373,29 @@ var SQLExpressionValidator = /*#__PURE__*/function (_BaseSingleton) {
129308
129373
  };
129309
129374
  }
129310
129375
  }
129311
- // Check statement terminator (prevents multi-statement injection).
129312
- // For full_query context, strip comments first (a trailing semicolon may be followed by
129313
- // an inline comment like `ORDER BY x DESC; -- highest first`), then strip the trailing
129314
- // semicolon. Only reject if semicolons remain mid-statement, indicating injection.
129376
+ // Block references to database system catalogs / metadata objects in ALL contexts
129377
+ // (including full_query). These live outside MemberJunction's entity-permission model, so
129378
+ // permitting them turns a validated SELECT into a schema-enumeration / credential-exfiltration
129379
+ // primitive. String literals were already stripped upstream, so legitimate literal values are safe.
129315
129380
  } catch (err) {
129316
129381
  _iterator.e(err);
129317
129382
  } finally {
129318
129383
  _iterator.f();
129319
129384
  }
129385
+ for (var _i = 0, _BLOCKED_SYSTEM_OBJEC = BLOCKED_SYSTEM_OBJECT_PATTERNS; _i < _BLOCKED_SYSTEM_OBJEC.length; _i++) {
129386
+ var sysPattern = _BLOCKED_SYSTEM_OBJEC[_i];
129387
+ if (sysPattern.test(textToCheck)) {
129388
+ return {
129389
+ valid: false,
129390
+ error: 'Access to database system catalogs / metadata objects is not allowed',
129391
+ trigger: 'system-object'
129392
+ };
129393
+ }
129394
+ }
129395
+ // Check statement terminator (prevents multi-statement injection).
129396
+ // For full_query context, strip comments first (a trailing semicolon may be followed by
129397
+ // an inline comment like `ORDER BY x DESC; -- highest first`), then strip the trailing
129398
+ // semicolon. Only reject if semicolons remain mid-statement, indicating injection.
129320
129399
  var textForSemicolonCheck = isFullQuery ? this.stripSQLComments(expression).replace(/;\s*$/, '') // strip comments then trailing semicolon
129321
129400
  : expression;
129322
129401
  if (textForSemicolonCheck.includes(';')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/react-runtime",
3
- "version": "5.51.0",
3
+ "version": "5.51.1",
4
4
  "description": "Platform-agnostic React component runtime for MemberJunction. Provides core compilation, registry, and execution capabilities for React components in any JavaScript environment.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -29,11 +29,11 @@
29
29
  },
30
30
  "homepage": "https://github.com/MemberJunction/MJ#readme",
31
31
  "dependencies": {
32
- "@memberjunction/core": "5.51.0",
33
- "@memberjunction/global": "5.51.0",
34
- "@memberjunction/interactive-component-types": "5.51.0",
35
- "@memberjunction/core-entities": "5.51.0",
36
- "@memberjunction/graphql-dataprovider": "5.51.0",
32
+ "@memberjunction/core": "5.51.1",
33
+ "@memberjunction/global": "5.51.1",
34
+ "@memberjunction/interactive-component-types": "5.51.1",
35
+ "@memberjunction/core-entities": "5.51.1",
36
+ "@memberjunction/graphql-dataprovider": "5.51.1",
37
37
  "@babel/standalone": "^7.29.1",
38
38
  "rxjs": "^7.8.2"
39
39
  },