From 2a8e93e4beda3a280ca02b0951bbd704fef4e7e1 Mon Sep 17 00:00:00 2001 From: KevinWh0 <45321184+KevinWh0@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:58:50 +0100 Subject: [PATCH] Fixed code injection from twitter import --- .../processors/ImportNotesProcessorService.ts | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/packages/backend/src/queue/processors/ImportNotesProcessorService.ts b/packages/backend/src/queue/processors/ImportNotesProcessorService.ts index 817befdf0..e5177d28e 100644 --- a/packages/backend/src/queue/processors/ImportNotesProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportNotesProcessorService.ts @@ -130,6 +130,17 @@ export class ImportNotesProcessorService { return typeof obj[Symbol.iterator] === 'function'; } + private parseTwitterFile(str : string) : null | [{ tweet: any }] { + const removed = str.replace(new RegExp('window\\.YTD\\.tweets\\.part0 = ', 'g'), ''); + + try { + return JSON.parse(removed); + } catch (error) { + //The format is not what we expected. Either this file was tampered with or twitters exports changed + return null; + } + } + @bindThis public async process(job: Bull.Job): Promise { this.logger.info(`Starting note import of ${job.data.user.id} ...`); @@ -175,23 +186,20 @@ export class ImportNotesProcessorService { try { this.logger.succ(`Unzipping to ${outputPath}`); ZipReader.withDestinationPath(outputPath).viaBuffer(await fs.promises.readFile(destPath)); - const fakeWindow: any = { - window: { - YTD: { - tweets: { - part0: {}, - }, - }, - }, - }; - const script = new vm.Script(fs.readFileSync(outputPath + '/data/tweets.js', 'utf-8')); - const context = vm.createContext(fakeWindow); - script.runInContext(context); - const tweets = Object.keys(fakeWindow.window.YTD.tweets.part0).reduce((m, key, i, obj) => { - return m.concat(fakeWindow.window.YTD.tweets.part0[key].tweet); - }, []); - const processedTweets = await this.recreateChain(['id_str'], ['in_reply_to_status_id_str'], tweets, false); - this.queueService.createImportTweetsToDbJob(job.data.user, processedTweets, null); + + const unprocessedTweetJson = this.parseTwitterFile(fs.readFileSync(outputPath + '/data/tweets.js', 'utf-8')); + + //Make sure that it isnt null (because if something went wrong in parseTwitterFile it returns null) + if (unprocessedTweetJson) { + const tweets = Object.keys(unprocessedTweetJson).reduce((m, key, i, obj) => { + return m.concat(unprocessedTweetJson[i].tweet); + }, []); + + const processedTweets = await this.recreateChain(['id_str'], ['in_reply_to_status_id_str'], tweets, false); + this.queueService.createImportTweetsToDbJob(job.data.user, processedTweets, null); + } else { + this.logger.warn('Failed to import twitter notes due to malformed file'); + } } finally { cleanup(); }