Skip to content

Commit

Permalink
feat: introduce ses in dev
Browse files Browse the repository at this point in the history
  • Loading branch information
Jack-Works committed Mar 2, 2022
1 parent 5adda0a commit 8969697
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 13 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"react": "18.0.0-rc.0",
"react-dom": "18.0.0-rc.0",
"react-i18next": "^11.15.4",
"ses": "^0.15.10",
"ts-results": "3.3.0",
"web3-core": "1.5.2",
"web3-core-method": "1.5.2"
Expand Down
26 changes: 21 additions & 5 deletions packages/mask/.webpack/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import './clean-hmr'

export function createConfiguration(rawFlags: BuildFlags): Configuration {
const normalizedFlags = normalizeBuildFlags(rawFlags)
const { sourceMapKind } = computedBuildFlags(normalizedFlags)
const { sourceMapKind, lockdown } = computedBuildFlags(normalizedFlags)
const { hmr, mode, profiling, reactRefresh, readonlyCache, reproducibleBuild, runtime, outputPath } =
normalizedFlags

Expand Down Expand Up @@ -204,6 +204,13 @@ export function createConfiguration(rawFlags: BuildFlags): Configuration {
to: polyfillFolder,
},
{ from: require.resolve('webextension-polyfill/dist/browser-polyfill.js'), to: polyfillFolder },
{
from:
mode === 'development'
? require.resolve('../../../node_modules/ses/dist/lockdown.umd.js')
: require.resolve('../../../node_modules/ses/dist/lockdown.umd.min.js'),
to: join(polyfillFolder, 'lockdown.js'),
},
],
}),
emitManifestFile(normalizedFlags),
Expand Down Expand Up @@ -276,14 +283,15 @@ export function createConfiguration(rawFlags: BuildFlags): Configuration {
debug: normalizeEntryDescription(join(__dirname, '../src/extension/debug-page/index.tsx')),
})
baseConfig.plugins!.push(
addHTMLEntry({ chunks: ['dashboard'], filename: 'dashboard.html', sourceMap: !!sourceMapKind }),
addHTMLEntry({ chunks: ['popups'], filename: 'popups.html', sourceMap: !!sourceMapKind }),
addHTMLEntry({ chunks: ['dashboard'], filename: 'dashboard.html', sourceMap: !!sourceMapKind, lockdown }),
addHTMLEntry({ chunks: ['popups'], filename: 'popups.html', sourceMap: !!sourceMapKind, lockdown }),
addHTMLEntry({
chunks: ['contentScript'],
filename: 'generated__content__script.html',
sourceMap: !!sourceMapKind,
lockdown,
}),
addHTMLEntry({ chunks: ['debug'], filename: 'debug.html', sourceMap: !!sourceMapKind }),
addHTMLEntry({ chunks: ['debug'], filename: 'debug.html', sourceMap: !!sourceMapKind, lockdown }),
)
// background
if (runtime.manifest === 3) {
Expand All @@ -301,6 +309,7 @@ export function createConfiguration(rawFlags: BuildFlags): Configuration {
filename: 'background.html',
secp256k1: true,
sourceMap: !!sourceMapKind,
lockdown,
}),
)
}
Expand All @@ -324,7 +333,7 @@ export function createConfiguration(rawFlags: BuildFlags): Configuration {
}
}
}
function addHTMLEntry(options: HTMLPlugin.Options & { secp256k1?: boolean; sourceMap: boolean }) {
function addHTMLEntry(options: HTMLPlugin.Options & { secp256k1?: boolean; sourceMap: boolean; lockdown: boolean }) {
let templateContent = readFileSync(join(__dirname, './template.html'), 'utf8')
if (options.secp256k1) {
templateContent = templateContent.replace(
Expand All @@ -338,6 +347,13 @@ function addHTMLEntry(options: HTMLPlugin.Options & { secp256k1?: boolean; sourc
`<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-eval'; require-trusted-types-for 'script'; trusted-types default webpack">`,
)
}
if (options.lockdown) {
templateContent = templateContent.replace(
`<!-- lockdown -->`,
`<script src="/polyfill/lockdown.js"></script>
<script src="/lockdown.js"></script>`,
)
}
return new HTMLPlugin({
templateContent,
inject: 'body',
Expand Down
89 changes: 89 additions & 0 deletions packages/mask/public/lockdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/// <reference types="ses" />

lockdown({
// In production, we have CSP enforced no eval
// In development, we use Trusted Types.
evalTaming: 'unsafeEval',
//
overrideTaming: 'severe',
consoleTaming: 'unsafe',
errorTaming: 'unsafe',
})
try {
// Frozen extra globals
;(() => {
delete globalThis.regeneratorRuntime
/**
* @param {string} name The global name to be protected
* @param {'accept' | 'ignore'} policy The global policy
* @param {boolean} freeze If the value should be frozen
* @param {boolean} warn If should log a warning when accessed
* @param {boolean} why If should trigger the debugger on set
*/
function global(name, policy = 'accept', freeze = true, warn = false, why = false) {
const old = Object.getOwnPropertyDescriptor(globalThis, name)
if (old) {
if (!old.configurable) return console.warn('globalThis.' + name + ' is not configurable.')
Reflect.deleteProperty(globalThis, name)
if (old.get) return console.warn('Cannot harden a global getter', name)

if (policy === 'accept') {
const { value } = old
if (freeze) harden(value)
if (warn) {
Object.defineProperty(globalThis, name, {
get() {
console.warn(`[Deprecation] Try to access globalThis.${name}`)
return value
},
})
} else {
old.configurable = false
old.writable = false
Object.defineProperty(globalThis, name, old)
}
}
return
}

let value
let hasBeenSet = false
Object.defineProperty(globalThis, name, {
get() {
if (warn) console.warn(`[Deprecation] Try to access globalThis.${name}`)
return value
},
set(val) {
if (why) debugger
if (policy === 'ignore') return

if (hasBeenSet) throw new TypeError(`globalThis.${name} is not writable.`)
hasBeenSet = true
value = val
if (freeze) harden(val)
return true
},
})
}

// accepted globals
global('Buffer') // by webpack
global('elliptic') // required by secp256k1 polyfill
global('regeneratorRuntime') // require by generator/async transpiled by babel
global('__EMOTION_REACT_11__', 'ignore') // by @emotion/react to avoid duplicate loading
global('_', 'ignore') // by lodash, as UMD

// to be investigated globals
global('Arweave', 'accept', false) // by arweave
global('FCL_REGISTRY', 'accept', false) // by @onflow/util-actor < @portto/sdk < @blocto/fcl
global('Web3', 'accept', false) // by web3
global('iFrameResize', 'accept', false) // by https://github.com/davidjbradshaw/iframe-resizer-react
global('proto', 'accept', false) // by @blocto/protobuf < @portto/sdk < @blocto/fcl
global('_ethers', 'accept', false) // by RSS3
})()
} catch (error) {
console.log('Lockdown failed', error)
}

// completion value
null
4 changes: 0 additions & 4 deletions packages/mask/src/extension/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ import { serializer, getLocalImplementation } from '@masknet/shared-base'
const SERVICE_HMR_EVENT = 'service-hmr'
const message = new WebExtensionMessage<Record<string, any>>({ domain: 'services' })
const log: AsyncCallOptions['log'] = {
beCalled: true,
localError: true,
remoteError: true,
sendLocalStack: true,
type: 'pretty',
requestReplay: process.env.NODE_ENV === 'development',
}
Expand Down
4 changes: 0 additions & 4 deletions packages/plugin-infra/src/utils/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import { Environment, isEnvironment, MessageTarget, UnboundedRegistry } from '@d
import { AsyncCall, AsyncCallLogLevel, AsyncGeneratorCall } from 'async-call-rpc/full'
import { serializer, getLocalImplementation, getLocalImplementationExotic } from '@masknet/shared-base'
const log: AsyncCallLogLevel = {
beCalled: true,
localError: true,
remoteError: true,
requestReplay: true,
sendLocalStack: true,
type: 'pretty',
}
export function createPluginRPC<T extends Record<string, (...args: any) => Promise<any>>>(
Expand Down
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 8969697

Please sign in to comment.