Skip to content

Commit

Permalink
Merge pull request #1583 from oasisprotocol/lw/strict-permissions-policy
Browse files Browse the repository at this point in the history
Add strict Permissions-Policy header
  • Loading branch information
lukaw3d authored Aug 10, 2023
2 parents 8d13573 + 84b30f3 commit 51de3ca
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ docker-compose up -d
REACT_APP_LOCALNET=1 REACT_APP_BACKEND=oasismonitor yarn start
yarn cypress:run

# Manually check that content-security-policy in ./internals/getCsp.js doesn't
# Manually check that content-security-policy in getPermissionHeaders.js doesn't
# break any functionality
yarn --silent print-csp
yarn start:prod
Expand Down
10 changes: 4 additions & 6 deletions docs/release-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,12 @@ Manually deploy `./build/` folder by following <https://github.com/oasisprotocol

Verify deployed version by opening the page in incognito (no cache) - it is displayed in the footer.

Update Content-Security-Policy header.
Update Content-Security-Policy and Permissions-Policy headers.

```sh
yarn print-csp

# See old deployed CSP
curl --head https://wallet.stg.oasis.io/ -s | grep content-security-policy
curl --head https://wallet.oasis.io/ -s | grep content-security-policy
# See old deployed headers
curl --head https://wallet.stg.oasis.io/ -s | grep "content-security-policy\|permissions-policy"
curl --head https://wallet.oasis.io/ -s | grep "content-security-policy\|permissions-policy"
```


Expand Down
40 changes: 39 additions & 1 deletion internals/getCsp.js → internals/getPermissionHeaders.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,42 @@ const getCsp = ({ isExtension } = { isExtension: false }) =>
.join(' ')
.replace(/ ;/g, ';')

module.exports = { getCsp }
// Generated with https://www.permissionspolicy.com/
const getPermissionsPolicy = () =>
`
accelerometer=*,
ambient-light-sensor=*,
autoplay=(),
bluetooth=(self),
camera=*,
cross-origin-isolated=(),
display-capture=(),
document-domain=(),
encrypted-media=*,
execution-while-not-rendered=(),
execution-while-out-of-viewport=(),
fullscreen=(self "https://global.transak.com" "https://global-stg.transak.com"),
geolocation=(),
gyroscope=*,
keyboard-map=(),
magnetometer=*,
microphone=*,
midi=(),
navigation-override=(),
payment=("https://global.transak.com" "https://global-stg.transak.com"),
picture-in-picture=(),
publickey-credentials-get=*,
screen-wake-lock=(),
sync-xhr=(),
usb=(self),
web-share=*,
xr-spatial-tracking=()
`
.trim()
.split('\n')
.map(line => line.trim())
.filter(line => !!line)
.join(' ')
.replace(/ ,/g, ',')

module.exports = { getCsp, getPermissionsPolicy }
2 changes: 1 addition & 1 deletion internals/scripts/build-ext.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @ts-check
const execSync = require('child_process').execSync
const { getCsp } = require('../getCsp.js')
const { getCsp } = require('../getPermissionHeaders.js')
const { buildDatetime, buildSha, buildVersion } = require('../getBuildData')

process.env.REACT_APP_BUILD_DATETIME = buildDatetime
Expand Down
2 changes: 1 addition & 1 deletion internals/scripts/build-web.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @ts-check
const execSync = require('child_process').execSync
const { getCsp } = require('../getCsp.js')
const { getCsp } = require('../getPermissionHeaders.js')
const { buildDatetime, buildSha, buildVersion } = require('../getBuildData')

process.env.REACT_APP_BUILD_DATETIME = buildDatetime
Expand Down
2 changes: 1 addition & 1 deletion internals/scripts/print-csp.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// @ts-check
const { getCsp } = require('../getCsp.js')
const { getCsp } = require('../getPermissionHeaders.js')
console.log(getCsp())
2 changes: 1 addition & 1 deletion internals/scripts/print-extension-csp.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// @ts-check
const { getCsp } = require('../getCsp.js')
const { getCsp } = require('../getPermissionHeaders.js')
console.log(getCsp({ isExtension: true }))
8 changes: 7 additions & 1 deletion internals/scripts/serve-prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
const path = require('path')
const http = require('http')
const serveHandler = require('serve-handler')
const { getCsp } = require('../getCsp.js')
const { getCsp, getPermissionsPolicy } = require('../getPermissionHeaders.js')
const csp = getCsp()
const permissionsPolicy = getPermissionsPolicy()
console.log(`Content-Security-Policy: ${csp}\n`)
console.log(`Permissions-Policy: ${permissionsPolicy}\n`)

const root = path.resolve(__dirname, '../..')

Expand All @@ -27,6 +29,10 @@ const server = http.createServer((request, response) => {
key: 'Content-Security-Policy',
value: csp,
},
{
key: 'Permissions-Policy',
value: permissionsPolicy,
},
],
},
],
Expand Down
29 changes: 28 additions & 1 deletion playwright/tests/fiat.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ test.beforeEach(async ({ page }) => {
})
await expect(page.getByTestId('account-selector')).toBeVisible()
await page.getByRole('link', { name: 'Buy' }).click()
await expect(page.getByText('Buy ROSE')).toBeVisible()
await expect(page.getByRole('heading', { name: 'Buy ROSE' })).toBeVisible()
})

test.describe('Fiat on-ramp', () => {
Expand Down Expand Up @@ -94,4 +94,31 @@ test.describe('Fiat on-ramp', () => {
.click()
await expect(page).toHaveURL('https://phishing-wallet.com/')
})

test('Permissions-Policy should contain Transak permissions', async ({ page, baseURL }) => {
expect(baseURL).toBe('http://localhost:5000')
expect((await page.request.head('/')).headers()).toHaveProperty('permissions-policy')
const permissionsPolicy = (await page.request.head('/'))
.headers()
['permissions-policy'].split(',')
.map(rule => rule.trim())

await page
.getByText(
'I understand that I’m using a third-party solution and Oasis* does not carry any responsibility over the usage of this solution.',
)
.click()

const transakPermissions = await page.locator('iframe').getAttribute('allow')
expect(transakPermissions).toBeTruthy()

for (const permission of transakPermissions!.split(';').map(permission => permission.trim())) {
expect(permissionsPolicy.find(rule => rule.startsWith(`${permission}=`))).toContain(
'https://global.transak.com',
)
expect(permissionsPolicy.find(rule => rule.startsWith(`${permission}=`))).toContain(
'https://global-stg.transak.com',
)
}
})
})
14 changes: 14 additions & 0 deletions playwright/tests/ledger.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { test, expect } from '@playwright/test'
import { expectNoErrorsInConsole } from '../utils/expectNoErrorsInConsole'

test.describe('Ledger', () => {
test('Permissions-Policy should allow USB', async ({ page, baseURL }) => {
expect(baseURL).toBe('http://localhost:5000')
expect((await page.request.head('/')).headers()).toHaveProperty('permissions-policy')
await expectNoErrorsInConsole(page)

await page.goto('/open-wallet/ledger')
await page.getByRole('button', { name: 'Select accounts to open' }).click()
await expect(page.getByText('error').or(page.getByText('fail'))).toBeHidden()
})
})
3 changes: 3 additions & 0 deletions src/app/pages/FiatOnrampPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ export function FiatOnramp() {
<iframe
height="875"
title="Transak On/Off Ramp Widget"
// From https://github.com/Transak/transak-sdk/blob/2ebb3bd/src/index.js#L52
// TODO: It also loads https://api.sardine.ai inside, and that tries
// to listen for devicemotion and deviceorientation. Is this necessary?
allow="camera;microphone;fullscreen;payment"
// Restrict top-navigation
sandbox={[
Expand Down

0 comments on commit 51de3ca

Please sign in to comment.