Skip to content

Commit

Permalink
Merge pull request #131 from gnosisguild/various-fixes
Browse files Browse the repository at this point in the history
fix execution as Safe owner
  • Loading branch information
jfschwarz authored Aug 16, 2024
2 parents 700ee8c + bb6eb46 commit 72063a0
Show file tree
Hide file tree
Showing 230 changed files with 2,426 additions and 2,744 deletions.
2,554 changes: 1,211 additions & 1,343 deletions extension/.pnp.cjs

Large diffs are not rendered by default.

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
20 changes: 12 additions & 8 deletions extension/esbuild.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-check
const esbuild = require('esbuild')
const cssModulesPlugin = require('esbuild-css-modules-plugin')
const plugin = require('node-stdlib-browser/helpers/esbuild/plugin')
Expand All @@ -6,7 +7,7 @@ const stdLibBrowser = require('node-stdlib-browser')
require('dotenv').config()

esbuild
.build({
.context({
entryPoints: [
'./src/background.ts',
'./src/contentScript.ts',
Expand All @@ -33,11 +34,14 @@ esbuild
global: 'window',
},
plugins: [plugin(stdLibBrowser), cssModulesPlugin()],
watch: process.env.NODE_ENV === 'development' && {
onRebuild() {
console.log('Rebuild successful.')
},
},
logLevel: 'info',
})
.then(async (ctx) => {
if (process.env.NODE_ENV === 'development') {
await ctx.watch()
} else {
await ctx.rebuild()
console.log('Build successful.')
ctx.dispose()
}
})
.then(() => console.log('Build successful.'))
.catch(() => process.exit(1))
16 changes: 8 additions & 8 deletions extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@
"@eslint/js": "^9.7.0",
"@gnosis.pm/zodiac": "^4.0.3",
"@noble/hashes": "^1.4.0",
"@safe-global/api-kit": "^2.4.4",
"@safe-global/protocol-kit": "^4.0.4",
"@safe-global/api-kit": "^2.4.2",
"@safe-global/protocol-kit": "^4.0.2",
"@safe-global/safe-apps-sdk": "^9.1.0",
"@safe-global/safe-core-sdk-types": "^5.0.3",
"@safe-global/safe-gateway-typescript-sdk": "^3.22.2",
"@safe-global/safe-core-sdk-types": "^5.0.2",
"@safe-global/safe-gateway-typescript-sdk": "^3.21.10",
"@shazow/whatsabi": "^0.13.2",
"@testing-library/dom": "^10.3.1",
"@testing-library/jest-dom": "^6.4.6",
Expand All @@ -54,8 +54,8 @@
"copy-to-clipboard": "^3.3.1",
"cspell": "^5.21.2",
"dotenv": "^16.0.1",
"esbuild": "^0.16.17",
"esbuild-css-modules-plugin": "^2.7.0",
"esbuild": "^0.23.0",
"esbuild-css-modules-plugin": "^2.7.1",
"eslint": "^9.7.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-jsx-a11y": "^6.9.0",
Expand All @@ -80,8 +80,8 @@
"react-select": "^5.2.1",
"react-toastify": "^9.0.8",
"rimraf": "^3.0.2",
"ser-kit": "^0.3.10",
"typescript": "^5.5.3",
"ser-kit": "^0.3.17",
"typescript": "^5.5.4",
"typescript-eslint": "^7.16.0",
"typescript-plugin-css-modules": "^5.1.0",
"vitest": "^2.0.2",
Expand Down
3 changes: 2 additions & 1 deletion extension/public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
},
"permissions": [
"tabs",
"declarativeNetRequest",
"declarativeNetRequestWithHostAccess",
"declarativeNetRequestFeedback",
"webRequest"
],
"background": {
Expand Down
96 changes: 58 additions & 38 deletions extension/src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ interface Fork {
rpcUrl: string
}

chrome.declarativeNetRequest.onRuleMatchedDebug.addListener((details) => {
if (details.rule.ruleId !== HEADERS_RULE_ID) {
console.debug(
'rule matched on request',
details.request.url,
details.rule.ruleId
)
}
})

// Track tabs showing our extension, so we can dynamically adjust the declarativeNetRequest rule.
// This rule removes some headers so foreign pages can be loaded in iframes. We don't want to
// generally circumvent this security mechanism, so we only apply it to extension tabs.
Expand All @@ -27,42 +37,62 @@ const stopTrackingTab = (tabId: number) => {
console.log('Pilot: stopped tracking tab', tabId)
}

const HEADERS_RULE_ID = 1

const updateHeadersRule = () => {
const RULE_ID = 1
// TODO removing the CSP headers alone is not enough as it does not handle apps setting CSPs via <meta http-equiv> tags in the HTML (such as Uniswap, for example)
// see: https://github.com/w3c/webextensions/issues/169#issuecomment-1689812644
// A potential solution could be a service worker rewriting the HTML content in the doc request to filter out these tags?
chrome.declarativeNetRequest.updateSessionRules(
{
addRules: [
{
id: RULE_ID,
id: HEADERS_RULE_ID,
priority: 1,
action: {
// @ts-expect-error @types/chrome uses enums which we can't access
type: 'modifyHeaders',
type: chrome.declarativeNetRequest.RuleActionType.MODIFY_HEADERS,
responseHeaders: [
// @ts-expect-error @types/chrome uses enums which we can't access
{ header: 'x-frame-options', operation: 'remove' },
// @ts-expect-error @types/chrome uses enums which we can't access
{ header: 'X-Frame-Options', operation: 'remove' },
// @ts-expect-error @types/chrome uses enums which we can't access
{ header: 'content-security-policy', operation: 'remove' },
// @ts-expect-error @types/chrome uses enums which we can't access
{ header: 'Content-Security-Policy', operation: 'remove' },
{
header: 'x-frame-options',
operation: chrome.declarativeNetRequest.HeaderOperation.REMOVE,
},
{
header: 'X-Frame-Options',
operation: chrome.declarativeNetRequest.HeaderOperation.REMOVE,
},
{
header: 'content-security-policy',
operation: chrome.declarativeNetRequest.HeaderOperation.REMOVE,
},
{
header: 'Content-Security-Policy',
operation: chrome.declarativeNetRequest.HeaderOperation.REMOVE,
},
{
header: 'content-security-policy-report-only',
operation: chrome.declarativeNetRequest.HeaderOperation.REMOVE,
},
{
header: 'Content-Security-Policy-Report-Only',
operation: chrome.declarativeNetRequest.HeaderOperation.REMOVE,
},
],
},
condition: {
// @ts-expect-error @types/chrome uses enums which we can't access
resourceTypes: ['sub_frame'],
resourceTypes: [
chrome.declarativeNetRequest.ResourceType.SUB_FRAME,
],
tabIds: Array.from(activeExtensionTabs),
},
},
],
removeRuleIds: [RULE_ID],
removeRuleIds: [HEADERS_RULE_ID],
},
() => {
if (chrome.runtime.lastError) {
console.error('Rule update failed', chrome.runtime.lastError)
console.error('Headers rule update failed', chrome.runtime.lastError)
} else {
console.debug('Rule update successful', activeExtensionTabs)
console.debug('Headers rule update successful', activeExtensionTabs)
}
}
)
Expand Down Expand Up @@ -131,21 +161,21 @@ async function clearStaleRules() {
activeExtensionTabs.difference(openTabIds).forEach((tabId) => {
activeExtensionTabs.delete(tabId)
})
console.log({ activeExtensionTabs, openTabIds })

// clear simulatingExtensionTabs that are not active (= extension is activated) anymore
const simulatingTabIds = new Set(simulatingExtensionTabs.keys())
simulatingTabIds.difference(activeExtensionTabs).forEach((tabId) => {
simulatingExtensionTabs.delete(tabId)
})

// remove rules for tabs that are not simulating anymore
// remove redirect rules for tabs that are not simulating anymore
const staleRules = await new Promise<chrome.declarativeNetRequest.Rule[]>(
(resolve) => {
chrome.declarativeNetRequest.getSessionRules((rules) => {
resolve(
rules.filter(
(rule) =>
rule.id !== HEADERS_RULE_ID &&
rule.condition.tabIds?.length === 1 &&
!simulatingExtensionTabs.has(rule.condition.tabIds[0])
)
Expand All @@ -160,7 +190,7 @@ async function clearStaleRules() {
console.debug('Cleared stale rules', staleRules)
}

const updateRpcRedirectRules = (tabId: number) => {
const updateRpcRedirectRules = async (tabId: number) => {
const fork = simulatingExtensionTabs.get(tabId)
if (!fork) {
return
Expand All @@ -177,11 +207,13 @@ const updateRpcRedirectRules = (tabId: number) => {
id: hash(rpcUrl, tabId),
priority: 1,
action: {
type: 'redirect',
type: chrome.declarativeNetRequest.RuleActionType.REDIRECT,
redirect: { url: fork.rpcUrl },
},
condition: {
resourceTypes: ['xmlhttprequest'],
resourceTypes: [
chrome.declarativeNetRequest.ResourceType.XMLHTTPREQUEST,
],
urlFilter: rpcUrl,
tabIds: [tabId],
},
Expand All @@ -192,7 +224,7 @@ const updateRpcRedirectRules = (tabId: number) => {
hash(rpcUrl, tabId)
)

chrome.declarativeNetRequest.updateSessionRules({
await chrome.declarativeNetRequest.updateSessionRules({
addRules,
removeRuleIds: ruleIds,
})
Expand All @@ -211,25 +243,14 @@ const removeRpcRedirectRules = (tabId: number) => {
chrome.declarativeNetRequest.updateSessionRules({
removeRuleIds: ruleIds,
})
console.log(
'removeRpcRedirectRules',
tabId,
ruleIds,
hash(
'https://virtual.mainnet.rpc.tenderly.co/880388c4-9707-46ce-97a5-1095090a6768',
735219801
)
)
console.log('removed all RPC redirect rules for tab', tabId, ruleIds)
}

chrome.runtime.onMessage.addListener((message, sender) => {
if (!sender.tab?.id) return

if (message.type === 'startSimulating') {
const { networkId, rpcUrl } = message
console.log('startSimulating', networkId, rpcUrl, {
simulatingExtensionTabs,
})
simulatingExtensionTabs.delete(sender.tab.id)
removeRpcRedirectRules(sender.tab.id)
simulatingExtensionTabs.set(sender.tab.id, {
Expand All @@ -245,7 +266,6 @@ chrome.runtime.onMessage.addListener((message, sender) => {
}

if (message.type === 'stopSimulating') {
console.log('stopSimulating', sender.tab.id, { simulatingExtensionTabs })
simulatingExtensionTabs.delete(sender.tab.id)
removeRpcRedirectRules(sender.tab.id)

Expand Down Expand Up @@ -304,12 +324,12 @@ const detectNetworkOfRpcUrl = async (url: string, tabId: number) => {
) as Map<string, Promise<number | undefined>>

if (!networkIdOfRpcUrlPromise.has(url)) {
const promise = new Promise((resolve) => {
const promise = new Promise<number | undefined>((resolve) => {
// fetch from the injected script, so the request has the apps origin (otherwise the request may be blocked by the RPC provider)
chrome.tabs.sendMessage(tabId, { type: 'requestChainId', url }, resolve)
})

networkIdOfRpcUrlPromise.set(url, promise as Promise<number | undefined>)
networkIdOfRpcUrlPromise.set(url, promise)
}

const result = await networkIdOfRpcUrlPromise.get(url)
Expand Down
6 changes: 3 additions & 3 deletions extension/src/browser/Drawer/Remove.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { RiDeleteBinLine } from 'react-icons/ri'
import { IconButton } from '../../components'
import { ForkProvider } from '../../providers'
import { useProvider } from '../ProvideProvider'
import { TransactionState, useDispatch, useNewTransactions } from '../../state'
import { TransactionState, useDispatch, useTransactions } from '../../state'

import classes from './style.module.css'

Expand All @@ -15,7 +15,7 @@ type Props = {
export const Remove: React.FC<Props> = ({ transactionState, index }) => {
const provider = useProvider()
const dispatch = useDispatch()
const transactions = useNewTransactions()
const transactions = useTransactions()

if (!(provider instanceof ForkProvider)) {
// Removing transactions is only supported when using ForkProvider
Expand All @@ -28,7 +28,7 @@ export const Remove: React.FC<Props> = ({ transactionState, index }) => {
// remove the transaction and all later ones from the store
dispatch({
type: 'REMOVE_TRANSACTION',
payload: { snapshotId: transactionState.snapshotId },
payload: { id: transactionState.id },
})

if (transactions.length === 1) {
Expand Down
Loading

0 comments on commit 72063a0

Please sign in to comment.