Skip to content

Commit

Permalink
feat: enable csp report-only mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Jack-Works committed May 6, 2022
1 parent f4d4a3e commit ceb7b16
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 7 deletions.
68 changes: 68 additions & 0 deletions packages/mask/.webpack/ContentSecurityPolicyBuilder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/Sources#sources
enum Source {
Self = "'self'",
// ! Not standard CSP directive, only available in WebExtension Manifest v2
UnsafeWASM = "'wasm-eval'",
UnsafeEval = "'unsafe-eval'",
ReportSample = "'report-sample'",
None = "'none'",
ANY_HTTPS = 'https:',
ANY_DATA_URI = 'data:',
ANY_BLOB_URI = 'blob:',
ANY_MEDIA_STREAM_URI = 'mediastream:',
}
const REPORT_URI = 'https://csp-report-collector.mask-reverse-proxy.workers.dev/report?to='

const RawProdCSP = {
'script-src': [Source.Self, Source.UnsafeWASM],
'object-src': [Source.Self],
}
const RawProdCSP_ReportOnly = null
const RawDevCSP = {
'script-src': [Source.Self, Source.UnsafeEval],
'require-trusted-types-for': "'script'",
'trusted-types': ['default', 'webpack'],
}
const RawDevCSP_ReportOnly = {
...RawDevCSP,
// iframe
// 'frame-src': Source.None,
// 'worker-src': Source.None,
// 'connect-src': Source.None,
// 'default-src': Source.None,
// 'font-src': Source.None,
// 'img-src': Source.None,
// 'manifest-src': Source.None,
// 'media-src': Source.None,
// 'object-src': Source.None,
// 'prefetch-src': Source.None,
// 'script-src': [Source.Self, Source.UnsafeEval],
// 'style-src': Source.None,
// 'base-uri': Source.None,
// // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/sandbox
// sandbox: 'allow-scripts',
// 'form-action': Source.None,
// 'frame-ancestors': Source.None,
// 'navigate-to': Source.None,
'report-uri': '',
// 'require-trusted-types-for': "'script'",
// 'trusted-types': ['default', 'webpack'],
}
export function buildCSP() {
const version = require('../src/manifest.json').version
const prodCSP = buildSingleCSP(RawProdCSP, REPORT_URI + version)
const prodCSP_ReportOnly = buildSingleCSP(RawProdCSP_ReportOnly, REPORT_URI + version + '-report')
const devCSP = buildSingleCSP(RawDevCSP, REPORT_URI + version + '-dev')
const devCSP_ReportOnly = buildSingleCSP(RawDevCSP_ReportOnly, REPORT_URI + version + '-dev-report')

return {
development: { csp: devCSP, csp_report_only: devCSP_ReportOnly },
production: { csp: prodCSP, csp_report_only: prodCSP_ReportOnly },
}
}
function buildSingleCSP(csp: null | Record<string, string | string[]>, reportURI: string) {
if (!csp) return null
if ('report-uri' in csp) csp['report-uri'] = reportURI
const entries = Object.entries(csp)
return entries.map(([key, value]) => `${key} ${Array.isArray(value) ? value.join(' ') : value}`).join('; ')
}
17 changes: 14 additions & 3 deletions packages/mask/.webpack/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { BuildFlags, normalizeBuildFlags, computedBuildFlags } from './flags'
import ResolveTypeScriptPlugin from 'resolve-typescript-plugin'

import './clean-hmr'
import { buildCSP } from './ContentSecurityPolicyBuilder'

export function createConfiguration(rawFlags: BuildFlags): Configuration {
const normalizedFlags = normalizeBuildFlags(rawFlags)
Expand Down Expand Up @@ -264,15 +265,16 @@ 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, lockdown }),
addHTMLEntry({ chunks: ['popups'], filename: 'popups.html', sourceMap: !!sourceMapKind, lockdown }),
addHTMLEntry({ chunks: ['dashboard'], filename: 'dashboard.html', sourceMap: !!sourceMapKind, lockdown, mode }),
addHTMLEntry({ chunks: ['popups'], filename: 'popups.html', sourceMap: !!sourceMapKind, lockdown, mode }),
addHTMLEntry({
chunks: ['contentScript'],
filename: 'generated__content__script.html',
sourceMap: !!sourceMapKind,
lockdown,
mode,
}),
addHTMLEntry({ chunks: ['debug'], filename: 'debug.html', sourceMap: !!sourceMapKind, lockdown }),
addHTMLEntry({ chunks: ['debug'], filename: 'debug.html', sourceMap: !!sourceMapKind, lockdown, mode }),
)
// background
if (runtime.manifest === 3) {
Expand All @@ -291,6 +293,7 @@ export function createConfiguration(rawFlags: BuildFlags): Configuration {
gun: true,
sourceMap: !!sourceMapKind,
lockdown,
mode,
}),
)
}
Expand All @@ -317,6 +320,7 @@ export function createConfiguration(rawFlags: BuildFlags): Configuration {
function addHTMLEntry(
options: HTMLPlugin.Options & {
sourceMap: boolean
mode: 'production' | 'development'
gun?: boolean
lockdown: boolean
},
Expand All @@ -338,6 +342,13 @@ function addHTMLEntry(
<script src="/lockdown.js"></script>`,
)
}

const { csp, csp_report_only } = buildCSP()[options.mode]
templateContent = templateContent.replace(
`<!-- CSP -->`,
`<meta http-equiv="Content-Security-Policy" content="${csp}">
<meta http-equiv="Content-Security-Policy-Report-Only" content="${csp_report_only}">`,
)
return new HTMLPlugin({
templateContent,
inject: 'body',
Expand Down
10 changes: 8 additions & 2 deletions packages/mask/.webpack/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import emitFile from '@nice-labs/emit-file-webpack-plugin'
import { cloneDeep } from 'lodash-unified'
import { NormalizedFlags } from './flags'
import { buildCSP } from './ContentSecurityPolicyBuilder'

type Manifest = typeof import('../src/manifest.json') & Record<string, any>
export function emitManifestFile(flags: NormalizedFlags) {
Expand All @@ -15,6 +16,8 @@ export function emitManifestFile(flags: NormalizedFlags) {
})
}
function modify(manifest: Manifest, flags: NormalizedFlags) {
const CSP = buildCSP()

if (flags.runtime.engine === 'firefox') {
// TODO: To make `browser.tabs.executeScript` run on Firefox, we need an extra permission "tabs".
// Switch to browser.userScripts (Firefox only) API can resolve the problem.
Expand All @@ -35,10 +38,13 @@ function modify(manifest: Manifest, flags: NormalizedFlags) {
}
if (flags.mode === 'development') {
manifest.name += ' (dev)'
// for eval-source-map
manifest.content_security_policy = `script-src 'self' 'unsafe-eval'; object-src 'self';`
// No csp_report_only support in manifest.json ,see https://github.com/w3c/webextensions/issues/197
manifest.content_security_policy = CSP.development.csp

acceptExternalConnect(manifest)
stableDevelopmentExtensionID(manifest)
} else {
manifest.content_security_policy = CSP.production.csp
}

if (flags.hmr) {
Expand Down
3 changes: 1 addition & 2 deletions packages/mask/src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,5 @@
"browser_action": { "default_popup": "popups.html" },
"homepage_url": "https://mask.io",
"description": "The portal to the new & open Internet. Send encrypted message and decentralized Apps right on top of social networks.",
"web_accessible_resources": ["js/*", "*.png", "*.css"],
"content_security_policy": "script-src 'self' 'wasm-eval'; object-src 'self';"
"web_accessible_resources": ["js/*", "*.png", "*.css"]
}

0 comments on commit ceb7b16

Please sign in to comment.