mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-14 14:13:43 +01:00
Merge pull request #17596 from overleaf/rh-permissions-policy
[web] Add Permissions-Policy header GitOrigin-RevId: 8934bbbda411102580d9ef8af135dcdc147627f9
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
const { expect } = require('chai')
|
||||
const fetch = require('node-fetch')
|
||||
const Settings = require('@overleaf/settings')
|
||||
|
||||
const BASE_URL = `http://${process.env.HTTP_TEST_HOST || 'localhost'}:23000`
|
||||
|
||||
describe('HttpPermissionsPolicy', function () {
|
||||
it('should have permissions-policy header on user-facing pages', async function () {
|
||||
const response = await fetch(BASE_URL)
|
||||
|
||||
expect(response.headers.get('permissions-policy')).to.equal(
|
||||
'accelerometer=(), attribution-reporting=(), browsing-topics=(), camera=(), display-capture=(), encrypted-media=(), fullscreen=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), identity-credentials-get=(), idle-detection=(), local-fonts=(), magnetometer=(), microphone=(), midi=(), otp-credentials=(), payment=(), picture-in-picture=(), screen-wake-lock=(), serial=(), storage-access=(), usb=(), window-management=(), xr-spatial-tracking=(), autoplay=(self "https://videos.ctfassets.net")'
|
||||
)
|
||||
})
|
||||
|
||||
it('should not have permissions-policy header on requests for non-rendered content', async function () {
|
||||
const response = await fetch(`${BASE_URL}/dev/csrf`)
|
||||
|
||||
expect(response.headers.get('permissions-policy')).to.be.null
|
||||
})
|
||||
|
||||
describe('when permissions policy is disabled', function () {
|
||||
it('it adds no additional headers', async function () {
|
||||
Settings.useHttpPermissionsPolicy = false
|
||||
const response = await fetch(BASE_URL)
|
||||
expect(response.headers.get('permissions-policy')).to.be.null
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,108 @@
|
||||
const { expect } = require('chai')
|
||||
const sinon = require('sinon')
|
||||
const modulePath = '../../../../app/src/infrastructure/HttpPermissionsPolicy.js'
|
||||
const SandboxedModule = require('sandboxed-module')
|
||||
const HttpPermissionsPolicyMiddleware = require('../../../../app/src/infrastructure/HttpPermissionsPolicy')
|
||||
const MockRequest = require('../helpers/MockRequest')
|
||||
const MockResponse = require('../helpers/MockResponse')
|
||||
|
||||
describe('HttpPermissionsPolicy', function () {
|
||||
this.beforeEach(function () {
|
||||
this.next = sinon.stub()
|
||||
this.HttpPermissionsPolicy = SandboxedModule.require(modulePath, {})
|
||||
this.path = '/foo/bar'
|
||||
this.req = new MockRequest()
|
||||
return (this.res = new MockResponse())
|
||||
})
|
||||
|
||||
describe('when a single blocked policy element is provided', function () {
|
||||
it('returns a valid header string', function () {
|
||||
const policy = {
|
||||
blocked: ['accelerometer'],
|
||||
}
|
||||
const httpPermissionsMiddleware = new HttpPermissionsPolicyMiddleware(
|
||||
policy
|
||||
)
|
||||
return expect(httpPermissionsMiddleware.policy).to.equal(
|
||||
'accelerometer=()'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when a single allowed policy element is provided', function () {
|
||||
it('returns a valid header string', function () {
|
||||
const policy = {
|
||||
allowed: { camera: 'self' },
|
||||
}
|
||||
const httpPermissionsMiddleware = new HttpPermissionsPolicyMiddleware(
|
||||
policy
|
||||
)
|
||||
return expect(httpPermissionsMiddleware.policy).to.equal('camera=(self)')
|
||||
})
|
||||
})
|
||||
|
||||
describe('when a full policy is provided', function () {
|
||||
it('returns a valid header string', function () {
|
||||
const policy = {
|
||||
blocked: ['usb', 'hid'],
|
||||
allowed: { camera: 'self https://example.com', fullscreen: 'self' },
|
||||
}
|
||||
const httpPermissionsMiddleware = new HttpPermissionsPolicyMiddleware(
|
||||
policy
|
||||
)
|
||||
return expect(httpPermissionsMiddleware.policy).to.equal(
|
||||
'usb=(), hid=(), camera=(self https://example.com), fullscreen=(self)'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when a conflicting policy is provided', function () {
|
||||
it('returns an error', function () {
|
||||
const policy = {
|
||||
blocked: ['usb'],
|
||||
allowed: { usb: 'self' },
|
||||
}
|
||||
return expect(() => new HttpPermissionsPolicyMiddleware(policy)).to.throw(
|
||||
'Invalid Permissions-Policy header configuration'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the allowlist contains an incomplete directive', function () {
|
||||
it('returns an error', function () {
|
||||
const policy = {
|
||||
blocked: ['usb'],
|
||||
allowed: { camera: '' },
|
||||
}
|
||||
return expect(() => new HttpPermissionsPolicyMiddleware(policy)).to.throw(
|
||||
'Invalid Permissions-Policy header configuration'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when an empty denylist is provided', function () {
|
||||
it('returns a valid header string ', function () {
|
||||
const policy = {
|
||||
allowed: { camera: 'self' },
|
||||
blocked: [],
|
||||
}
|
||||
const httpPermissionsMiddleware = new HttpPermissionsPolicyMiddleware(
|
||||
policy
|
||||
)
|
||||
return expect(httpPermissionsMiddleware.policy).to.equal('camera=(self)')
|
||||
})
|
||||
})
|
||||
|
||||
describe('when an empty allowlist is provided', function () {
|
||||
it('returns a valid header string ', function () {
|
||||
const policy = {
|
||||
allowed: {},
|
||||
blocked: ['usb'],
|
||||
}
|
||||
const httpPermissionsMiddleware = new HttpPermissionsPolicyMiddleware(
|
||||
policy
|
||||
)
|
||||
return expect(httpPermissionsMiddleware.policy).to.equal('usb=()')
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user