Skip to content

Conversation

@stevenconner
Copy link
Contributor

@stevenconner stevenconner commented Sep 17, 2025

Screenshot 2025-09-19 at 3 32 13 PM Screenshot 2025-09-19 at 3 32 19 PM Screenshot 2025-09-19 at 3 32 25 PM Screenshot 2025-09-19 at 3 32 39 PM Screenshot 2025-09-19 at 3 32 51 PM

@stevenconner stevenconner changed the title implement basic state screen WIP - implement basic state screen Sep 19, 2025
@stevenconner stevenconner changed the title WIP - implement basic state screen Implement state screen Sep 22, 2025
Copy link
Contributor

@SeanBarker182 SeanBarker182 left a 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!

// Create a safe object with only expected properties to prevent prototype pollution
const safeChange = {
path: change.path,
value: change.value,
Copy link
Contributor

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:

Suggested change
value: change.value,
value: sanitizeValue(change.value),

const existingSubscription = currentSubscriptions[existingSubscriptionIndex]
currentSubscriptions[existingSubscriptionIndex] = {
path: existingSubscription.path,
value: change.value,
Copy link
Contributor

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:

Suggested change
value: change.value,
value: sanitizeValue(change.value),

const clientId = data?.conn?.clientId
if (!clientIds.includes(clientId)) {
setClientIds((prev) => [...prev, clientId])
// setActiveClientId(clientId)
Copy link
Contributor

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?

Copy link
Contributor Author

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

This assignment may alter Object.prototype if a malicious '__proto__' string is injected from
user controlled input
.

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:

  1. Ensure we never use "__proto__", "constructor", or "prototype" (or similarly risky keys) as object keys.
  2. Continue to use isSafeKey, but strengthen it if needed (not shown, but suggest robust implementation).
  3. 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.
  4. Add an explicit check before using data.cmd.clientId and change.path as keys, even after isSafeKey, to block prototype pollution keys.
  5. Update the code in the block where setStateSubscriptionsByClientId is called to bail out if unsafe keys are present.
  6. Add a utility predicate to reject keys "__proto__", "constructor", or "prototype", and use it alongside isSafeKey.

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.


Suggested changeset 1
app/state/connectToServer.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/app/state/connectToServer.ts b/app/state/connectToServer.ts
--- a/app/state/connectToServer.ts
+++ b/app/state/connectToServer.ts
@@ -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,
EOF
@@ -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,
Copilot is powered by AI and may make mistakes. Always verify output.
@stevenconner stevenconner merged commit 52d2458 into main Sep 23, 2025
4 checks passed
@stevenconner stevenconner deleted the steve/basic-state-screen branch September 23, 2025 22:20
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.

3 participants