Skip to content

The plugin services registry is keyed by plugin name into a plain object, so a reserved name corrupts it #1341

Description

@borisno2

The problem

packages/core/src/context/index.ts:651 assigns into a plain object with a caller-supplied key:

context.plugins[plugin.name] = 

A plugin named __proto__ therefore sets the object's prototype rather than adding a member. A plugin named constructor or toString collides with an inherited name, so a later lookup of a different plugin's services can find an inherited function instead of failing cleanly.

This is the same hazard that has now been fixed twice elsewhere in this package: once in a provider-name lookup, and once in a plugin-owned field write where a prototype key walked past two guards and reached the database as a column name.

Why it is worth closing rather than shrugging at

Plugin names are author-supplied, so this is not attacker-controlled in the usual sense, and nobody is likely to name a plugin __proto__ on purpose. But the failure is silent and its symptom appears far away — a plugin's services resolving to an inherited function rather than being absent, which reads as a corrupt registry rather than a naming mistake.

The remedy is one word, and the same one both prior fixes used.

What to do

Build the registry with a null-prototype object, or gate the write and every read with Object.hasOwn, and refuse a reserved name by name at registration so the author is told rather than left to debug it.

While there: sweep for other assignments into a plain object under a config-supplied key. Two instances of this shape have already been found in this package by separate reviews, which suggests looking rather than assuming these were the last.

Provenance

Pre-existing. Found while fixing the same class in the plugin-owned field write on #1332, and deliberately left out of that pull request's scope.

Context


_Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ready-for-agentFully specified, ready for an AFK agent

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions