From 6edc8a54be630f408f88f0e1931b734ec082c221 Mon Sep 17 00:00:00 2001 From: Dakota Brink <779390+codabrink@users.noreply.github.com> Date: Mon, 2 Dec 2024 18:25:33 -0500 Subject: [PATCH] Static Frames Validation Security Fix (#736) * authorize with lib * wip * bump node bindings * await * messaging * check the wallet * bump * yarn install * bump node bindings * bump node sdk version * fix * random client * new bindings * update the validator * bump node-sdk * fix version * cleanup * cleanup * lint * bump version * update the frame url * missing quote * one more bump to the urls * Undo frame-validator version bump * Refactor node client API * Upgrade Node SDK * Create lemon-rockets-do.md --------- Co-authored-by: Naomi Plasterer Co-authored-by: Ry Racherbaumer Co-authored-by: Ry Racherbaumer --- .changeset/lemon-rockets-do.md | 5 ++++ packages/frames-client/package.json | 2 +- packages/frames-client/src/client.test.ts | 6 ++--- packages/frames-validator/package.json | 2 +- packages/frames-validator/src/validation.ts | 22 +++++++++++++---- yarn.lock | 26 +++------------------ 6 files changed, 30 insertions(+), 33 deletions(-) create mode 100644 .changeset/lemon-rockets-do.md diff --git a/.changeset/lemon-rockets-do.md b/.changeset/lemon-rockets-do.md new file mode 100644 index 000000000..6835c3412 --- /dev/null +++ b/.changeset/lemon-rockets-do.md @@ -0,0 +1,5 @@ +--- +"@xmtp/frames-validator": patch +--- + +Fix V3 frames validation diff --git a/packages/frames-client/package.json b/packages/frames-client/package.json index c36b9ba50..3ab232635 100644 --- a/packages/frames-client/package.json +++ b/packages/frames-client/package.json @@ -70,7 +70,7 @@ "@open-frames/types": "^0.1.1", "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^12.1.1", - "@xmtp/node-sdk": "^0.0.27", + "@xmtp/node-sdk": "^0.0.30", "@xmtp/xmtp-js": "^12.0.0", "ethers": "^6.13.1", "fast-glob": "^3.3.2", diff --git a/packages/frames-client/src/client.test.ts b/packages/frames-client/src/client.test.ts index 6c921375f..9521e1593 100644 --- a/packages/frames-client/src/client.test.ts +++ b/packages/frames-client/src/client.test.ts @@ -133,7 +133,7 @@ const shouldSignFrameActionWithValidSignature = // Will add E2E tests back once we have Frames deployed with the new schema const worksE2E = (framesClient: FramesClient) => async () => { const frameUrl = - "https://fc-polls-five.vercel.app/polls/01032f47-e976-42ee-9e3d-3aac1324f4b8"; + "https://fc-polls-five.vercel.app/polls/03710836-bc1d-4921-9e24-89d82015c53b"; const metadata = await framesClient.proxy.readMetadata(frameUrl); expect(metadata).toBeDefined(); expect(metadata.frameInfo).toMatchObject({ @@ -150,10 +150,10 @@ const worksE2E = (framesClient: FramesClient) => async () => { }, image: { content: - "https://fc-polls-five.vercel.app/api/image?id=01032f47-e976-42ee-9e3d-3aac1324f4b8", + "https://fc-polls-five.vercel.app/api/image?id=03710836-bc1d-4921-9e24-89d82015c53b", }, postUrl: - "https://fc-polls-five.vercel.app/api/vote?id=01032f47-e976-42ee-9e3d-3aac1324f4b8", + "https://fc-polls-five.vercel.app/api/vote?id=03710836-bc1d-4921-9e24-89d82015c53b", }); const signedPayload = await framesClient.signFrameAction({ frameUrl, diff --git a/packages/frames-validator/package.json b/packages/frames-validator/package.json index 68f618913..09171838d 100644 --- a/packages/frames-validator/package.json +++ b/packages/frames-validator/package.json @@ -40,7 +40,7 @@ "dependencies": { "@noble/curves": "^1.3.0", "@noble/hashes": "^1.4.0", - "@xmtp/node-sdk": "^0.0.27", + "@xmtp/node-sdk": "^0.0.30", "@xmtp/proto": "^3.72.3", "uint8array-extras": "^1.4.0", "viem": "^2.16.5" diff --git a/packages/frames-validator/src/validation.ts b/packages/frames-validator/src/validation.ts index d9713e7f1..f69c1f937 100644 --- a/packages/frames-validator/src/validation.ts +++ b/packages/frames-validator/src/validation.ts @@ -1,5 +1,5 @@ import { sha256 } from "@noble/hashes/sha256"; -import { Client, getInboxIdForAddress, type XmtpEnv } from "@xmtp/node-sdk"; +import { Client, type XmtpEnv } from "@xmtp/node-sdk"; import { fetcher, frames, type publicKey, type signature } from "@xmtp/proto"; import { uint8ArrayToHex } from "uint8array-extras"; import type { @@ -28,7 +28,7 @@ export async function validateFramesPost( actionBodyBytes, signature, signedPublicKeyBundle, - installationId, // not necessary + installationId, installationSignature, inboxId, } = deserializeProtoMessage(messageBytes); @@ -48,9 +48,21 @@ export async function validateFramesPost( } } else { // make sure inbox IDs match - const addressInboxId = await getInboxIdForAddress(walletAddress, env); - if (inboxId !== addressInboxId) { - throw new Error("Invalid inbox ID"); + const authorized = await Client.isInstallationAuthorized( + inboxId, + installationId, + { env }, + ); + if (!authorized) { + throw new Error("Installation not a member of association state"); + } + + const isMember = await Client.isAddressAuthorized(inboxId, walletAddress, { + env, + }); + + if (!isMember) { + throw new Error("Unable to associate wallet address with inbox"); } const digest = sha256(actionBodyBytes); diff --git a/yarn.lock b/yarn.lock index 5a7d61a74..591f6a75b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5033,7 +5033,7 @@ __metadata: "@open-frames/types": "npm:^0.1.1" "@rollup/plugin-terser": "npm:^0.4.4" "@rollup/plugin-typescript": "npm:^12.1.1" - "@xmtp/node-sdk": "npm:^0.0.27" + "@xmtp/node-sdk": "npm:^0.0.30" "@xmtp/proto": "npm:^3.72.3" "@xmtp/xmtp-js": "npm:^12.0.0" ethers: "npm:^6.13.1" @@ -5065,7 +5065,7 @@ __metadata: "@rollup/plugin-typescript": "npm:^12.1.1" "@types/bl": "npm:^5.1.4" "@xmtp/frames-client": "npm:^1.0.0" - "@xmtp/node-sdk": "npm:^0.0.27" + "@xmtp/node-sdk": "npm:^0.0.30" "@xmtp/proto": "npm:^3.72.3" "@xmtp/xmtp-js": "npm:^12.1.0" ethers: "npm:^6.10.0" @@ -5079,13 +5079,6 @@ __metadata: languageName: unknown linkType: soft -"@xmtp/node-bindings@npm:^0.0.22": - version: 0.0.22 - resolution: "@xmtp/node-bindings@npm:0.0.22" - checksum: 10/e8668b2fd30041dff8671625c13d49245d421ac31c0669b9be5365b5f22bf3c28f4d0cc12015a2710b90136423828bcdb1a99a10b37d4d5ac51e3ac47228b960 - languageName: node - linkType: hard - "@xmtp/node-bindings@npm:^0.0.28": version: 0.0.28 resolution: "@xmtp/node-bindings@npm:0.0.28" @@ -5093,20 +5086,7 @@ __metadata: languageName: node linkType: hard -"@xmtp/node-sdk@npm:^0.0.27": - version: 0.0.27 - resolution: "@xmtp/node-sdk@npm:0.0.27" - dependencies: - "@xmtp/content-type-group-updated": "npm:^1.0.1" - "@xmtp/content-type-primitives": "npm:^1.0.3" - "@xmtp/content-type-text": "npm:^1.0.1" - "@xmtp/node-bindings": "npm:^0.0.22" - "@xmtp/proto": "npm:^3.72.3" - checksum: 10/9937c77d4bd3f3ed8df2f9938e940e2c21a7c8e8f06506d227bb97939f8294e0ae6ec6bc1498f528274257d61f9142e38639aa123c3ddf086a98d9cd041c0161 - languageName: node - linkType: hard - -"@xmtp/node-sdk@workspace:sdks/node-sdk": +"@xmtp/node-sdk@npm:^0.0.30, @xmtp/node-sdk@workspace:sdks/node-sdk": version: 0.0.0-use.local resolution: "@xmtp/node-sdk@workspace:sdks/node-sdk" dependencies: