Skip to content

fix: Instance comparison with instanceof is not realm-safe#10225

Merged
mtrezza merged 12 commits intoparse-community:alphafrom
mtrezza:fix/instanceof
Mar 16, 2026
Merged

fix: Instance comparison with instanceof is not realm-safe#10225
mtrezza merged 12 commits intoparse-community:alphafrom
mtrezza:fix/instanceof

Conversation

@mtrezza
Copy link
Member

@mtrezza mtrezza commented Mar 16, 2026

Pull Request

Issue

Instance comparison with instanceof is not realm-safe. This may cause issues in certain test or production setups.

Approach

  • Replace occurrences of instanceof with safe alternatives.
  • Add lint rule to prevent future use of instanceof.

Tasks

  • Add tests
  • Add changes to documentation (guides, repository pages, code comments)
  • Add security check
  • Add new Parse Error codes to Parse JS SDK

Summary by CodeRabbit

  • New Features

    • Added cross-realm-safe type-checking utilities for Date, RegExp, Map, Set, native Error, Promise/thenable, and generic object detection.
  • Improvements

    • Replaced fragile instanceof checks with the new, safer utilities and Array.isArray/Buffer.isBuffer where appropriate for more reliable runtime behavior.
  • Tests

    • Expanded unit tests to cover cross-realm, edge-case, and prototype-pollution scenarios.
  • Chores

    • Added lint rules to enforce use of the safer type-check utilities.

@parse-github-assistant
Copy link

parse-github-assistant bot commented Mar 16, 2026

🚀 Thanks for opening this pull request! We appreciate your effort in improving the project. Please let us know once your pull request is ready for review.

Tip

  • Keep pull requests small. Large PRs will be rejected. Break complex features into smaller, incremental PRs.
  • Use Test Driven Development. Write failing tests before implementing functionality. Ensure tests pass.
  • Group code into logical blocks. Add a short comment before each block to explain its purpose.
  • We offer conceptual guidance. Coding is up to you. PRs must be merge-ready for human review.
  • Our review focuses on concept, not quality. PRs with code issues will be rejected. Use an AI agent.
  • Human review time is precious. Avoid review ping-pong. Inspect and test your AI-generated code.

Note

Please respond to review comments from AI agents just like you would to comments from a human reviewer. Let the reviewer resolve their own comments, unless they have reviewed and accepted your commit, or agreed with your explanation for why the feedback was incorrect.

Caution

Pull requests must be written using an AI agent with human supervision. Pull requests written entirely by a human will likely be rejected, because of lower code quality, higher review effort and the higher risk of introducing bugs. Please note that AI review comments on this pull request alone do not satisfy this requirement.

@parseplatformorg
Copy link
Contributor

parseplatformorg commented Mar 16, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@coderabbitai
Copy link

coderabbitai bot commented Mar 16, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d8750ecf-2b12-46b5-ad48-efb305eaf42f

📥 Commits

Reviewing files that changed from the base of the PR and between ad5d0e9 and 837692d.

📒 Files selected for processing (21)
  • eslint.config.js
  • spec/AdapterLoader.spec.js
  • spec/GridFSBucketStorageAdapter.spec.js
  • spec/MongoStorageAdapter.spec.js
  • spec/ParseAPI.spec.js
  • spec/Utils.spec.js
  • spec/eslint.config.js
  • spec/helper.js
  • spec/rest.spec.js
  • src/Adapters/Storage/Mongo/MongoTransform.js
  • src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
  • src/Config.js
  • src/Controllers/DatabaseController.js
  • src/Controllers/FilesController.js
  • src/Controllers/LiveQueryController.js
  • src/Controllers/SchemaController.js
  • src/GraphQL/transformers/query.js
  • src/RestQuery.js
  • src/Routers/FilesRouter.js
  • src/Utils.js
  • src/middlewares.js
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/middlewares.js
  • spec/eslint.config.js
  • spec/ParseAPI.spec.js
  • spec/GridFSBucketStorageAdapter.spec.js
  • eslint.config.js
  • src/Routers/FilesRouter.js
  • src/Utils.js
  • spec/AdapterLoader.spec.js

📝 Walkthrough

Walkthrough

Adds realm-safe type-checking helpers to Utils (isDate, isRegExp, isMap, isSet, isNativeError, isObject), replaces isPromise with a duck-typed, pollution-safe implementation, updates call sites to use these helpers, adds tests, and extends ESLint rules to discourage instanceof checks (including Array).

Changes

Cohort / File(s) Summary
Utils core
src/Utils.js
Adds isDate, isRegExp, isMap, isSet, isNativeError, isObject; replaces isPromise with a duck‑typed, Object.prototype‑pollution‑safe implementation; serialization logic updated to use these helpers.
Unit tests
spec/Utils.spec.js
Adds extensive tests for the new/updated Utils type‑checkers, including cross‑realm cases via vm.runInNewContext and Object.prototype.then pollution scenarios.
ESLint rules
eslint.config.js, spec/eslint.config.js
Adds no-restricted-syntax selectors forbidding instanceof for Date/RegExp/Error/Promise/Map/Object/Set/Buffer/Array with messages recommending Utils.is*, Buffer.isBuffer, or Array.isArray.
Storage adapters (Mongo/Postgres)
src/Adapters/Storage/Mongo/MongoStorageAdapter.js, src/Adapters/Storage/Mongo/MongoTransform.js, src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
Replaces instanceof Date / instanceof RegExp checks with Utils.isDate / Utils.isRegExp; replaces instanceof Array with Array.isArray; cleans duplicate imports and centralizes type detection.
GraphQL / Config / Controllers
src/GraphQL/loaders/defaultGraphQLTypes.js, src/Config.js, src/Controllers/ParseGraphQLController.js
Switches Date/RegExp/Promise detection to Utils.isDate / Utils.isRegExp / Utils.isPromise in parsing, serialization, and validation logic.
Runtime error handling & triggers
src/StatusHandler.js, src/triggers.js
Replaces instanceof Error checks with Utils.isNativeError(...) when preserving or mapping native errors.
Promise handling sites
src/Routers/PagesRouter.js, src/Security/Check.js
Replaces instanceof Promise checks with Utils.isPromise(...) to support thenables/duck‑typed promises.
Buffer / object runtime checks
src/Routers/FilesRouter.js, src/middlewares.js, spec/GridFSBucketStorageAdapter.spec.js
Replaces instanceof Buffer with Buffer.isBuffer(...) and instanceof Object with Utils.isObject(...); tests updated accordingly.
Array checks and various controllers
src/Controllers/DatabaseController.js, src/Controllers/FilesController.js, src/Controllers/LiveQueryController.js, src/Controllers/SchemaController.js, src/GraphQL/transformers/query.js, src/RestQuery.js
Replaces instanceof Array with Array.isArray(...) across validation, transformation, and query code paths to improve cross‑realm correctness.
Broad test updates
spec/*.spec.js (e.g. spec/CloudCode.spec.js, spec/MongoStorageAdapter.spec.js, spec/MongoTransform.spec.js, spec/ParseAPI.spec.js, spec/ParseGraphQLServer.spec.js, spec/ParseQuery.spec.js, spec/ParseUser.spec.js, spec/PushController.spec.js, spec/AdapterLoader.spec.js, spec/GridFSBucketStorageAdapter.spec.js, spec/ParseUser.spec.js, spec/ParseAPI.spec.js)
Adds Utils imports and replaces instanceof Date/instanceof Object/instanceof Array/instanceof Buffer assertions with Utils.isDate/Utils.isObject/Array.isArray/Buffer.isBuffer as appropriate across test suite.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • Moumouls
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly and specifically describes the main change: replacing unsafe instanceof comparisons with realm-safe alternatives.
Description check ✅ Passed The pull request description follows the template with Issue, Approach, and Tasks sections completed, though security check and error codes tasks are marked as not applicable.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/Utils.js (1)

498-515: Consider updating getCircularReplacer to use the new realm-safe helpers.

This method still uses instanceof Map and instanceof Set (lines 501, 504), which contradicts the PR's objective of replacing instanceof with realm-safe alternatives. Cross-realm Map/Set instances would not be correctly serialized.

♻️ Proposed fix
   static getCircularReplacer() {
     const seen = new WeakSet();
     return (key, value) => {
-      if (value instanceof Map) {
+      if (Utils.isMap(value)) {
         return Object.fromEntries(value);
       }
-      if (value instanceof Set) {
+      if (Utils.isSet(value)) {
         return Array.from(value);
       }
       if (typeof value === 'object' && value !== null) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Utils.js` around lines 498 - 515, The getCircularReplacer function uses
instanceof Map/Set which fails for cross-realm objects; update it to use
realm-safe checks (e.g., imported helpers like isMap/isSet or a toString-based
check) instead of instanceof when inspecting value, keep the existing handling
for Map->Object.fromEntries and Set->Array.from and continue using the seen
WeakSet to detect cycles; specifically replace the instanceof Map and instanceof
Set checks in getCircularReplacer with calls to the realm-safe helpers (or
Object.prototype.toString checks) so cross-realm Map/Set instances are
serialized correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/Utils.js`:
- Around line 498-515: The getCircularReplacer function uses instanceof Map/Set
which fails for cross-realm objects; update it to use realm-safe checks (e.g.,
imported helpers like isMap/isSet or a toString-based check) instead of
instanceof when inspecting value, keep the existing handling for
Map->Object.fromEntries and Set->Array.from and continue using the seen WeakSet
to detect cycles; specifically replace the instanceof Map and instanceof Set
checks in getCircularReplacer with calls to the realm-safe helpers (or
Object.prototype.toString checks) so cross-realm Map/Set instances are
serialized correctly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 746f52b6-8ccf-4d2e-92a7-df111b705c9a

📥 Commits

Reviewing files that changed from the base of the PR and between cdc2551 and 9154cfe.

📒 Files selected for processing (2)
  • spec/Utils.spec.js
  • src/Utils.js

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Controllers/ParseGraphQLController.js (1)

305-312: ⚠️ Potential issue | 🟠 Major

Replace realm-unsafe Promise check with realm-safe utility.

Line 311 uses instanceof Promise, which fails across realms. Replace with Utils.isPromise(obj), which is already available and properly implements realm-safe duck-typing.

🔧 Suggested patch
 const isValidSimpleObject = function (obj): boolean {
   return (
     typeof obj === 'object' &&
     !Array.isArray(obj) &&
     obj !== null &&
     Utils.isDate(obj) !== true &&
-    obj instanceof Promise !== true
+    Utils.isPromise(obj) !== true
   );
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Controllers/ParseGraphQLController.js` around lines 305 - 312, The
isValidSimpleObject function currently uses a realm-unsafe check "obj instanceof
Promise" (inside isValidSimpleObject) which breaks across realms; replace that
check with the realm-safe utility Utils.isPromise(obj). Update the condition in
isValidSimpleObject to call Utils.isPromise(obj) instead of using instanceof so
promise detection uses the existing duck-typed helper.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@spec/Utils.spec.js`:
- Around line 316-319: The test intentionally uses a cross-realm instanceof
check (crossRealmRegExp instanceof RegExp) which triggers the lint
restricted-syntax rule; add an inline ESLint disable comment immediately above
that assertion (same style as the existing inline disable on Line 298) to bypass
the rule for this specific line so the test keeps its intentional check while
avoiding lint failures; locate the assertion in the 'should return true for a
cross-realm RegExp' test that creates crossRealmRegExp via vm.runInNewContext
and add the single-line disable comment before the instanceof RegExp
expectation.

---

Outside diff comments:
In `@src/Controllers/ParseGraphQLController.js`:
- Around line 305-312: The isValidSimpleObject function currently uses a
realm-unsafe check "obj instanceof Promise" (inside isValidSimpleObject) which
breaks across realms; replace that check with the realm-safe utility
Utils.isPromise(obj). Update the condition in isValidSimpleObject to call
Utils.isPromise(obj) instead of using instanceof so promise detection uses the
existing duck-typed helper.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7f34bb38-76cd-4ae0-a662-89c013b9557e

📥 Commits

Reviewing files that changed from the base of the PR and between 9154cfe and bbcd5f9.

📒 Files selected for processing (9)
  • eslint.config.js
  • spec/Utils.spec.js
  • spec/eslint.config.js
  • src/Adapters/Storage/Mongo/MongoStorageAdapter.js
  • src/Adapters/Storage/Mongo/MongoTransform.js
  • src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
  • src/Config.js
  • src/Controllers/ParseGraphQLController.js
  • src/GraphQL/loaders/defaultGraphQLTypes.js

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
spec/ParseGraphQLServer.spec.js (1)

8478-8567: Refactor to use async/await instead of done callback.

The test at line 8478 uses callback-style with done, and the apolloClient.mutate() call at line 8555 is not awaited. This allows the test to complete before the mutation finishes, defeating the test's purpose. Convert to async/await to match the suite's established pattern and ensure proper error propagation.

♻️ Suggested refactor
-        it('should accept different params', done => {
+        it('should accept different params', async () => {
           Parse.Cloud.define('hello', async req => {
             expect(Utils.isDate(req.params.date)).toBe(true);
             expect(req.params.date.getTime()).toBe(1463907600000);
             expect(Utils.isDate(req.params.dateList[0])).toBe(true);
             expect(req.params.dateList[0].getTime()).toBe(1463907600000);
             expect(Utils.isDate(req.params.complexStructure.date[0])).toBe(true);
             expect(req.params.complexStructure.date[0].getTime()).toBe(1463907600000);
             expect(Utils.isDate(req.params.complexStructure.deepDate.date[0])).toBe(true);
             expect(req.params.complexStructure.deepDate.date[0].getTime()).toBe(1463907600000);
             expect(Utils.isDate(req.params.complexStructure.deepDate2[0].date)).toBe(true);
             expect(req.params.complexStructure.deepDate2[0].date.getTime()).toBe(1463907600000);
             // Regression for `#2294`
             expect(req.params.file instanceof Parse.File).toBe(true);
             expect(req.params.file.url()).toEqual('https://some.url');
             // Regression for `#2204`
             expect(req.params.array).toEqual(['a', 'b', 'c']);
             expect(Array.isArray(req.params.array)).toBe(true);
             expect(req.params.arrayOfArray).toEqual([
               ['a', 'b', 'c'],
               ['d', 'e', 'f'],
             ]);
             expect(Array.isArray(req.params.arrayOfArray)).toBe(true);
             expect(Array.isArray(req.params.arrayOfArray[0])).toBe(true);
             expect(Array.isArray(req.params.arrayOfArray[1])).toBe(true);
           });
@@
-          apolloClient.mutate({
+          await apolloClient.mutate({
             mutation: gql`
               mutation CallFunction($params: Object) {
                 callCloudCode(input: { functionName: hello, params: $params }) {
                   result
                 }
               }
             `,
             variables: {
               params,
             },
           });
         });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@spec/ParseGraphQLServer.spec.js` around lines 8478 - 8567, The test "should
accept different params" uses the callback-style done and calls
apolloClient.mutate(...) without awaiting it, causing the test to finish before
the mutation completes; convert the test to an async function (replace the done
callback) and await the apolloClient.mutate(...) call so the
Parse.Cloud.define('hello', ...) assertions run before the test completes;
update the test declaration (the it(...) callback) to async and await
apolloClient.mutate(...) to ensure proper error propagation and timing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@spec/Utils.spec.js`:
- Around line 396-416: In the tests around Utils.isPromise where you
intentionally set Object.prototype.then and create objects with a then property,
add explicit Biome ignore comments to suppress the lint rule
lint/suspicious/noThenProperty; specifically insert a biome-ignore comment (e.g.
// biome-ignore lint/suspicious/noThenProperty) immediately above the lines that
assign Object.prototype.then = () => {} and above the expect(Utils.isPromise({
then: () => {} })) assertion so the intentional prototype pollution and thenable
creation in the Utils.isPromise tests are exempted from the linter.

---

Nitpick comments:
In `@spec/ParseGraphQLServer.spec.js`:
- Around line 8478-8567: The test "should accept different params" uses the
callback-style done and calls apolloClient.mutate(...) without awaiting it,
causing the test to finish before the mutation completes; convert the test to an
async function (replace the done callback) and await the
apolloClient.mutate(...) call so the Parse.Cloud.define('hello', ...) assertions
run before the test completes; update the test declaration (the it(...)
callback) to async and await apolloClient.mutate(...) to ensure proper error
propagation and timing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f45650c9-62b8-42c2-ab0b-ec0d1b6f1aaa

📥 Commits

Reviewing files that changed from the base of the PR and between bbcd5f9 and 4e959d7.

📒 Files selected for processing (13)
  • eslint.config.js
  • spec/CloudCode.spec.js
  • spec/MongoStorageAdapter.spec.js
  • spec/MongoTransform.spec.js
  • spec/ParseAPI.spec.js
  • spec/ParseGraphQLServer.spec.js
  • spec/ParseQuery.spec.js
  • spec/ParseUser.spec.js
  • spec/PushController.spec.js
  • spec/Utils.spec.js
  • spec/eslint.config.js
  • src/StatusHandler.js
  • src/triggers.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • spec/eslint.config.js

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
eslint.config.js (2)

45-67: Consider adding instanceof Set to the restricted syntax rules.

Same as spec/eslint.config.js - the PR adds Utils.isSet() but doesn't include a corresponding lint rule. Consider adding it for consistency.

🔧 Suggested patch
         {
           selector: "BinaryExpression[operator='instanceof'][right.name='Map']",
           message: "Use Utils.isMap() instead of instanceof Map (cross-realm safe).",
         },
+        {
+          selector: "BinaryExpression[operator='instanceof'][right.name='Set']",
+          message: "Use Utils.isSet() instead of instanceof Set (cross-realm safe).",
+        },
       ]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@eslint.config.js` around lines 45 - 67, Add a rule to the
no-restricted-syntax array to forbid "instanceof Set" and point to
Utils.isSet(); specifically, add an object with selector
"BinaryExpression[operator='instanceof'][right.name='Set']" and message "Use
Utils.isSet() instead of instanceof Set (cross-realm safe)." so the lint config
is consistent with the newly added Utils.isSet().

44-44: Unrelated change: no-console rule added.

This "no-console": "warn" rule appears unrelated to the PR's objective of replacing instanceof checks with realm-safe alternatives. Consider splitting this into a separate commit or PR for clearer change tracking.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@eslint.config.js` at line 44, The change adding the ESLint rule "no-console":
"warn" is unrelated to the instanceof-to-realm-safe refactor; remove that rule
from this PR (revert the `"no-console": "warn"` change in eslint.config.js) or
move it into a separate commit/PR so the instanceof replacement changes remain
isolated and reviewable.
spec/eslint.config.js (1)

66-88: Consider adding instanceof Set to the restricted syntax rules.

The PR adds Utils.isSet() and tests for it, but the ESLint rule doesn't include a selector for instanceof Set. Consider adding it for consistency.

🔧 Suggested patch
         {
           selector: "BinaryExpression[operator='instanceof'][right.name='Map']",
           message: "Use Utils.isMap() instead of instanceof Map (cross-realm safe).",
         },
+        {
+          selector: "BinaryExpression[operator='instanceof'][right.name='Set']",
+          message: "Use Utils.isSet() instead of instanceof Set (cross-realm safe).",
+        },
       ],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@spec/eslint.config.js` around lines 66 - 88, Add a "instanceof Set"
restriction to the ESLint no-restricted-syntax rules to mirror the new
Utils.isSet() helper; specifically add a selector entry matching
BinaryExpression[operator='instanceof'][right.name='Set'] with a message
advising to use Utils.isSet() instead of instanceof Set so the rule set (the
array containing selectors for Date, RegExp, Error, Promise, Map) also blocks
Set usage consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@spec/Utils.spec.js`:
- Around line 352-356: The test "should return true for a cross-realm Set"
intentionally asserts that crossRealmSet instanceof Set is false; add the same
ESLint bypass used in nearby tests to suppress the rule for intentional
instanceof usage by placing an appropriate ESLint disable comment immediately
before the line containing expect(crossRealmSet instanceof Set).toBe(false); so
the linter ignores the instanceof check while leaving the rest of the test
(including Utils.isSet(crossRealmSet)) unchanged.

---

Nitpick comments:
In `@eslint.config.js`:
- Around line 45-67: Add a rule to the no-restricted-syntax array to forbid
"instanceof Set" and point to Utils.isSet(); specifically, add an object with
selector "BinaryExpression[operator='instanceof'][right.name='Set']" and message
"Use Utils.isSet() instead of instanceof Set (cross-realm safe)." so the lint
config is consistent with the newly added Utils.isSet().
- Line 44: The change adding the ESLint rule "no-console": "warn" is unrelated
to the instanceof-to-realm-safe refactor; remove that rule from this PR (revert
the `"no-console": "warn"` change in eslint.config.js) or move it into a
separate commit/PR so the instanceof replacement changes remain isolated and
reviewable.

In `@spec/eslint.config.js`:
- Around line 66-88: Add a "instanceof Set" restriction to the ESLint
no-restricted-syntax rules to mirror the new Utils.isSet() helper; specifically
add a selector entry matching
BinaryExpression[operator='instanceof'][right.name='Set'] with a message
advising to use Utils.isSet() instead of instanceof Set so the rule set (the
array containing selectors for Date, RegExp, Error, Promise, Map) also blocks
Set usage consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 44db3402-f90c-4a3a-a953-3b23032f3b16

📥 Commits

Reviewing files that changed from the base of the PR and between 4e959d7 and ad5d0e9.

📒 Files selected for processing (7)
  • eslint.config.js
  • spec/Utils.spec.js
  • spec/eslint.config.js
  • src/Controllers/ParseGraphQLController.js
  • src/Routers/PagesRouter.js
  • src/Security/Check.js
  • src/Utils.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Utils.js

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
eslint.config.js (1)

45-79: Consider centralizing this no-restricted-syntax list shared with spec/eslint.config.js.

This block is duplicated across both ESLint configs; extracting a shared rules constant would reduce drift risk when adding/removing realm-safe selectors later.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@eslint.config.js` around lines 45 - 79, The duplicated "no-restricted-syntax"
block (the selectors like
BinaryExpression[operator='instanceof'][right.name='Date'], RegExp, Error,
Promise, Map, Object, Set, Buffer) should be extracted into a shared constant
(e.g., REALM_SAFE_INSTANCEOF_RULES or SHARED_INSTANCEOF_SELECTORS) and imported
into both ESLint configs so they reference the same array; create a module that
exports the array of rule objects, update eslint.config.js to replace the inline
array under "no-restricted-syntax" with a reference or spread of that constant,
and likewise update spec/eslint.config.js to import and reuse the same exported
constant to avoid duplication and drift.
src/middlewares.js (1)

2-2: Suggested PR title: fix(security): replace realm-unsafe instanceof checks with realm-safe type guards.

Based on learnings: For Parse Server PRs, always suggest an Angular commit convention PR title in type(scope): description format.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/middlewares.js` at line 2, Change the PR title to follow Angular commit
convention and reflect the fix, e.g. "fix(middlewares): replace realm-unsafe
instanceof checks with realm-safe type guards"; then update src/middlewares.js
by removing any realm-unsafe instanceof usages and replacing them with
realm-safe type guards (create or use helpers in Utils such as Utils.isError,
Utils.isRequest, Utils.isResponse or similar) and update any functions/methods
that relied on instanceof to use those guards (search for "instanceof"
references in middleware handlers and validation logic and replace them with
calls to the new Utils type-guard functions).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@eslint.config.js`:
- Around line 45-79: The duplicated "no-restricted-syntax" block (the selectors
like BinaryExpression[operator='instanceof'][right.name='Date'], RegExp, Error,
Promise, Map, Object, Set, Buffer) should be extracted into a shared constant
(e.g., REALM_SAFE_INSTANCEOF_RULES or SHARED_INSTANCEOF_SELECTORS) and imported
into both ESLint configs so they reference the same array; create a module that
exports the array of rule objects, update eslint.config.js to replace the inline
array under "no-restricted-syntax" with a reference or spread of that constant,
and likewise update spec/eslint.config.js to import and reuse the same exported
constant to avoid duplication and drift.

In `@src/middlewares.js`:
- Line 2: Change the PR title to follow Angular commit convention and reflect
the fix, e.g. "fix(middlewares): replace realm-unsafe instanceof checks with
realm-safe type guards"; then update src/middlewares.js by removing any
realm-unsafe instanceof usages and replacing them with realm-safe type guards
(create or use helpers in Utils such as Utils.isError, Utils.isRequest,
Utils.isResponse or similar) and update any functions/methods that relied on
instanceof to use those guards (search for "instanceof" references in middleware
handlers and validation logic and replace them with calls to the new Utils
type-guard functions).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 72a31b80-addb-4c11-936b-8bb02d2edcff

📥 Commits

Reviewing files that changed from the base of the PR and between ad5d0e9 and 0b7541f.

📒 Files selected for processing (9)
  • eslint.config.js
  • spec/AdapterLoader.spec.js
  • spec/GridFSBucketStorageAdapter.spec.js
  • spec/ParseAPI.spec.js
  • spec/Utils.spec.js
  • spec/eslint.config.js
  • src/Routers/FilesRouter.js
  • src/Utils.js
  • src/middlewares.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Utils.js
  • spec/ParseAPI.spec.js

@mtrezza
Copy link
Member Author

mtrezza commented Mar 16, 2026

@coderabbitai resume

@coderabbitai
Copy link

coderabbitai bot commented Mar 16, 2026

✅ Actions performed

Reviews resumed.

@codecov
Copy link

codecov bot commented Mar 16, 2026

Codecov Report

❌ Patch coverage is 96.25000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.60%. Comparing base (e5e1f5b) to head (837692d).
⚠️ Report is 5 commits behind head on alpha.

Files with missing lines Patch % Lines
src/Adapters/Storage/Mongo/MongoTransform.js 96.00% 1 Missing ⚠️
src/Controllers/DatabaseController.js 83.33% 1 Missing ⚠️
src/GraphQL/transformers/query.js 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            alpha   #10225      +/-   ##
==========================================
+ Coverage   92.18%   92.60%   +0.41%     
==========================================
  Files         192      192              
  Lines       16307    16322      +15     
  Branches      199      199              
==========================================
+ Hits        15033    15115      +82     
+ Misses       1253     1190      -63     
+ Partials       21       17       -4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mtrezza mtrezza merged commit 51efb1e into parse-community:alpha Mar 16, 2026
21 of 24 checks passed
parseplatformorg pushed a commit that referenced this pull request Mar 16, 2026
# [9.6.0-alpha.32](9.6.0-alpha.31...9.6.0-alpha.32) (2026-03-16)

### Bug Fixes

* Instance comparison with `instanceof` is not realm-safe ([#10225](#10225)) ([51efb1e](51efb1e))
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 9.6.0-alpha.32

@parseplatformorg parseplatformorg added the state:released-alpha Released as alpha version label Mar 16, 2026
@mtrezza mtrezza deleted the fix/instanceof branch March 16, 2026 21:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state:released-alpha Released as alpha version

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants