-
Notifications
You must be signed in to change notification settings - Fork 0
Implement state screen #22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
SeanBarker182
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good and works for me on both Redux and MST!
app/state/connectToServer.ts
Outdated
| // Create a safe object with only expected properties to prevent prototype pollution | ||
| const safeChange = { | ||
| path: change.path, | ||
| value: change.value, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If using the util above:
| value: change.value, | |
| value: sanitizeValue(change.value), |
app/state/connectToServer.ts
Outdated
| const existingSubscription = currentSubscriptions[existingSubscriptionIndex] | ||
| currentSubscriptions[existingSubscriptionIndex] = { | ||
| path: existingSubscription.path, | ||
| value: change.value, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If using the util above:
| value: change.value, | |
| value: sanitizeValue(change.value), |
app/state/connectToServer.ts
Outdated
| const clientId = data?.conn?.clientId | ||
| if (!clientIds.includes(clientId)) { | ||
| setClientIds((prev) => [...prev, clientId]) | ||
| // setActiveClientId(clientId) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be commented out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whoops lol, was testing the opposite side of it
| if (existingSubscriptionIndex !== -1) { | ||
| // Create a safe object with only expected properties to prevent prototype pollution | ||
| const existingSubscription = currentSubscriptions[existingSubscriptionIndex] | ||
| currentSubscriptions[existingSubscriptionIndex] = { |
Check warning
Code scanning / CodeQL
Prototype-polluting assignment Medium
user controlled input
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 3 months ago
To fix prototype pollution risks in this code, the best approach is to avoid using potentially polluted object keys directly, especially those derived from user-controlled input. The patch should:
- Ensure we never use
"__proto__","constructor", or"prototype"(or similarly risky keys) as object keys. - Continue to use
isSafeKey, but strengthen it if needed (not shown, but suggest robust implementation). - Use a Map for mapping client IDs to their subscriptions instead of a plain object, OR create a prototype-less object via
Object.create(null). Since we only have this code shown, and can't refactor the wider state shape, we will add explicit checks to forbid dangerous keys. - Add an explicit check before using
data.cmd.clientIdandchange.pathas keys, even afterisSafeKey, to block prototype pollution keys. - Update the code in the block where
setStateSubscriptionsByClientIdis called to bail out if unsafe keys are present. - Add a utility predicate to reject keys
"__proto__","constructor", or"prototype", and use it alongsideisSafeKey.
No dependency is needed; we can add a constant or function for the forbidden key check.
This change is localized to the handler for the state.values.change command, inside the ws.socket.onmessage block.
-
Copy modified lines R112-R118
| @@ -109,7 +109,13 @@ | ||
| if (data.cmd.type === "state.values.change") { | ||
| console.log("state.values.change", data.cmd) | ||
| data.cmd.payload.changes.forEach((change: StateSubscription) => { | ||
| if (!isSafeKey(data.cmd.clientId) || !isSafeKey(change.path)) { | ||
| // Defense in depth: reject forbidden keys explicitly | ||
| if ( | ||
| !isSafeKey(data.cmd.clientId) || | ||
| isForbiddenKey(data.cmd.clientId) || | ||
| !isSafeKey(change.path) || | ||
| isForbiddenKey(change.path) | ||
| ) { | ||
| console.warn( | ||
| "Ignored suspicious property name in state.values.change:", | ||
| data.cmd.clientId, |
Uh oh!
There was an error while loading. Please reload this page.