From 7dac98c42942cbbed6e6fe2b0efbb7b88320a0fe Mon Sep 17 00:00:00 2001 From: tsukino <0xtsukino@gmail.com> Date: Tue, 29 Oct 2024 21:29:25 +0800 Subject: [PATCH 1/5] wip --- src/entries/Background/rpc.ts | 151 ++++++++++++++++++++----- src/entries/Offscreen/Offscreen.tsx | 165 ++++++++++++++++++++-------- src/entries/Offscreen/types.ts | 4 + src/entries/Offscreen/utils.ts | 39 +++++++ src/utils/misc.ts | 32 ++++-- 5 files changed, 310 insertions(+), 81 deletions(-) create mode 100644 src/entries/Offscreen/utils.ts diff --git a/src/entries/Background/rpc.ts b/src/entries/Background/rpc.ts index ea95fd1f..574c1796 100644 --- a/src/entries/Background/rpc.ts +++ b/src/entries/Background/rpc.ts @@ -46,6 +46,7 @@ import { deferredPromise } from '../../utils/promise'; import { minimatch } from 'minimatch'; import { OffscreenActionTypes } from '../Offscreen/types'; import { SidePanelActionTypes } from '../SidePanel/types'; +import { subtractRanges } from '../Offscreen/utils'; const charwise = require('charwise'); @@ -382,8 +383,9 @@ async function runPluginProver(request: BackgroundAction, now = Date.now()) { method, headers, body, - secretHeaders, - secretResps, + secretHeaders = [], + // secretResps, + getSecretResponse, notaryUrl: _notaryUrl, websocketProxyUrl: _websocketProxyUrl, maxSentData: _maxSentData, @@ -394,33 +396,130 @@ async function runPluginProver(request: BackgroundAction, now = Date.now()) { const maxSentData = _maxSentData || (await getMaxSent()); const maxRecvData = _maxRecvData || (await getMaxRecv()); - const { id } = await addNotaryRequest(now, { - url, - method, - headers, - body, - notaryUrl, - websocketProxyUrl, - maxRecvData, - maxSentData, - secretHeaders, - secretResps, - }); + let secretResps: string[] = []; + + // const { id } = await addNotaryRequest(now, { + // url, + // method, + // headers, + // body, + // notaryUrl, + // websocketProxyUrl, + // maxRecvData, + // maxSentData, + // secretHeaders, + // secretResps, + // }); + // + // await setNotaryRequestStatus(id, 'pending'); + // + // await browser.runtime.sendMessage({ + // type: BackgroundActiontype.push_action, + // data: { + // tabId: 'background', + // }, + // action: addRequestHistory(await getNotaryRequest(id)), + // }); + + const onProverResponse = async (request: any) => { + const { data, type } = request; + + if (type !== OffscreenActionTypes.create_prover_response) { + return; + } - await setNotaryRequestStatus(id, 'pending'); + if (data.error) { + console.error(data.error); + return; + } - await browser.runtime.sendMessage({ - type: BackgroundActiontype.push_action, - data: { - tabId: 'background', - }, - action: addRequestHistory(await getNotaryRequest(id)), - }); + if (data.id !== now) { + return; + } - await browser.runtime.sendMessage({ - type: BackgroundActiontype.process_prove_request, + if (getSecretResponse) { + console.log('getting secret response'); + const { + recv, + ranges: { + recv: { + body: { start }, + all: { end }, + }, + }, + } = data.transcript; + secretResps = await getSecretResponse(recv.slice(start, end)); + } + + const commit = { + sent: subtractRanges( + data.transcript.ranges.sent.all, + secretHeaders + .map((secret: string) => { + const index = data.transcript.sent.indexOf(secret); + return index > -1 + ? { + start: index, + end: index + secret.length, + } + : null; + }) + .filter((data: any) => !!data) as { start: number; end: number }[], + ), + recv: subtractRanges( + data.transcript.ranges.recv.all, + secretResps + .map((secret: string) => { + const index = data.transcript.recv.indexOf(secret); + return index > -1 + ? { + start: index, + end: index + secret.length, + } + : null; + }) + .filter((data: any) => !!data) as { start: number; end: number }[], + ), + }; + + browser.runtime.sendMessage({ + type: OffscreenActionTypes.create_presentation_request, + data: { + id: now, + commit, + }, + }); + + browser.runtime.onMessage.removeListener(onProverResponse); + }; + + const onPresentationResponse = async (request: any) => { + const { data, type } = request; + + if (type !== OffscreenActionTypes.create_presentation_response) { + return; + } + + if (data.error) { + console.error(data.error); + return; + } + + if (data.id !== now) { + return; + } + + console.log(request); + browser.runtime.onMessage.removeListener(onPresentationResponse); + }; + + browser.runtime.onMessage.addListener(onProverResponse); + browser.runtime.onMessage.addListener(onPresentationResponse); + + browser.runtime.sendMessage({ + type: OffscreenActionTypes.create_prover_request, data: { - id, + id: now, url, method, headers, @@ -429,8 +528,6 @@ async function runPluginProver(request: BackgroundAction, now = Date.now()) { websocketProxyUrl, maxRecvData, maxSentData, - secretHeaders, - secretResps, }, }); } diff --git a/src/entries/Offscreen/Offscreen.tsx b/src/entries/Offscreen/Offscreen.tsx index 5841d90e..020fb16c 100644 --- a/src/entries/Offscreen/Offscreen.tsx +++ b/src/entries/Offscreen/Offscreen.tsx @@ -14,12 +14,15 @@ import { BackgroundActiontype } from '../Background/rpc'; import browser from 'webextension-polyfill'; import { PresentationJSON } from '../../utils/types'; import { PresentationJSON as PresentationJSONa7 } from 'tlsn-js/build/types'; -import { Method } from 'tlsn-js/wasm/pkg'; +import { Commit, Method } from 'tlsn-wasm'; +import { subtractRanges } from './utils'; const { init, Prover, Presentation }: any = Comlink.wrap( new Worker(new URL('./worker.ts', import.meta.url)), ); +const provers: { [id: string]: TProver } = {}; + const Offscreen = () => { useEffect(() => { (async () => { @@ -74,6 +77,76 @@ const Offscreen = () => { break; } + case OffscreenActionTypes.create_prover_request: { + const { id } = request.data; + + (async () => { + try { + const prover = await createProver(request.data); + + provers[id] = prover; + + browser.runtime.sendMessage({ + type: OffscreenActionTypes.create_prover_response, + data: { + id, + transcript: await prover.transcript(), + }, + }); + } catch (error) { + console.error(error); + browser.runtime.sendMessage({ + type: OffscreenActionTypes.create_prover_response, + data: { + id, + error, + }, + }); + } + })(); + break; + } + case OffscreenActionTypes.create_presentation_request: { + const { id, commit } = request.data; + (async () => { + const prover = provers[id]; + + try { + if (!prover) throw new Error(`Cannot find prover ${id}.`); + + const notarizationOutputs = await prover.notarize(commit); + + const presentation = (await new Presentation({ + attestationHex: notarizationOutputs.attestation, + secretsHex: notarizationOutputs.secrets, + notaryUrl: notarizationOutputs.notaryUrl, + websocketProxyUrl: notarizationOutputs.websocketProxyUrl, + reveal: commit, + })) as TPresentation; + const presentationJSON = await presentation.json(); + + browser.runtime.sendMessage({ + type: OffscreenActionTypes.create_presentation_response, + data: { + id, + presentation: presentationJSON, + }, + }); + + delete provers[id]; + } catch (error) { + console.error(error); + browser.runtime.sendMessage({ + type: OffscreenActionTypes.create_presentation_response, + data: { + id, + error, + }, + }); + } + })(); + break; + } case BackgroundActiontype.process_prove_request: { const { id } = request.data; @@ -141,46 +214,6 @@ const Offscreen = () => { export default Offscreen; -function subtractRanges( - ranges: { start: number; end: number }, - negatives: { start: number; end: number }[], -): { start: number; end: number }[] { - const returnVal: { start: number; end: number }[] = [ranges]; - - negatives - .sort((a, b) => (a.start < b.start ? -1 : 1)) - .forEach(({ start, end }) => { - const last = returnVal.pop()!; - - if (start < last.start || end > last.end) { - console.error('invalid ranges'); - return; - } - - if (start === last.start && end === last.end) { - return; - } - - if (start === last.start && end < last.end) { - returnVal.push({ start: end, end: last.end }); - return; - } - - if (start > last.start && end < last.end) { - returnVal.push({ start: last.start, end: start }); - returnVal.push({ start: end, end: last.end }); - return; - } - - if (start > last.start && end === last.end) { - returnVal.push({ start: last.start, end: start }); - return; - } - }); - - return returnVal; -} - async function createProof(options: { url: string; notaryUrl: string; @@ -270,8 +303,54 @@ async function createProof(options: { websocketProxyUrl: notarizationOutputs.websocketProxyUrl, reveal: commit, })) as TPresentation; - const presentationJSON = await presentation.json(); - return presentationJSON; + + return presentation.json(); +} + +async function createProver(options: { + url: string; + notaryUrl: string; + websocketProxyUrl: string; + method?: Method; + headers?: { + [name: string]: string; + }; + body?: any; + maxSentData?: number; + maxRecvData?: number; + id: string; +}): Promise { + const { + url, + method = 'GET', + headers = {}, + body, + maxSentData, + maxRecvData, + notaryUrl, + websocketProxyUrl, + id, + } = options; + + const hostname = urlify(url)?.hostname || ''; + const notary = NotaryServer.from(notaryUrl); + const prover: TProver = await new Prover({ + id, + serverDns: hostname, + maxSentData, + maxRecvData, + }); + + await prover.setup(await notary.sessionUrl(maxSentData, maxRecvData)); + + await prover.sendRequest(websocketProxyUrl + `?token=${hostname}`, { + url, + method, + headers, + body, + }); + + return prover; } async function verifyProof( diff --git a/src/entries/Offscreen/types.ts b/src/entries/Offscreen/types.ts index 88733095..2bd16073 100644 --- a/src/entries/Offscreen/types.ts +++ b/src/entries/Offscreen/types.ts @@ -1,4 +1,8 @@ export enum OffscreenActionTypes { notarization_request = 'offscreen/notarization_request', notarization_response = 'offscreen/notarization_response', + create_prover_request = 'offscreen/create_prover_request', + create_prover_response = 'offscreen/create_prover_response', + create_presentation_request = 'offscreen/create_presentation_request', + create_presentation_response = 'offscreen/create_presentation_response', } diff --git a/src/entries/Offscreen/utils.ts b/src/entries/Offscreen/utils.ts new file mode 100644 index 00000000..d5fe894d --- /dev/null +++ b/src/entries/Offscreen/utils.ts @@ -0,0 +1,39 @@ +export function subtractRanges( + ranges: { start: number; end: number }, + negatives: { start: number; end: number }[], +): { start: number; end: number }[] { + const returnVal: { start: number; end: number }[] = [ranges]; + + negatives + .sort((a, b) => (a.start < b.start ? -1 : 1)) + .forEach(({ start, end }) => { + const last = returnVal.pop()!; + + if (start < last.start || end > last.end) { + console.error('invalid ranges'); + return; + } + + if (start === last.start && end === last.end) { + return; + } + + if (start === last.start && end < last.end) { + returnVal.push({ start: end, end: last.end }); + return; + } + + if (start > last.start && end < last.end) { + returnVal.push({ start: last.start, end: start }); + returnVal.push({ start: end, end: last.end }); + return; + } + + if (start > last.start && end === last.end) { + returnVal.push({ start: last.start, end: start }); + return; + } + }); + + return returnVal; +} diff --git a/src/utils/misc.ts b/src/utils/misc.ts index d8adb17e..46091516 100644 --- a/src/utils/misc.ts +++ b/src/utils/misc.ts @@ -207,24 +207,34 @@ export const makePlugin = async ( body: reqBody, } = params; let secretResps; - const resp = await fetch(url, { - method, - headers, - body: reqBody, - }); - const body = await extractBodyFromResponse(resp); - if (getSecretResponse) { - const out = await plugin.call(getSecretResponse, body); - secretResps = JSON.parse(out.string()); - } + // const resp = await fetch(url, { + // method, + // headers, + // body: reqBody, + // }); + // const body = await extractBodyFromResponse(resp); + // console.log('pre', body); + // + // if (getSecretResponse) { + // const out = await plugin.call(getSecretResponse, body); + // secretResps = JSON.parse(out.string()); + // console.log({ secretResps }); + // } handleExecPluginProver({ type: BackgroundActiontype.execute_plugin_prover, data: { ...params, body: reqBody, - secretResps, + getSecretResponse: async (body: string) => { + return new Promise((resolve) => { + setTimeout(async () => { + const out = await plugin.call(getSecretResponse, body); + resolve(JSON.parse(out.string())); + }, 0); + }); + }, now, }, }); From 7776b59f4556dbd486aaba417b5e94ef444ebe5a Mon Sep 17 00:00:00 2001 From: tsukino <0xtsukino@gmail.com> Date: Thu, 31 Oct 2024 18:17:45 +0800 Subject: [PATCH 2/5] fix: use transcript for redaction --- src/entries/Background/rpc.ts | 89 ++++++++++------------------- src/entries/Offscreen/Offscreen.tsx | 6 +- src/entries/SidePanel/SidePanel.tsx | 1 + src/utils/misc.ts | 25 +------- 4 files changed, 37 insertions(+), 84 deletions(-) diff --git a/src/entries/Background/rpc.ts b/src/entries/Background/rpc.ts index 574c1796..530dba0b 100644 --- a/src/entries/Background/rpc.ts +++ b/src/entries/Background/rpc.ts @@ -34,6 +34,7 @@ import { hexToArrayBuffer, makePlugin, PluginConfig, + safeParseJSON, } from '../../utils/misc'; import { getLoggingFilter, @@ -384,8 +385,8 @@ async function runPluginProver(request: BackgroundAction, now = Date.now()) { headers, body, secretHeaders = [], - // secretResps, getSecretResponse, + getSecretResponseFn, notaryUrl: _notaryUrl, websocketProxyUrl: _websocketProxyUrl, maxSentData: _maxSentData, @@ -398,28 +399,28 @@ async function runPluginProver(request: BackgroundAction, now = Date.now()) { let secretResps: string[] = []; - // const { id } = await addNotaryRequest(now, { - // url, - // method, - // headers, - // body, - // notaryUrl, - // websocketProxyUrl, - // maxRecvData, - // maxSentData, - // secretHeaders, - // secretResps, - // }); - // - // await setNotaryRequestStatus(id, 'pending'); - // - // await browser.runtime.sendMessage({ - // type: BackgroundActiontype.push_action, - // data: { - // tabId: 'background', - // }, - // action: addRequestHistory(await getNotaryRequest(id)), - // }); + const { id } = await addNotaryRequest(now, { + url, + method, + headers, + body, + notaryUrl, + websocketProxyUrl, + maxRecvData, + maxSentData, + secretHeaders, + secretResps, + }); + + await setNotaryRequestStatus(id, 'pending'); + + await browser.runtime.sendMessage({ + type: BackgroundActiontype.push_action, + data: { + tabId: 'background', + }, + action: addRequestHistory(await getNotaryRequest(id)), + }); const onProverResponse = async (request: any) => { const { data, type } = request; @@ -433,22 +434,15 @@ async function runPluginProver(request: BackgroundAction, now = Date.now()) { return; } - if (data.id !== now) { + if (data.id !== id) { return; } if (getSecretResponse) { - console.log('getting secret response'); - const { - recv, - ranges: { - recv: { - body: { start }, - all: { end }, - }, - }, - } = data.transcript; - secretResps = await getSecretResponse(recv.slice(start, end)); + const body = data.transcript.recv + .split('\r\n') + .filter((txt: string) => safeParseJSON(txt))[0]; + secretResps = await getSecretResponseFn(body); } const commit = { @@ -485,7 +479,7 @@ async function runPluginProver(request: BackgroundAction, now = Date.now()) { browser.runtime.sendMessage({ type: OffscreenActionTypes.create_presentation_request, data: { - id: now, + id, commit, }, }); @@ -493,33 +487,12 @@ async function runPluginProver(request: BackgroundAction, now = Date.now()) { browser.runtime.onMessage.removeListener(onProverResponse); }; - const onPresentationResponse = async (request: any) => { - const { data, type } = request; - - if (type !== OffscreenActionTypes.create_presentation_response) { - return; - } - - if (data.error) { - console.error(data.error); - return; - } - - if (data.id !== now) { - return; - } - - console.log(request); - browser.runtime.onMessage.removeListener(onPresentationResponse); - }; - browser.runtime.onMessage.addListener(onProverResponse); - browser.runtime.onMessage.addListener(onPresentationResponse); browser.runtime.sendMessage({ type: OffscreenActionTypes.create_prover_request, data: { - id: now, + id, url, method, headers, diff --git a/src/entries/Offscreen/Offscreen.tsx b/src/entries/Offscreen/Offscreen.tsx index 020fb16c..47360a39 100644 --- a/src/entries/Offscreen/Offscreen.tsx +++ b/src/entries/Offscreen/Offscreen.tsx @@ -126,10 +126,10 @@ const Offscreen = () => { const presentationJSON = await presentation.json(); browser.runtime.sendMessage({ - type: OffscreenActionTypes.create_presentation_response, + type: BackgroundActiontype.finish_prove_request, data: { id, - presentation: presentationJSON, + proof: presentationJSON, }, }); @@ -137,7 +137,7 @@ const Offscreen = () => { } catch (error) { console.error(error); browser.runtime.sendMessage({ - type: OffscreenActionTypes.create_presentation_response, + type: BackgroundActiontype.finish_prove_request, data: { id, error, diff --git a/src/entries/SidePanel/SidePanel.tsx b/src/entries/SidePanel/SidePanel.tsx index ba8046b1..2c5d8945 100644 --- a/src/entries/SidePanel/SidePanel.tsx +++ b/src/entries/SidePanel/SidePanel.tsx @@ -109,6 +109,7 @@ function PluginBody(props: {
{steps?.map((step, i) => ( { - const { - url, - method, - headers, - getSecretResponse, - body: reqBody, - } = params; - let secretResps; - - // const resp = await fetch(url, { - // method, - // headers, - // body: reqBody, - // }); - // const body = await extractBodyFromResponse(resp); - // console.log('pre', body); - // - // if (getSecretResponse) { - // const out = await plugin.call(getSecretResponse, body); - // secretResps = JSON.parse(out.string()); - // console.log({ secretResps }); - // } + const { getSecretResponse, body: reqBody } = params; handleExecPluginProver({ type: BackgroundActiontype.execute_plugin_prover, data: { ...params, body: reqBody, - getSecretResponse: async (body: string) => { + getSecretResponseFn: async (body: string) => { return new Promise((resolve) => { setTimeout(async () => { const out = await plugin.call(getSecretResponse, body); From 727582eee9146770fb88a5df53b078de21c34476 Mon Sep 17 00:00:00 2001 From: tsukino <0xtsukino@gmail.com> Date: Mon, 4 Nov 2024 17:39:55 +0800 Subject: [PATCH 3/5] refactor: add map secret to ranges utility --- src/entries/Background/plugins/utils.ts | 14 ++++++++++++++ src/entries/Background/rpc.ts | 25 +++---------------------- src/entries/Offscreen/Offscreen.tsx | 25 +++---------------------- 3 files changed, 20 insertions(+), 44 deletions(-) diff --git a/src/entries/Background/plugins/utils.ts b/src/entries/Background/plugins/utils.ts index cb7bc081..bcd78f76 100644 --- a/src/entries/Background/plugins/utils.ts +++ b/src/entries/Background/plugins/utils.ts @@ -26,4 +26,18 @@ export async function installPlugin( filePath, }); return hash; +} + +export function mapSecretsToRange(secrets: string[], text: string) { + return secrets + .map((secret: string) => { + const index = text.indexOf(secret); + return index > -1 + ? { + start: index, + end: index + secret.length, + } + : null; + }) + .filter((data: any) => !!data) as { start: number; end: number }[] } \ No newline at end of file diff --git a/src/entries/Background/rpc.ts b/src/entries/Background/rpc.ts index 530dba0b..3e488fbd 100644 --- a/src/entries/Background/rpc.ts +++ b/src/entries/Background/rpc.ts @@ -48,6 +48,7 @@ import { minimatch } from 'minimatch'; import { OffscreenActionTypes } from '../Offscreen/types'; import { SidePanelActionTypes } from '../SidePanel/types'; import { subtractRanges } from '../Offscreen/utils'; +import { mapSecretsToRange } from './plugins/utils'; const charwise = require('charwise'); @@ -448,31 +449,11 @@ async function runPluginProver(request: BackgroundAction, now = Date.now()) { const commit = { sent: subtractRanges( data.transcript.ranges.sent.all, - secretHeaders - .map((secret: string) => { - const index = data.transcript.sent.indexOf(secret); - return index > -1 - ? { - start: index, - end: index + secret.length, - } - : null; - }) - .filter((data: any) => !!data) as { start: number; end: number }[], + mapSecretsToRange(secretHeaders, data.transcript.sent), ), recv: subtractRanges( data.transcript.ranges.recv.all, - secretResps - .map((secret: string) => { - const index = data.transcript.recv.indexOf(secret); - return index > -1 - ? { - start: index, - end: index + secret.length, - } - : null; - }) - .filter((data: any) => !!data) as { start: number; end: number }[], + mapSecretsToRange(secretResps, data.transcript.recv), ), }; diff --git a/src/entries/Offscreen/Offscreen.tsx b/src/entries/Offscreen/Offscreen.tsx index 47360a39..2d93dc5d 100644 --- a/src/entries/Offscreen/Offscreen.tsx +++ b/src/entries/Offscreen/Offscreen.tsx @@ -16,6 +16,7 @@ import { PresentationJSON } from '../../utils/types'; import { PresentationJSON as PresentationJSONa7 } from 'tlsn-js/build/types'; import { Commit, Method } from 'tlsn-wasm'; import { subtractRanges } from './utils'; +import { mapSecretsToRange } from '../Background/plugins/utils'; const { init, Prover, Presentation }: any = Comlink.wrap( new Worker(new URL('./worker.ts', import.meta.url)), @@ -266,31 +267,11 @@ async function createProof(options: { const commit = { sent: subtractRanges( transcript.ranges.sent.all, - secretHeaders - .map((secret: string) => { - const index = transcript.sent.indexOf(secret); - return index > -1 - ? { - start: index, - end: index + secret.length, - } - : null; - }) - .filter((data: any) => !!data) as { start: number; end: number }[], + mapSecretsToRange(secretHeaders, transcript.sent), ), recv: subtractRanges( transcript.ranges.recv.all, - secretResps - .map((secret: string) => { - const index = transcript.recv.indexOf(secret); - return index > -1 - ? { - start: index, - end: index + secret.length, - } - : null; - }) - .filter((data: any) => !!data) as { start: number; end: number }[], + mapSecretsToRange(secretResps, transcript.recv), ), }; From 3fffc8eda85a232955860f1e69091b03df145267 Mon Sep 17 00:00:00 2001 From: tsukino <0xtsukino@gmail.com> Date: Mon, 4 Nov 2024 18:05:42 +0800 Subject: [PATCH 4/5] fix: body selector --- src/entries/Background/rpc.ts | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/entries/Background/rpc.ts b/src/entries/Background/rpc.ts index 3e488fbd..c62b0928 100644 --- a/src/entries/Background/rpc.ts +++ b/src/entries/Background/rpc.ts @@ -440,10 +440,29 @@ async function runPluginProver(request: BackgroundAction, now = Date.now()) { } if (getSecretResponse) { - const body = data.transcript.recv - .split('\r\n') - .filter((txt: string) => safeParseJSON(txt))[0]; - secretResps = await getSecretResponseFn(body); + const body = data.transcript.recv.split('\r\n').reduce( + ( + state: { headerEnd: boolean; isBody: boolean; body: string[] }, + line: string, + ) => { + if (state.headerEnd) { + state.body.push(line); + } else if (!line) { + state.headerEnd = true; + } + + return state; + }, + { headerEnd: false, body: [] }, + ).body; + + if (body.length == 1) { + secretResps = await getSecretResponseFn(body[0]); + } else { + secretResps = await getSecretResponse( + body.filter((txt: string) => safeParseJSON(txt))[0], + ); + } } const commit = { From 94e5a370643f44d9076723e72bfa78b719870c21 Mon Sep 17 00:00:00 2001 From: tsukino <0xtsukino@gmail.com> Date: Mon, 4 Nov 2024 18:19:19 +0800 Subject: [PATCH 5/5] fix --- src/entries/Background/rpc.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/entries/Background/rpc.ts b/src/entries/Background/rpc.ts index c62b0928..37a9e500 100644 --- a/src/entries/Background/rpc.ts +++ b/src/entries/Background/rpc.ts @@ -460,7 +460,10 @@ async function runPluginProver(request: BackgroundAction, now = Date.now()) { secretResps = await getSecretResponseFn(body[0]); } else { secretResps = await getSecretResponse( - body.filter((txt: string) => safeParseJSON(txt))[0], + body.filter((txt: string) => { + const json = safeParseJSON(txt); + return typeof json === 'object'; + })[0], ); } }