Skip to content

fix(shared): prevent clone() from re-parenting the cloned object - #1790

Merged
dinwwwh merged 1 commit into
middleapi:mainfrom
dinwwwh:claude/clone-prototype-reparenting-ea440f
Aug 5, 2026
Merged

fix(shared): prevent clone() from re-parenting the cloned object#1790
dinwwwh merged 1 commit into
middleapi:mainfrom
dinwwwh:claude/clone-prototype-reparenting-ea440f

Conversation

@dinwwwh

@dinwwwh dinwwwh commented Aug 5, 2026

Copy link
Copy Markdown
Member

clone() copied properties with plain assignment, so a source object carrying an own __proto__ key went through Object.prototype's __proto__ setter instead of getting a property. The clone came back re-parented onto the source's payload, or silently lost the key when its value was not an object. Copying through Object.defineProperty makes every key a real own property.

This is reachable with ordinary input: JSON.parse and NullProtoObj both produce own __proto__ keys, and isPlainObject treats both as plain objects.

Fixes

  • Cloning an object with an own __proto__ key now yields a clone whose prototype is still Object.prototype, with __proto__ present as a normal own property.
  • Non-object __proto__ values (e.g. 2) are preserved instead of being dropped by the setter.
  • Scope note: Object.prototype itself was never mutated, so this was clone corruption rather than global prototype pollution.

Testing

New clone with __proto__ property case covers both the JSON.parse and NullProtoObj sources and fails on the previous code (the clone's prototype had become the payload). Full packages/shared suite passes at 302 tests, lint clean.

clone() copied properties with plain assignment, so a source object with
an own `__proto__` key (routine from JSON.parse or NullProtoObj, both
treated as plain objects here) invoked Object.prototype's `__proto__`
setter on the result instead of creating a property. The clone came back
re-parented onto the source's payload, or silently lost the key when the
value was not an object.

Copy through Object.defineProperty so every key becomes a real own
property.
@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
orpc Ready Ready Preview Aug 5, 2026 7:16am

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • clone() re-parenting fix: the plain-object loop in packages/shared/src/object.ts now copies properties via the existing defineOwnProperty helper (Object.defineProperty) instead of plain assignment, so an own __proto__ data key becomes a real own property instead of triggering Object.prototype's __proto__ setter. Applied to both the string-key and symbol loops.
  • New clone with __proto__ property test covering JSON.parse and NullProtoObj sources.

The fix is minimal and reuses the established defineOwnProperty helper (already used by set). Because defineOwnProperty sets writable/enumerable/configurable, the behavior is identical to plain assignment for ordinary properties — the only change is that __proto__-style data keys no longer re-parent the result or get silently dropped. I verified the new test genuinely fails on the previous code: with assignment, the clone's prototype becomes the payload and __proto__ is absent as an own property, so both prototype and value assertions catch the bug.

Pullfrog  | View workflow run | Using openrouter/~deepseek/deepseek-v4-flash-latest (free via Pullfrog for OSS) | 𝕏

@pkg-pr-new

pkg-pr-new Bot commented Aug 5, 2026

Copy link
Copy Markdown
More templates

@orpc/ai-sdk

npm i https://pkg.pr.new/@orpc/ai-sdk@1790

@orpc/arktype

npm i https://pkg.pr.new/@orpc/arktype@1790

@orpc/bun

npm i https://pkg.pr.new/@orpc/bun@1790

@orpc/client

npm i https://pkg.pr.new/@orpc/client@1790

@orpc/cloudflare

npm i https://pkg.pr.new/@orpc/cloudflare@1790

@orpc/contract

npm i https://pkg.pr.new/@orpc/contract@1790

@orpc/experimental-effect

npm i https://pkg.pr.new/@orpc/experimental-effect@1790

@orpc/evlog

npm i https://pkg.pr.new/@orpc/evlog@1790

@orpc/hibernation

npm i https://pkg.pr.new/@orpc/hibernation@1790

@orpc/json-schema

npm i https://pkg.pr.new/@orpc/json-schema@1790

@orpc/nest

npm i https://pkg.pr.new/@orpc/nest@1790

@orpc/next

npm i https://pkg.pr.new/@orpc/next@1790

@orpc/openapi

npm i https://pkg.pr.new/@orpc/openapi@1790

@orpc/opentelemetry

npm i https://pkg.pr.new/@orpc/opentelemetry@1790

@orpc/pinia-colada

npm i https://pkg.pr.new/@orpc/pinia-colada@1790

@orpc/pino

npm i https://pkg.pr.new/@orpc/pino@1790

@orpc/publisher

npm i https://pkg.pr.new/@orpc/publisher@1790

@orpc/ratelimit

npm i https://pkg.pr.new/@orpc/ratelimit@1790

@orpc/server

npm i https://pkg.pr.new/@orpc/server@1790

@orpc/shared

npm i https://pkg.pr.new/@orpc/shared@1790

@orpc/swr

npm i https://pkg.pr.new/@orpc/swr@1790

@orpc/tanstack-query

npm i https://pkg.pr.new/@orpc/tanstack-query@1790

@orpc/trpc

npm i https://pkg.pr.new/@orpc/trpc@1790

@orpc/valibot

npm i https://pkg.pr.new/@orpc/valibot@1790

@orpc/zod

npm i https://pkg.pr.new/@orpc/zod@1790

commit: b5b9c36

@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 25 untouched benchmarks


Comparing dinwwwh:claude/clone-prototype-reparenting-ea440f (b5b9c36) with main (e0b4947)

Open in CodSpeed

@dinwwwh
dinwwwh merged commit 9f9d664 into middleapi:main Aug 5, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant