Repository navigation
fix(dashboard): guard provider icon lookups against prototype collisions - #11880
Merged
diegosouzapw merged 2 commits intoAug 28, 2026
Conversation
getLobeProviderIcon indexed two object literals with no own-property check. A provider id whose lowercased form is an Object.prototype member resolves through the prototype chain: LOBE_PROVIDER_ALIASES["constructor"] returns the Object constructor, which is truthy, so the existing falsy guard lets it through. The follow-up LOBE_ICON_COMPONENTS lookup is then undefined and entry.color throws. ProviderIcon calls this for every card, so one such provider id takes the whole providers page down through the App Router error boundary, which shows a "check your connection" card even though nothing was wrong with the network. Only constructor and __proto__ can reach it. Every other Object.prototype member is camelCase and stops colliding after toLowerCase(). Closes diegosouzapw#11853
diegosouzapw
added a commit
that referenced
this pull request
Aug 28, 2026
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…ons (diegosouzapw#11880) getLobeProviderIcon() indexed two plain-object maps with no own-property check — a provider id that lowercases to an Object.prototype member (e.g. constructor) resolved through the prototype chain and threw on the follow-up .color/.mono lookup, surfacing as the misleading 'Failed to load providers, check your connection' error boundary card with a healthy server and clean logs. Thanks for the precise root-cause trace!
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…sions (diegosouzapw#11920 port) (diegosouzapw#11935) Ports the 3 still-needed guards from diegosouzapw#11920 that diegosouzapw#11880 didn't cover. 90/90 + 4/4 focused tests passing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The providers dashboard intermittently rendered the red "Failed to load providers, check your connection and try again" card while the server was healthy and its logs were clean. The card comes from the App Router error boundary at
src/app/(dashboard)/dashboard/providers/error.tsx, which catches any uncaught client-side throw under/dashboard/providers/**, so the copy blaming the network is misleading. No request has to fail to produce it.The throw is in
getLobeProviderIcon():Both maps are plain object literals indexed with no own-property check. A provider id whose lowercased form is an
Object.prototypemember resolves through the prototype chain, soLOBE_PROVIDER_ALIASES["constructor"]returns theObjectconstructor. That is truthy, the falsy guard lets it through, and the follow-up lookup isundefined. Reading.coloroff it throwsCannot read properties of undefined (reading 'color'), which matches the minified console trace exactly.ProviderIconcalls this for every provider card, so a single such id takes the whole page down.Worth noting for anyone reading the original report: only
constructorand__proto__can actually reach this. Every otherObject.prototypemember is camelCase and stops colliding once.toLowerCase()has run, sovalueOf,hasOwnPropertyand friends already returnednullsafely. I checked this at runtime rather than by inspection.The fix adds
Object.hasOwn()guards on both lookups plus a defensiveentrycheck, and returnsnullfor a non-string id instead of throwing on.toLowerCase().Related Issues
Validation
npm run lintI also swept all 171 real ids in
LOBE_PROVIDER_ALIASESin bothcolorandmonomodes, before and after the change, and got zero behavioural differences. That sweep is not in the committed test since it would just restate the alias table, but the committed test does cover the known-provider and unknown-provider paths.Tests Added Or Updated
tests/unit/lobe-provider-icons-prototype-collision-11853.test.ts(new)Coverage Notes
The new file covers
getLobeProviderIcon()end to end: the two colliding ids in both icon modes, the camelCase prototype members that were already safe, a known provider, an unknown provider, and a non-string id.Reviewer Notes
Same unguarded-lookup pattern exists in
PROVIDER_ICON_ALIASES,LOCAL_SVG_ALIASESandTHEMED_SVGS, whichProviderIconalso consults. I kept this PR to the one map that actually throws today so the change stays reviewable. Happy to follow up on the other three if you want them hardened in the same pass.There is a second, unrelated crash on the same page that I did not touch here: opening
/dashboard/providers/<id>for an id missing from the dashboard catalog makesresolveDashboardProviderInforeturnnull, which then gets spread intoproviderInfo, and a downstreamproviderId.toLowerCase()throws. Same error card, different signature (reading 'toLowerCase'). Say the word and I will open a separate issue for it.