openvibers/openvibe.computer Commits
CSP: allow avatars from openvibe.media in img-src (#40)
Changes
@@@ -27,7 +27,7 @@ function createApp(opts = {}) {const app = express();app.disable('x-powered-by'); app.set('trust proxy', config.trustProxy);app.use(helmet({ contentSecurityPolicy: { directives: {-- defaultSrc: ["'self'"], scriptSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network', 'https://static.cloudflareinsights.com'], styleSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network', 'https://fonts.googleapis.com'], fontSrc: ["'self'", 'data:', 'https://fonts.gstatic.com'], imgSrc: ["'self'", 'data:', 'https://openvibe.network'], connectSrc: ["'self'", 'https://openvibe.network', 'https://openvibe.chat', 'https://billing.openvibe.network', 'https://openvibe.events', 'https://cloudflareinsights.com'], frameSrc: ["'self'", 'https://openvibe.network'], frameAncestors: ["'none'"], objectSrc: ["'none'"], baseUri: ["'self'"], formAction: ["'self'", 'https://openvibe.network'],++ defaultSrc: ["'self'"], scriptSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network', 'https://static.cloudflareinsights.com'], styleSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network', 'https://fonts.googleapis.com'], fontSrc: ["'self'", 'data:', 'https://fonts.gstatic.com'], imgSrc: ["'self'", 'data:', 'https://openvibe.network', 'https://openvibe.media'], connectSrc: ["'self'", 'https://openvibe.network', 'https://openvibe.chat', 'https://billing.openvibe.network', 'https://openvibe.events', 'https://cloudflareinsights.com'], frameSrc: ["'self'", 'https://openvibe.network'], frameAncestors: ["'none'"], objectSrc: ["'none'"], baseUri: ["'self'"], formAction: ["'self'", 'https://openvibe.network'],} }, crossOriginEmbedderPolicy: false, referrerPolicy: { policy: 'strict-origin-when-cross-origin' } }));app.use(express.urlencoded({ extended: false }));app.use('/auth', sso.router(express));@@@ -44,6 +44,12 @@ test('home renders signed out and signed in; sign-in and computer controls are v{ const r = await fetch(`${s.base}/release.json`); assert.equal(r.status, 200, 'the navbar release watch polls /release.json'); assert.equal((await r.json()).service, 'computer'); }});++test('the security policy lets an avatar from openvibe.media show in img-src', async (t) => {++ const s = await serve({ run: {} }); t.after(s.close);++ const csp = (await fetch(s.base)).headers.get('content-security-policy') || '';++ assert.match(csp, /img-src[^;]*https:\/\/openvibe\.media(?:[ ;]|$)/, csp);++});++test('facade forwards only the presented person token to Run', async (t) => {const received = [];const run = { list: async (token) => { received.push(token); return { sessions: [] }; }, create: async (token, body) => { received.push(token); return { id: 'ses_new', ...body }; } };
@@ -27,7 +27,7 @@ function createApp(opts = {}) {
@@ -27,7 +27,7 @@ function createApp(opts = {}) {
const app = express();
const app = express();
app.disable('x-powered-by'); app.set('trust proxy', config.trustProxy);
app.disable('x-powered-by'); app.set('trust proxy', config.trustProxy);
app.use(helmet({ contentSecurityPolicy: { directives: {
app.use(helmet({ contentSecurityPolicy: { directives: {
- defaultSrc: ["'self'"], scriptSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network', 'https://static.cloudflareinsights.com'], styleSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network', 'https://fonts.googleapis.com'], fontSrc: ["'self'", 'data:', 'https://fonts.gstatic.com'], imgSrc: ["'self'", 'data:', 'https://openvibe.network'], connectSrc: ["'self'", 'https://openvibe.network', 'https://openvibe.chat', 'https://billing.openvibe.network', 'https://openvibe.events', 'https://cloudflareinsights.com'], frameSrc: ["'self'", 'https://openvibe.network'], frameAncestors: ["'none'"], objectSrc: ["'none'"], baseUri: ["'self'"], formAction: ["'self'", 'https://openvibe.network'],
+ defaultSrc: ["'self'"], scriptSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network', 'https://static.cloudflareinsights.com'], styleSrc: ["'self'", "'unsafe-inline'", 'https://openvibe.network', 'https://fonts.googleapis.com'], fontSrc: ["'self'", 'data:', 'https://fonts.gstatic.com'], imgSrc: ["'self'", 'data:', 'https://openvibe.network', 'https://openvibe.media'], connectSrc: ["'self'", 'https://openvibe.network', 'https://openvibe.chat', 'https://billing.openvibe.network', 'https://openvibe.events', 'https://cloudflareinsights.com'], frameSrc: ["'self'", 'https://openvibe.network'], frameAncestors: ["'none'"], objectSrc: ["'none'"], baseUri: ["'self'"], formAction: ["'self'", 'https://openvibe.network'],
} }, crossOriginEmbedderPolicy: false, referrerPolicy: { policy: 'strict-origin-when-cross-origin' } }));
} }, crossOriginEmbedderPolicy: false, referrerPolicy: { policy: 'strict-origin-when-cross-origin' } }));
app.use(express.urlencoded({ extended: false }));
app.use(express.urlencoded({ extended: false }));
app.use('/auth', sso.router(express));
app.use('/auth', sso.router(express));
@@ -44,6 +44,12 @@ test('home renders signed out and signed in; sign-in and computer controls are v
@@ -44,6 +44,12 @@ test('home renders signed out and signed in; sign-in and computer controls are v
{ const r = await fetch(`${s.base}/release.json`); assert.equal(r.status, 200, 'the navbar release watch polls /release.json'); assert.equal((await r.json()).service, 'computer'); }
{ const r = await fetch(`${s.base}/release.json`); assert.equal(r.status, 200, 'the navbar release watch polls /release.json'); assert.equal((await r.json()).service, 'computer'); }
});
});
+test('the security policy lets an avatar from openvibe.media show in img-src', async (t) => {
+ const s = await serve({ run: {} }); t.after(s.close);
+ const csp = (await fetch(s.base)).headers.get('content-security-policy') || '';
+ assert.match(csp, /img-src[^;]*https:\/\/openvibe\.media(?:[ ;]|$)/, csp);
+});
+
test('facade forwards only the presented person token to Run', async (t) => {
test('facade forwards only the presented person token to Run', async (t) => {
const received = [];
const received = [];
const run = { list: async (token) => { received.push(token); return { sessions: [] }; }, create: async (token, body) => { received.push(token); return { id: 'ses_new', ...body }; } };
const run = { list: async (token) => { received.push(token); return { sessions: [] }; }, create: async (token, body) => { received.push(token); return { id: 'ses_new', ...body }; } };