dwn-sdk-js icon indicating copy to clipboard operation
dwn-sdk-js copied to clipboard

Given `author` in non-owner query/subscribe filter is overwritten

Open thehenrytsai opened this issue 1 year ago • 0 comments

When author is given in a non-owner query filter, buildUnpublishedRecordsBySubscribeAuthorFilter() is always called resulting an internal query that includes the author of query as the author in the filter.

While this is not an elevation in privilege, it is functionally incorrect. Suspecting this issue also affects RecordsSubscribe since the code is a copy from RecordsQuery.

Adding the following test in handlers/records-query.spec.ts will reproduce the issue:

      it('should not override the `author` in filter in non-owner query if given.', async () => {
        const alice = await DidKeyResolver.generate();
        const bob = await DidKeyResolver.generate();
        const carol = await DidKeyResolver.generate();

        const protocolDefinition = freeForAll;

        const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
          author: alice,
          protocolDefinition
        });
        const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
        expect(protocolsConfigureReply.status.code).to.equal(202);

        // Bob write a record
        const recordByBob = await TestDataGenerator.generateRecordsWrite({
          author       : bob,
          protocol     : protocolDefinition.protocol,
          schema       : protocolDefinition.types.post.schema,
          dataFormat   : protocolDefinition.types.post.dataFormats[0],
          protocolPath : 'post'
        });
        const bobWriteResult = await dwn.processMessage(alice.did, recordByBob.message, { dataStream: recordByBob.dataStream });
        expect(bobWriteResult.status.code).to.equal(202);

        const recordByCarol = await TestDataGenerator.generateRecordsWrite({
          author       : carol,
          protocol     : protocolDefinition.protocol,
          schema       : protocolDefinition.types.post.schema,
          dataFormat   : protocolDefinition.types.post.dataFormats[0],
          protocolPath : 'post'
        });
        const carolWriteResult = await dwn.processMessage(alice.did, recordByCarol.message, { dataStream: recordByCarol.dataStream });
        expect(carolWriteResult.status.code).to.equal(202);

        // Bob query for Carol's record
        const queryByBob = await RecordsQuery.create({
          filter: {
            author : carol.did,
            schema : protocolDefinition.types.post.schema,
          },
          signer: Jws.createSigner(bob)
        });

        // Verify that no record is return to Bob.
        const replyToBobQuery = await dwn.processMessage(alice.did, queryByBob.message);
        expect(replyToBobQuery.status.code).to.equal(200);
        expect(replyToBobQuery.entries?.length).to.equal(0);
        
        // actual result: an entry with Bob being the author is returned.
      });

thehenrytsai avatar Jan 22 '24 22:01 thehenrytsai