Conversation
Automated security fix generated by OrbisAI Security
There was a problem hiding this comment.
Thanks for the submission! This probably looks like a sensible change, but a couple of notes:
- your PR title talks about "authentication", but this change has nothing to do with authentication?
- this change doesn't have any tests flexing the bug you're trying to fix
- this change doesn't actually address one of the concerns you raise in your PR description that an attacker can impersonate any client ID
Could you please address the above and resubmit for review? Thanks!
…lution agent.src (the handshake `id`) is a client-chosen correlation token used for op/presence self-echo suppression and resubmission dedup, not a credential, so this cannot prevent client id impersonation - real identity verification belongs in connect/receive middleware. This closes the one gap where request.id wasn't run through the same isDangerousProperty/type check already applied to collection, doc id, presence id, and presence channel in _checkRequest, and adds regression tests for it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
| if (typeof request.b !== 'object') return 'Invalid bulk subscribe data'; | ||
| } else if (request.a === ACTIONS.handshake) { | ||
| if (request.id != null) { | ||
| if (typeof request.id !== 'string' || util.isDangerousProperty(request.id)) { |
There was a problem hiding this comment.
I don't think the request.id is actually ever used as an object key anywhere unless I'm missing something? What actual attack vector are you trying to guard against here?
Also I think we already validate the id type as a string both on client connection and during checkOp. Again, what exact bug are you trying to fix here?
There was a problem hiding this comment.
You're right, and thanks for pushing on this. I traced every use of agent.src/op.src across lib/ (agent.js, submit-request.js, ot.js, backend.js, db/index.js, client/*) and confirmed it's never used as an object/map key anywhere - only === comparisons and plain property assignment (this.src = src, {src: ...} on outgoing messages). That's unlike collection/doc id/presence id/channel, which genuinely are used as keys elsewhere (e.g. the subscribedDocs/subscribedPresences maps), which is why isDangerousProperty is warranted there.
So there's no real prototype-pollution vector here, and the type-confusion angle is also largely redundant: a string-type check for the handshake id already existed inline before this PR, and lib/ot.js's checkOp already rejects a non-string op.src before any op is persisted.
I've pushed a commit that drops the isDangerousProperty check for this field and keeps only the plain typeof === 'string' check, for consistency with the other fields _checkRequest validates - not framed as a security fix. Updated the PR description and removed the now-invalid __proto__/constructor/hasOwnProperty rejection tests accordingly (those are valid ids now).
request.id (agent.src) is never used as an object/map key anywhere in lib/ - unlike collection, doc id, presence id, and channel, which the isDangerousProperty check in _checkRequest genuinely protects. Per review feedback on share#730, that framing was wrong, so the check is narrowed to a plain typeof === 'string' validation, kept only for consistency with the type checks already applied to the other fields. Removes the __proto__/constructor/hasOwnProperty rejection tests, since those are now valid ids. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
What changed
Agent.prototype._checkRequestinlib/agent.jsvalidates the handshakeidis a string, consistent with the type checks already applied to theother client-supplied string fields (
c,d,ch, and the presenceid).Update per review feedback: an earlier version of this change also
rejected
idvalues like__proto__/constructor/hasOwnPropertyviautil.isDangerousProperty, framed as closing a prototype-pollution gap. Aspointed out in review, that framing didn't hold up:
agent.src(and theop-level
srcit feeds, seelib/agent.js:25-29) is never used as anobject/map key anywhere in
lib/- only in===comparisons and plainproperty assignments (
this.src = src,{src: ...}on outgoing messages).That's unlike
collection/docid/presenceid/channel, which genuinelyare used as keys elsewhere (e.g. the
subscribedDocs/subscribedPresencesmaps), which is why
isDangerousPropertyis warranted for those.So this has been narrowed to just the plain string-type check. It's not a
prototype-pollution or type-confusion fix - it's a protocol-hygiene
consistency change, rejecting the handshake with
ERR_MESSAGE_BADLY_FORMED/
'Invalid client id'ifidis set and isn't a string.What this is not
An earlier version of this PR framed this as an authentication/CWE-287 fix,
claiming it prevented client-id impersonation. That framing was also wrong
and has been corrected:
agent.srcis a client-chosen correlation token, echoed back onops/presence for self-echo suppression (
_isOwnOp,_handlePresenceData)and used as a resubmission dedup key (
lib/submit-request.js,lib/ot.js).It is never treated as a verified identity anywhere in
lib/.a connection is the
connect/receivemiddleware (lib/backend.js),which this change doesn't touch.
from claiming any (string) client id it likes - that was never something
the handshake
idfield protected against.Tests
test/agent.js'shandshakesuite:idis a non-string.id(including values like__proto__, which are valid ids now thatisDangerousPropertyhas beendropped for this field), and confirms it's set on
agent.srcand echoedback to the client.
🤖 Generated with Claude Code