From 77e3c2115b31d3216e725f0879bdad70a09b60be Mon Sep 17 00:00:00 2001 From: Jorrin Date: Tue, 9 Jan 2024 21:35:03 +0100 Subject: [PATCH] really really basic domain whitelisting --- package.json | 7 ++- pnpm-lock.yaml | 20 +++++++ .../messages/declarative-net-request.ts | 4 ++ src/background/messages/proxy-request.ts | 3 + src/contents/movie-web.ts | 2 +- src/popup.tsx | 59 +++++++++++++++++-- src/utils/storage.ts | 15 +++++ 7 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 src/utils/storage.ts diff --git a/package.json b/package.json index 8c49719..279958a 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ }, "dependencies": { "@plasmohq/messaging": "^0.6.1", + "@plasmohq/storage": "^1.9.0", "plasmo": "0.84.0", "react": "18.2.0", "react-dom": "18.2.0" @@ -24,8 +25,6 @@ "@types/node": "20.9.0", "@types/react": "18.2.37", "@types/react-dom": "18.2.15", - "prettier": "3.0.3", - "typescript": "5.2.2", "@typescript-eslint/eslint-plugin": "^6.15.0", "@typescript-eslint/parser": "^6.15.0", "eslint": "^8.56.0", @@ -33,7 +32,9 @@ "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-prettier": "^5.1.1" + "eslint-plugin-prettier": "^5.1.1", + "prettier": "3.0.3", + "typescript": "5.2.2" }, "manifest": { "permissions": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a88f228..83f4b7b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ dependencies: '@plasmohq/messaging': specifier: ^0.6.1 version: 0.6.1(react@18.2.0) + '@plasmohq/storage': + specifier: ^1.9.0 + version: 1.9.0(react@18.2.0) plasmo: specifier: 0.84.0 version: 0.84.0(react-dom@18.2.0)(react@18.2.0) @@ -2308,6 +2311,18 @@ packages: - whiskers dev: false + /@plasmohq/storage@1.9.0(react@18.2.0): + resolution: {integrity: sha512-mntoJ0EVh7JfYyMKWKnt6yqVlJnwavEkwdXssSOxS1CEeyNX2GPkXQfChvlGhuEJplqcRhLaym6rEc690Ao0fg==} + peerDependencies: + react: ^16.8.6 || ^17 || ^18 + peerDependenciesMeta: + react: + optional: true + dependencies: + pify: 6.1.0 + react: 18.2.0 + dev: false + /@pnpm/config.env-replace@1.1.0: resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} engines: {node: '>=12.22.0'} @@ -5748,6 +5763,11 @@ packages: dev: false optional: true + /pify@6.1.0: + resolution: {integrity: sha512-KocF8ve28eFjjuBKKGvzOBGzG8ew2OqOOSxTTZhirkzH7h3BI1vyzqlR0qbfcDBve1Yzo3FVlWUAtCRrbVN8Fw==} + engines: {node: '>=14.16'} + dev: false + /pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} diff --git a/src/background/messages/declarative-net-request.ts b/src/background/messages/declarative-net-request.ts index e415ded..032954b 100644 --- a/src/background/messages/declarative-net-request.ts +++ b/src/background/messages/declarative-net-request.ts @@ -1,7 +1,9 @@ import type { PlasmoMessaging } from '@plasmohq/messaging'; +import { domainIsInWhitelist, validateDomainWhiteList } from '~utils/storage'; interface RequestBody { ruleId: number; + requestDomain: string; domain: string; requestHeaders?: Record; responseHeaders?: Record; @@ -19,6 +21,8 @@ const mapHeadersToDeclarativeNetRequestHeaders = ( const handler: PlasmoMessaging.MessageHandler = async (req, res) => { try { + await validateDomainWhiteList(req.body.requestDomain); + await chrome.declarativeNetRequest.updateDynamicRules({ removeRuleIds: [req.body.ruleId], addRules: [ diff --git a/src/background/messages/proxy-request.ts b/src/background/messages/proxy-request.ts index 8115fd6..0836650 100644 --- a/src/background/messages/proxy-request.ts +++ b/src/background/messages/proxy-request.ts @@ -1,7 +1,10 @@ import type { PlasmoMessaging } from '@plasmohq/messaging'; +import { domainIsInWhitelist, validateDomainWhiteList } from '~utils/storage'; const handler: PlasmoMessaging.MessageHandler = async (req, res) => { try { + await validateDomainWhiteList(req.body.requestDomain); + const response = await fetch(req.body.url, { headers: req.body.headers, }); diff --git a/src/contents/movie-web.ts b/src/contents/movie-web.ts index 2508ecf..d59faee 100644 --- a/src/contents/movie-web.ts +++ b/src/contents/movie-web.ts @@ -3,7 +3,7 @@ import type { PlasmoCSConfig } from 'plasmo'; import { relayMessage } from '@plasmohq/messaging'; export const config: PlasmoCSConfig = { - matches: ['https://movie-web.app/*', 'https://dev.movie-web.app/*', 'http://localhost:5173/*'], + matches: [''], }; relayMessage({ diff --git a/src/popup.tsx b/src/popup.tsx index e325f22..5e74211 100644 --- a/src/popup.tsx +++ b/src/popup.tsx @@ -1,9 +1,60 @@ +import { useStorage } from '@plasmohq/storage/hook' +import { useState } from 'react'; +import { DEFAULT_DOMAIN_WHITELIST } from '~utils/storage'; + function IndexPopup() { + const [domainInput, setDomainInput] = useState(''); + const [domainWhiteist, setDomainWhitelist] = useStorage('domainWhitelist', (v) => v ?? DEFAULT_DOMAIN_WHITELIST) + + const [error, setError] = useState(null) + + const handleDomainSubmit = () => { + try { + const origin = new URL(domainInput).origin + setDomainWhitelist([...domainWhiteist, origin]) + setDomainInput('') + } catch (e) { + setError('Invalid domain') + } + } + return ( -
-

- Extension running at version {chrome.runtime.getManifest().version} -

+
+
+

+ movie-web +

+ +

+ v{chrome.runtime.getManifest().version} +

+
+ +

Domains

+ +
+
+ setDomainInput(e.target.value)} + /> + +
+ {error && {error}} + + + {domainWhiteist.map((domain) => ( + + + + + ))} + +
{domain} + +
+
) } diff --git a/src/utils/storage.ts b/src/utils/storage.ts new file mode 100644 index 0000000..a173abd --- /dev/null +++ b/src/utils/storage.ts @@ -0,0 +1,15 @@ +import { Storage } from '@plasmohq/storage'; + +export const DEFAULT_DOMAIN_WHITELIST = ['https://movie-web.app', 'http://localhost:5173']; + +export const storage = new Storage(); + +export const domainIsInWhitelist = async (domain: string) => { + const whitelist = await storage.get('domainWhitelist'); + return whitelist?.some((d) => d.includes(domain)) ?? false; +}; + +export const validateDomainWhiteList = async (domain: string) => { + const isWhiteListed = await domainIsInWhitelist(domain); + if (!isWhiteListed) throw new Error('Domain is not whitelisted'); +};