diff --git a/package-lock.json b/package-lock.json index 0568e05c..569e5466 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13032,6 +13032,29 @@ "node": ">=14.17" } }, + "node_modules/ua-parser-js": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.38.tgz", + "integrity": "sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/uglify-js": { "version": "3.17.4", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", @@ -14074,6 +14097,7 @@ "string-length": "^6.0.0", "svgo": "^3.0.2", "tiktoken": "^1.0.11", + "ua-parser-js": "^1.0.38", "uglify-js": "^3.17.4", "uuid": "^9.0.0", "validator": "^13.9.0", diff --git a/src/backend/package.json b/src/backend/package.json index daa5753a..f3d0d950 100644 --- a/src/backend/package.json +++ b/src/backend/package.json @@ -66,6 +66,7 @@ "string-length": "^6.0.0", "svgo": "^3.0.2", "tiktoken": "^1.0.11", + "ua-parser-js": "^1.0.38", "uglify-js": "^3.17.4", "uuid": "^9.0.0", "validator": "^13.9.0", diff --git a/src/backend/src/services/PuterHomepageService.js b/src/backend/src/services/PuterHomepageService.js index 57208f80..b6236620 100644 --- a/src/backend/src/services/PuterHomepageService.js +++ b/src/backend/src/services/PuterHomepageService.js @@ -109,6 +109,7 @@ class PuterHomepageService extends BaseService { short_description: config.short_description, long_description: config.long_description, disable_temp_users: config.disable_temp_users, + co_isolation_enabled: req.co_isolation_enabled, }, })); } diff --git a/src/backend/src/services/WebServerService.js b/src/backend/src/services/WebServerService.js index 57fe8b82..3aeb068a 100644 --- a/src/backend/src/services/WebServerService.js +++ b/src/backend/src/services/WebServerService.js @@ -357,11 +357,29 @@ class WebServerService extends BaseService { app.use(helmet.xssFilter()); // app.use(helmet.referrerPolicy()); app.disable('x-powered-by'); + + const uaParser = require('ua-parser-js'); + app.use(function (req, res, next) { + const ua_header = req.headers['user-agent']; + const ua = uaParser(ua_header); + req.ua = ua; + console.log('\x1B[26;1m===== UA =====\x1B[0m', ua); + next(); + }); + + app.use(function (req, res, next) { + req.co_isolation_enabled = + ['Chrome', 'Edge'].includes(req.ua.browser.name) + && (Number(req.ua.browser.major) >= 110); + next(); + }); app.use(function (req, res, next) { const origin = req.headers.origin; const is_site = req.hostname.endsWith(config.static_hosting_domain); + + const co_isolation_okay = is_site || req.co_isolation_enabled; if ( req.path === '/signup' || req.path === '/login' ) { res.setHeader('Access-Control-Allow-Origin', origin ?? '*'); @@ -392,7 +410,7 @@ class WebServerService extends BaseService { // NOTE: This is put behind a configuration flag because we // need some experimentation to ensure the interface // between apps and Puter doesn't break. - if ( config.cross_origin_isolation && is_site ) { + if ( config.cross_origin_isolation && co_isolation_okay ) { res.setHeader('Cross-Origin-Opener-Policy', 'same-origin'); res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp'); } diff --git a/src/gui/src/UI/UIWindow.js b/src/gui/src/UI/UIWindow.js index 223a6d6a..1af86ef7 100644 --- a/src/gui/src/UI/UIWindow.js +++ b/src/gui/src/UI/UIWindow.js @@ -323,6 +323,10 @@ async function UIWindow(options) { frameborder="0" ${options.iframe_url ? 'src="'+ html_encode(options.iframe_url)+'"' : ''} ${options.iframe_srcdoc ? 'srcdoc="'+ html_encode(options.iframe_srcdoc) +'"' : ''} + ${window.co_isolation_enabled + ? 'credentialless allow="cross-origin-isolated" ' + : '' + } allow = "accelerometer; camera; encrypted-media; gamepad; display-capture; geolocation; gyroscope; microphone; midi; clipboard-read; clipboard-write; fullscreen;" allowtransparency="true" allowpaymentrequest="true" diff --git a/src/gui/src/index.js b/src/gui/src/index.js index 08fe713f..59ea7983 100644 --- a/src/gui/src/index.js +++ b/src/gui/src/index.js @@ -56,6 +56,7 @@ window.gui = async function(options){ window.max_item_name_length = options.max_item_name_length ?? 500; window.require_email_verification_to_publish_website = options.require_email_verification_to_publish_website ?? true; window.disable_temp_users = options.disable_temp_users ?? false; + window.co_isolation_enabled = options.co_isolation_enabled; // DEV: Load the initgui.js file if we are in development mode if(!window.gui_env || window.gui_env === "dev"){