parse-community / parse-community/parse-server

allowCustomObjectId accepts an operation as objectId and creates an unreachable user

Open
#10,639 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
21.4k
Forks
4.8k
Avg merge
7h 45m
Merged PRs (30d)
11

Description

New Issue Checklist
Issue Description

With allowCustomObjectId: true, a create whose objectId is an operation envelope such as
{"__op":"Delete"} is accepted, and the row that results is unusable in three separate ways.

getType returns nothing for an operation envelope, so validateObject hits
if (!expected) { continue; } and never compares the value against the String type of the
objectId column. The value then reaches the database layer, where the driver generates its own
_id.

The outcome is a _User that:

  • is stored under a Mongo-generated _id such as 6a862fa06e17011e3f5a9c96, which is not a Parse
    objectId and is not what the client was told,
  • has _rperm and _wperm of ["[object Object]"], because the owner ACL is keyed by stringifying
    the same operation object, so the row is readable and writable by nobody,
  • and is echoed back to the client with "objectId": {"__op":"Delete"}, along with a working
    session token for a user that session can never read.

A non-operation value behaves correctly and is refused with 111 INCORRECT_TYPE, so this is
specific to values whose type cannot be inferred.

Steps to reproduce

Start a server with allowCustomObjectId: true, then:

curl -s -X POST http://127.0.0.1:1337/parse/users \
  -H 'X-Parse-Application-Id: myAppId' -H 'Content-Type: application/json' \
  -d '{"objectId":{"__op":"Delete"},"username":"probe2","password":"pw"}'

Then look at the stored row, with the master key:

curl -s -G http://127.0.0.1:1337/parse/classes/_User \
  -H 'X-Parse-Application-Id: myAppId' -H 'X-Parse-Master-Key: myMasterKey' \
  --data-urlencode 'where={"username":"probe2"}'

For contrast, "objectId": 123 in the same body is refused as expected.

Actual Outcome
201 {"objectId":{"__op":"Delete"},"createdAt":"...","sessionToken":"r:..."}

and in MongoDB:

_id:     "6a862fa06e17011e3f5a9c96"
_rperm:  ["[object Object]"]
_wperm:  ["[object Object]"]

An anonymous GET /classes/_User does not return the row, and neither does a query by another
authenticated user, so the account exists and is unreachable by everyone except the master key.

With "objectId": 123 instead: 400 {"code":111,...} and no row, which is the expected behaviour.

Expected Outcome

An objectId whose type cannot be inferred should be refused rather than skipped. Either the same
111 INCORRECT_TYPE that every other non-string value produces, or an explicit rejection of
operation envelopes in that position.

At minimum the response should not report an objectId that differs from the stored _id, since a
client cannot address the object it just created.

Environment

Server

  • Parse Server version: 9.10.1-alpha.6 (commit ca75b1fe)
  • Operating system: macOS 26.5.2
  • Local or remote host: local

Database

  • System (MongoDB or Postgres): MongoDB
  • Database version: 7.0.25
  • Local or remote host: local

Client

  • SDK (iOS, Android, JavaScript, PHP, Unity, etc): none, raw REST over HTTP
  • SDK version: n/a
Logs

No error is logged; the request succeeds.

Found while building a reimplementation and comparing behaviour against a server built at
ca75b1fe. The stored _id and permission columns above were read directly out of MongoDB rather
than inferred.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the validateObject path and its getType handling for objectId, then reproduce the raw REST request against MongoDB and compare it with the numeric objectId case. Done means operation-envelope objectIds are rejected with 111 INCORRECT_TYPE or an explicit rejection, with no unreachable row or session created.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, mongodb, nodejs
Domain
api, backend, database, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.