diff --git a/.meteor/packages b/.meteor/packages index f6f893dc56355..4c4e0246bc6b0 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -89,3 +89,4 @@ rocketchat:i18n rocketchat:postcss dandv:caret-position facts-base@1.0.1 +browser-policy diff --git a/.meteor/versions b/.meteor/versions index 069655e8be53c..2c7259e87ee0f 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -17,6 +17,10 @@ blaze@2.3.4 blaze-html-templates@1.1.2 blaze-tools@1.0.10 boilerplate-generator@1.7.1 +browser-policy@1.1.0 +browser-policy-common@1.0.11 +browser-policy-content@1.1.1 +browser-policy-framing@1.1.0 caching-compiler@1.2.2 caching-html-compiler@1.1.3 callback-hook@1.3.0 diff --git a/app/lib/server/startup/settings.js b/app/lib/server/startup/settings.js index 7b20b3ed77984..a83b03514d9fe 100644 --- a/app/lib/server/startup/settings.js +++ b/app/lib/server/startup/settings.js @@ -850,6 +850,11 @@ settings.addGroup('General', function() { type: 'boolean', secret: true, }); + + this.add('Enable_CSP', true, { + type: 'boolean', + }); + this.add('Iframe_Restrict_Access', true, { type: 'boolean', secret: true, diff --git a/app/theme/server/server.js b/app/theme/server/server.js index 1b3ee5ed74354..b1a55d40ac20b 100644 --- a/app/theme/server/server.js +++ b/app/theme/server/server.js @@ -8,8 +8,7 @@ import { Meteor } from 'meteor/meteor'; import { settings } from '../../settings'; import { Logger } from '../../logger'; -import { getURL } from '../../utils/lib/getURL'; -import { injectIntoHead } from '../../ui-master/server'; +import { addStyle } from '../../ui-master/server/inject'; const logger = new Logger('rocketchat:theme', { methods: { @@ -140,7 +139,7 @@ Meteor.startup(() => { settings.get('css', (key, value = '') => { currentHash = crypto.createHash('sha1').update(value).digest('hex'); currentSize = value.length; - injectIntoHead('css-theme', ``); + addStyle('css-theme', value); }); }); diff --git a/app/ui-master/client/main.js b/app/ui-master/client/main.js index c4401c688619a..fd855764af5f0 100644 --- a/app/ui-master/client/main.js +++ b/app/ui-master/client/main.js @@ -12,21 +12,12 @@ import { CachedCollectionManager } from '../../ui-cached-collection'; import { tooltip } from '../../ui/client/components/tooltip'; import { callbacks } from '../../callbacks/client'; import { isSyncReady } from '../../../client/lib/userData'; +import { fireGlobalEvent } from '../../ui-utils/client'; import './main.html'; -function executeCustomScript(script) { - eval(script);//eslint-disable-line -} -function customScriptsOnLogout() { - const script = settings.get('Custom_Script_On_Logout') || ''; - if (script.trim()) { - executeCustomScript(script); - } -} - -callbacks.add('afterLogoutCleanUp', () => customScriptsOnLogout(), callbacks.priority.LOW, 'custom-script-on-logout'); +callbacks.add('afterLogoutCleanUp', () => fireGlobalEvent('Custom_Script_On_Logout'), callbacks.priority.LOW, 'custom-script-on-logout'); Template.main.helpers({ removeSidenav: () => Layout.isEmbedded() && !/^\/admin/.test(FlowRouter.current().route.path), @@ -81,16 +72,10 @@ Template.main.helpers({ return mandatoryRole !== undefined && is2faEnabled; }, CustomScriptLoggedOut: () => { - const script = settings.get('Custom_Script_Logged_Out') || ''; - if (script.trim()) { - executeCustomScript(script); - } + fireGlobalEvent('Custom_Script_Logged_Out'); }, CustomScriptLoggedIn: () => { - const script = settings.get('Custom_Script_Logged_In') || ''; - if (script.trim()) { - executeCustomScript(script); - } + fireGlobalEvent('Custom_Script_Logged_In'); }, embeddedVersion: () => { if (Layout.isEmbedded()) { diff --git a/app/ui-master/server/index.js b/app/ui-master/server/index.js index d41ede02b28ee..655f466204024 100644 --- a/app/ui-master/server/index.js +++ b/app/ui-master/server/index.js @@ -1 +1,167 @@ +import { Meteor } from 'meteor/meteor'; +import { BrowserPolicy } from 'meteor/browser-policy'; +import { Inject } from 'meteor/meteorhacks:inject-initial'; +import { Tracker } from 'meteor/tracker'; +import _ from 'underscore'; +import { escapeHTML } from '@rocket.chat/string-helpers'; + +import { Settings } from '../../models'; +import { settings } from '../../settings/server'; +import { applyHeadInjections, headInjections, injectIntoBody, injectIntoHead } from './inject'; +import './scripts'; + export * from './inject'; + +Meteor.startup(() => { + settings.get('Enable_CSP', (_, enabled) => { + if (!enabled) { + return BrowserPolicy.content.setPolicy("default-src 'self'; " + + "script-src 'self' 'unsafe-inline' 'unsafe-eval'; " + + 'connect-src * data:; ' + + 'img-src * data: ; ' + + "style-src 'self' 'unsafe-inline';"); + } + BrowserPolicy.content.allowImageOrigin('*'); + BrowserPolicy.content.disallowInlineScripts(); + BrowserPolicy.content.allowFontDataUrl(); + BrowserPolicy.content.allowConnectDataUrl(); + BrowserPolicy.content.allowInlineStyles(); + }); + Tracker.autorun(() => { + const injections = Object.values(headInjections.all()); + Inject.rawModHtml('headInjections', applyHeadInjections(injections)); + }); + + settings.get('Default_Referrer_Policy', (key, value) => { + if (!value) { + return injectIntoHead('noreferrer', ''); + } + + injectIntoHead('noreferrer', ``); + }); + + if (process.env.DISABLE_ANIMATION) { + injectIntoHead('disable-animation', ` + + `); + } + + settings.get('Assets_SvgFavicon_Enable', (key, value) => { + const standardFavicons = ` + + `; + + if (value) { + injectIntoHead(key, + `${ standardFavicons } + `); + } else { + injectIntoHead(key, standardFavicons); + } + }); + + settings.get('theme-color-sidebar-background', (key, value) => { + const escapedValue = escapeHTML(value); + injectIntoHead(key, `` + + ``); + }); + + settings.get('Site_Name', (key, value = 'Rocket.Chat') => { + const escapedValue = escapeHTML(value); + injectIntoHead(key, + `${ escapedValue }` + + `` + + ``); + }); + + settings.get('Meta_language', (key, value = '') => { + const escapedValue = escapeHTML(value); + injectIntoHead(key, + `` + + ``); + }); + + settings.get('Meta_robots', (key, value = '') => { + const escapedValue = escapeHTML(value); + injectIntoHead(key, ``); + }); + + settings.get('Meta_msvalidate01', (key, value = '') => { + const escapedValue = escapeHTML(value); + injectIntoHead(key, ``); + }); + + settings.get('Meta_google-site-verification', (key, value = '') => { + const escapedValue = escapeHTML(value); + injectIntoHead(key, ``); + }); + + settings.get('Meta_fb_app_id', (key, value = '') => { + const escapedValue = escapeHTML(value); + injectIntoHead(key, ``); + }); + + settings.get('Meta_custom', (key, value = '') => { + injectIntoHead(key, value); + }); + + const baseUrl = ((prefix) => { + if (!prefix) { + return '/'; + } + + prefix = prefix.trim(); + + if (!prefix) { + return '/'; + } + + return /\/$/.test(prefix) ? prefix : `${ prefix }/`; + })(__meteor_runtime_config__.ROOT_URL_PATH_PREFIX); + + injectIntoHead('base', ``); + + injectIntoHead('css-theme', ''); +}); + +const renderDynamicCssList = _.debounce(Meteor.bindEnvironment(() => { + // const variables = RocketChat.models.Settings.findOne({_id:'theme-custom-variables'}, {fields: { value: 1}}); + const colors = Settings.find({ _id: /theme-color-rc/i }, { fields: { value: 1, editor: 1 } }).fetch().filter((color) => color && color.value); + + if (!colors) { + return; + } + const css = colors.map(({ _id, value, editor }) => { + if (editor === 'expression') { + return `--${ _id.replace('theme-color-', '') }: var(--${ value });`; + } + return `--${ _id.replace('theme-color-', '') }: ${ value };`; + }).join('\n'); + injectIntoBody('dynamic-variables', ``); +}), 500); + +renderDynamicCssList(); + +// RocketChat.models.Settings.find({_id:'theme-custom-variables'}, {fields: { value: 1}}).observe({ +// changed: renderDynamicCssList +// }); + +settings.get(/theme-color-rc/i, () => renderDynamicCssList()); + +injectIntoBody('react-root', ` +
+
+
+
+
+
+
+
+
+`); + +injectIntoBody('icons', Assets.getText('public/icons.svg')); diff --git a/app/ui-master/server/inject.js b/app/ui-master/server/inject.js deleted file mode 100644 index 17e5d9f1f08ad..0000000000000 --- a/app/ui-master/server/inject.js +++ /dev/null @@ -1,202 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import { Inject } from 'meteor/meteorhacks:inject-initial'; -import { ReactiveDict } from 'meteor/reactive-dict'; -import { Tracker } from 'meteor/tracker'; -import _ from 'underscore'; -import { escapeHTML } from '@rocket.chat/string-helpers'; - -import { Settings } from '../../models'; -import { settings } from '../../settings/server'; - -const headInjections = new ReactiveDict(); - -export const injectIntoHead = (key, value) => { - headInjections.set(key, value); -}; - -export const injectIntoBody = (key, value) => { - Inject.rawBody(key, value); -}; - -const applyHeadInjections = (injections) => { - if (injections.length === 0) { - return (html) => html; - } - - const replacementHtml = `${ injections.join('\n').replace(/\$/g, '$$$$') }\n`; - - return (html) => html.replace('', replacementHtml); -}; - -Meteor.startup(() => { - Tracker.autorun(() => { - const injections = Object.values(headInjections.all()); - Inject.rawModHtml('headInjections', applyHeadInjections(injections)); - }); - - settings.get('Default_Referrer_Policy', (key, value) => { - if (!value) { - return injectIntoHead('noreferrer', ''); - } - - injectIntoHead('noreferrer', ``); - }); - - if (process.env.DISABLE_ANIMATION) { - injectIntoHead('disable-animation', ` - - - `); - } - - settings.get('API_Use_REST_For_DDP_Calls', (key, value) => { - if (!value) { - return injectIntoHead(key, ''); - } - injectIntoHead(key, ''); - }); - - settings.get('Assets_SvgFavicon_Enable', (key, value) => { - const standardFavicons = ` - - `; - - if (value) { - injectIntoHead(key, - `${ standardFavicons } - `); - } else { - injectIntoHead(key, standardFavicons); - } - }); - - settings.get('theme-color-sidebar-background', (key, value) => { - const escapedValue = escapeHTML(value); - injectIntoHead(key, `` - + ``); - }); - - settings.get('Site_Name', (key, value = 'Rocket.Chat') => { - const escapedValue = escapeHTML(value); - injectIntoHead(key, - `${ escapedValue }` - + `` - + ``); - }); - - settings.get('Meta_language', (key, value = '') => { - const escapedValue = escapeHTML(value); - injectIntoHead(key, - `` - + ``); - }); - - settings.get('Meta_robots', (key, value = '') => { - const escapedValue = escapeHTML(value); - injectIntoHead(key, ``); - }); - - settings.get('Meta_msvalidate01', (key, value = '') => { - const escapedValue = escapeHTML(value); - injectIntoHead(key, ``); - }); - - settings.get('Meta_google-site-verification', (key, value = '') => { - const escapedValue = escapeHTML(value); - injectIntoHead(key, ``); - }); - - settings.get('Meta_fb_app_id', (key, value = '') => { - const escapedValue = escapeHTML(value); - injectIntoHead(key, ``); - }); - - settings.get('Meta_custom', (key, value = '') => { - injectIntoHead(key, value); - }); - - const baseUrl = ((prefix) => { - if (!prefix) { - return '/'; - } - - prefix = prefix.trim(); - - if (!prefix) { - return '/'; - } - - return /\/$/.test(prefix) ? prefix : `${ prefix }/`; - })(__meteor_runtime_config__.ROOT_URL_PATH_PREFIX); - - injectIntoHead('base', ``); - - injectIntoHead('css-theme', ''); -}); - -const renderDynamicCssList = _.debounce(Meteor.bindEnvironment(() => { - // const variables = RocketChat.models.Settings.findOne({_id:'theme-custom-variables'}, {fields: { value: 1}}); - const colors = Settings.find({ _id: /theme-color-rc/i }, { fields: { value: 1, editor: 1 } }).fetch().filter((color) => color && color.value); - - if (!colors) { - return; - } - const css = colors.map(({ _id, value, editor }) => { - if (editor === 'expression') { - return `--${ _id.replace('theme-color-', '') }: var(--${ value });`; - } - return `--${ _id.replace('theme-color-', '') }: ${ value };`; - }).join('\n'); - injectIntoBody('dynamic-variables', ``); -}), 500); - -renderDynamicCssList(); - -// RocketChat.models.Settings.find({_id:'theme-custom-variables'}, {fields: { value: 1}}).observe({ -// changed: renderDynamicCssList -// }); - -settings.get(/theme-color-rc/i, () => renderDynamicCssList()); - -injectIntoBody('react-root', ` -
-
-
-
-
-
-
-
-
-`); - -injectIntoBody('icons', Assets.getText('public/icons.svg')); - -settings.get('Accounts_ForgetUserSessionOnWindowClose', (key, value) => { - if (value) { - Inject.rawModHtml(key, (html) => { - const script = ` - - `; - return html + script; - }); - } else { - Inject.rawModHtml(key, (html) => html); - } -}); diff --git a/app/ui-master/server/inject.ts b/app/ui-master/server/inject.ts new file mode 100644 index 0000000000000..2348b36d42aff --- /dev/null +++ b/app/ui-master/server/inject.ts @@ -0,0 +1,109 @@ +import crypto from 'crypto'; + +import parseRequest from 'parseurl'; +import { NextHandleFunction } from 'connect'; +import { WebApp } from 'meteor/webapp'; +import { ReactiveDict } from 'meteor/reactive-dict'; +import { Inject } from 'meteor/meteorhacks:inject-initial'; + +import { getURL } from '../../utils/server'; + +type Injection = string | { + content: string; + type: 'JS' | 'CSS'; + tag: string; +} + +export const headInjections = new ReactiveDict(); + +const callback: NextHandleFunction = (req, res, next) => { + if (req.method !== 'GET' && req.method !== 'HEAD' && req.method !== 'OPTIONS') { + next(); + return; + } + try { + const rawPath = parseRequest(req); + const pathname = rawPath !== undefined && rawPath.pathname && decodeURIComponent(rawPath.pathname); + + if (!pathname) { + next(); + return; + } + + const injection = headInjections.get(pathname.replace(/^\//, '')) as Injection | undefined; + + if (!injection || typeof injection === 'string') { + next(); + return; + } + + const serve = (contentType: string) => (content: string, cacheControl = 'public, max-age=31536000'): void => { + res.writeHead(200, { + 'Content-type': contentType, + 'cache-control': cacheControl, + 'Content-Length': content.length, + }); + res.write(content); + res.end(); + }; + + const serveStaticJS = serve('application/javascript; charset=UTF-8'); + const serveStaticCSS = serve('text/css; charset=UTF-8'); + + if (injection.type === 'JS') { + serveStaticJS(injection.content); + return; + } + + if (injection.type === 'CSS') { + serveStaticCSS(injection.content); + return; + } + next(); + } catch (e) { + next(); + } +}; + +WebApp.connectHandlers.use(callback); + +export const injectIntoHead = (key: string, value: Injection): void => { + headInjections.set(key, value); +}; + +export const addScript = (key: string, content: string): void => { + if (!content.trim()) { + injectIntoHead(`${ key }.js`, ''); + return; + } + const currentHash = crypto.createHash('sha1').update(content).digest('hex'); + injectIntoHead(`${ key }.js`, { type: 'JS', tag: ``, content }); +}; + +export const addStyle = (key: string, content: string): void => { + if (!content.trim()) { + injectIntoHead(`${ key }.css`, ''); + return; + } + const currentHash = crypto.createHash('sha1').update(content).digest('hex'); + injectIntoHead(`${ key }.css`, { type: 'CSS', tag: ``, content }); +}; + +export const injectIntoBody = (key: string, value: string): void => { + Inject.rawBody(key, value); +}; + +export const applyHeadInjections = (injections: Injection[]): (html: string) => string => { + if (injections.length === 0) { + return (html: string): string => html; + } + + const replacementHtml = `${ injections.map((i) => { + if (typeof i === 'string') { + return i; + } + return i.content.trim().length > 0 ? i.tag : ''; + }).join('\n').replace(/\$/g, '$$$$') }\n`; + + return (html: string): string => html.replace('', replacementHtml); +}; diff --git a/app/ui-master/server/scripts.ts b/app/ui-master/server/scripts.ts new file mode 100644 index 0000000000000..dab20a2b5bb74 --- /dev/null +++ b/app/ui-master/server/scripts.ts @@ -0,0 +1,43 @@ +import { debounce } from 'underscore'; + +import { settings } from '../../settings/server'; +import { addScript } from './inject'; + +const getContent = (): string => ` +${ process.env.DISABLE_ANIMATION ? 'window.DISABLE_ANIMATION = true;\n' : '' } + +${ settings.get('API_Use_REST_For_DDP_Calls') ? 'window.USE_REST_FOR_DDP_CALLS = true;\n' : '' } + +// Custom_Script_Logged_Out +window.addEventListener('Custom_Script_Logged_Out', function() { + ${ settings.get('Custom_Script_Logged_Out') } +}) + + +// Custom_Script_Logged_In +window.addEventListener('Custom_Script_Logged_In', function() { + ${ settings.get('Custom_Script_Logged_In') } +}) + + +// Custom_Script_On_Logout +window.addEventListener('Custom_Script_On_Logout', function() { + ${ settings.get('Custom_Script_On_Logout') } +}) + +${ settings.get('Accounts_ForgetUserSessionOnWindowClose') ? ` +window.addEventListener('load', function() { + if (window.localStorage) { + Object.keys(window.localStorage).forEach(function(key) { + window.sessionStorage.setItem(key, window.localStorage.getItem(key)); + }); + window.localStorage.clear(); + Meteor._localStorage = window.sessionStorage; + } +}); +` : '' }`; + +settings.get(/(API_Use_REST_For_DDP_Calls|Custom_Script_Logged_Out|Custom_Script_Logged_In|Custom_Script_On_Logout|Accounts_ForgetUserSessionOnWindowClose)/, debounce(() => { + const content = getContent(); + addScript('scripts', content); +}, 1000)); diff --git a/client/types/meteor.d.ts b/client/types/meteor.d.ts index 90878ecd81c2c..fe1c8037162e3 100644 --- a/client/types/meteor.d.ts +++ b/client/types/meteor.d.ts @@ -1,6 +1,4 @@ declare module 'meteor/meteor' { - import { EJSON } from 'meteor/ejson'; - namespace Meteor { interface IDDPMessage { msg: 'method'; diff --git a/package-lock.json b/package-lock.json index fd292fc2d46af..1b8caf735e190 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13574,6 +13574,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.2.1.tgz", "integrity": "sha512-3JwbEeRVQ3n6+JgBW/hCdkydRk9/vWT+UEglcXEJqLJEcUganDH37zlfLznxPKTZZfDqA9K229l1qN458ubcOQ==", + "dev": true, "requires": { "@types/trusted-types": "*" } @@ -13627,7 +13628,8 @@ "@types/fibers": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@types/fibers/-/fibers-3.1.0.tgz", - "integrity": "sha512-1o3I9xtk2PZFxwaLCC6gTaBfBZ5rvw/DSZZPK89fwuwO6LNrzSbC6rEs1xI0bQ3fCRWmO+uNJQQeD2J56oTMDg==" + "integrity": "sha512-1o3I9xtk2PZFxwaLCC6gTaBfBZ5rvw/DSZZPK89fwuwO6LNrzSbC6rEs1xI0bQ3fCRWmO+uNJQQeD2J56oTMDg==", + "dev": true }, "@types/find-cache-dir": { "version": "3.2.0", @@ -13704,6 +13706,7 @@ "version": "0.8.33", "resolved": "https://registry.npmjs.org/@types/imap/-/imap-0.8.33.tgz", "integrity": "sha512-j9yzLtu3OV5YiOWpU33HT9K6RUOsmNSDDOpoflVpPZ586REK9Uyj+ZVUjYkOQJKMszQ7U5/fJWLRN4L56xE0xg==", + "dev": true, "requires": { "@types/node": "*" } @@ -13798,6 +13801,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/mailparser/-/mailparser-3.0.0.tgz", "integrity": "sha512-LsGznUos/+iY83fVjoduIr3PUGfkgtcEvR7HqXpmiP4TsdZo6jf31EcmjDcROmluj1PDMhWRXOxy4ndkx78wUQ==", + "dev": true, "requires": { "@types/node": "*" } @@ -13814,7 +13818,8 @@ "@types/marked": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/marked/-/marked-1.2.2.tgz", - "integrity": "sha512-wLfw1hnuuDYrFz97IzJja0pdVsC0oedtS4QsKH1/inyW9qkLQbXgMUqEQT0MVtUBx3twjWeInUfjQbhBVLECXw==" + "integrity": "sha512-wLfw1hnuuDYrFz97IzJja0pdVsC0oedtS4QsKH1/inyW9qkLQbXgMUqEQT0MVtUBx3twjWeInUfjQbhBVLECXw==", + "dev": true }, "@types/md5-file": { "version": "4.0.2", @@ -13873,6 +13878,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.1.tgz", "integrity": "sha512-HkGSK7CGAXncr8Qn/0VqNtExEE+PHMWb+qlR1faHMao7ng6P3tAaoWWBMdva0gL5h4zprjIO89GJOLXsMcDm1Q==", + "dev": true, "requires": { "@types/node": "*" } @@ -13951,6 +13957,7 @@ "version": "6.4.0", "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.0.tgz", "integrity": "sha512-KY7bFWB0MahRZvVW4CuW83qcCDny59pJJ0MQ5ifvfcjNwPlIT0vW4uARO4u1gtkYnWdhSvURegecY/tzcukJcA==", + "dev": true, "requires": { "@types/node": "*" } @@ -14006,6 +14013,15 @@ "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==", "dev": true }, + "@types/parseurl": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@types/parseurl/-/parseurl-1.3.1.tgz", + "integrity": "sha1-48sRAhYOSO+ln0l8TsIt7k87Wyc=", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/pretty-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.0.tgz", @@ -14152,6 +14168,7 @@ "version": "0.28.0", "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.28.0.tgz", "integrity": "sha512-YvRFnQM44wAihAKzBDzu3BxnEohpqWd/5KXkwsSUl3qFTb51NyKHCKHX1D62YAy0jZij5aXgm/33v/Cv6VVsdA==", + "dev": true, "requires": { "@types/node": "*" } @@ -14185,7 +14202,8 @@ "@types/string-strip-html": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@types/string-strip-html/-/string-strip-html-5.0.0.tgz", - "integrity": "sha512-+mdBIb+pxJ9SLwtjc2DgolMm8U7CG6qBdCevkjSsFB7ehJ0EExFd2ltKQ6m9CoKitqXwe6Tx5h+fAcklGQD0Bw==" + "integrity": "sha512-+mdBIb+pxJ9SLwtjc2DgolMm8U7CG6qBdCevkjSsFB7ehJ0EExFd2ltKQ6m9CoKitqXwe6Tx5h+fAcklGQD0Bw==", + "dev": true }, "@types/tapable": { "version": "1.0.7", @@ -14216,7 +14234,8 @@ "@types/trusted-types": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.0.tgz", - "integrity": "sha512-I8MnZqNXsOLHsU111oHbn3khtvKMi5Bn4qVFsIWSJcCP1KKDiXX5AEw8UPk0nSopeC+Hvxt6yAy1/a5PailFqg==" + "integrity": "sha512-I8MnZqNXsOLHsU111oHbn3khtvKMi5Bn4qVFsIWSJcCP1KKDiXX5AEw8UPk0nSopeC+Hvxt6yAy1/a5PailFqg==", + "dev": true }, "@types/uglify-js": { "version": "3.13.0", @@ -14238,12 +14257,14 @@ "@types/underscore": { "version": "1.9.4", "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.9.4.tgz", - "integrity": "sha512-CjHWEMECc2/UxOZh0kpiz3lEyX2Px3rQS9HzD20lxMvx571ivOBQKeLnqEjxUY0BMgp6WJWo/pQLRBwMW5v4WQ==" + "integrity": "sha512-CjHWEMECc2/UxOZh0kpiz3lEyX2Px3rQS9HzD20lxMvx571ivOBQKeLnqEjxUY0BMgp6WJWo/pQLRBwMW5v4WQ==", + "dev": true }, "@types/underscore.string": { "version": "0.0.38", "resolved": "https://registry.npmjs.org/@types/underscore.string/-/underscore.string-0.0.38.tgz", "integrity": "sha512-QPMttDInBYkulH/3nON0KnYpEd/RlyE5kUrhuts5d76B/stpjXpDticq+iTluoAsVnVXuGECFhPtuX+aDJdx+A==", + "dev": true, "requires": { "@types/underscore": "*" } @@ -14257,7 +14278,8 @@ "@types/use-subscription": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/use-subscription/-/use-subscription-1.0.0.tgz", - "integrity": "sha512-0WWZ5GUDKMXUY/1zy4Ur5/zsC0s/B+JjXfHdkvx6JgDNZzZV5eW+KKhDqsTGyqX56uh99gwGwbsKbVwkcVIKQA==" + "integrity": "sha512-0WWZ5GUDKMXUY/1zy4Ur5/zsC0s/B+JjXfHdkvx6JgDNZzZV5eW+KKhDqsTGyqX56uh99gwGwbsKbVwkcVIKQA==", + "dev": true }, "@types/uuid": { "version": "8.3.0", @@ -14325,6 +14347,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/@types/xml-crypto/-/xml-crypto-1.4.1.tgz", "integrity": "sha512-w7pI4Gq1buWinzLsDopd4du0sUzlSltT7QfHqknLu+hVuFWTXLzJnAOmYKuD20ncx3XCkYNwSRr2sKeYiwCvZw==", + "dev": true, "requires": { "@types/node": "*", "xpath": "0.0.27" @@ -14333,7 +14356,8 @@ "@types/xmldom": { "version": "0.1.30", "resolved": "https://registry.npmjs.org/@types/xmldom/-/xmldom-0.1.30.tgz", - "integrity": "sha512-edqgAFXMEtVvaBZ3YnhamvmrHjoYpuxETmnb0lbTZmf/dXpAsO9ZKotUO4K2rn2SIZBDFCMOuA7fOe0H6dRZcA==" + "integrity": "sha512-edqgAFXMEtVvaBZ3YnhamvmrHjoYpuxETmnb0lbTZmf/dXpAsO9ZKotUO4K2rn2SIZBDFCMOuA7fOe0H6dRZcA==", + "dev": true }, "@types/yargs": { "version": "15.0.13", diff --git a/package.json b/package.json index 0435b93be840c..b0dc94ca9c429 100644 --- a/package.json +++ b/package.json @@ -65,20 +65,34 @@ "@types/chai": "^4.2.12", "@types/chai-spies": "^1.0.1", "@types/clipboard": "^2.0.1", + "@types/dompurify": "^2.2.1", "@types/ejson": "^2.1.2", + "@types/fibers": "^3.1.0", + "@types/imap": "^0.8.33", "@types/jsdom": "^16.2.6", "@types/less": "^3.0.2", + "@types/mailparser": "^3.0.0", + "@types/marked": "^1.2.2", "@types/meteor": "^1.4.49", + "@types/mkdirp": "^1.0.1", "@types/mocha": "^8.0.3", "@types/mock-require": "^2.0.0", "@types/moment-timezone": "^0.5.30", "@types/mongodb": "^3.5.26", "@types/node": "^12.20.10", + "@types/nodemailer": "^6.4.0", + "@types/parseurl": "^1.3.1", "@types/react": "^17.0.11", "@types/react-dom": "^16.9.13", "@types/rewire": "^2.5.28", "@types/semver": "^7.3.3", + "@types/sharp": "^0.28.0", + "@types/string-strip-html": "^5.0.0", "@types/toastr": "^2.1.38", + "@types/underscore.string": "0.0.38", + "@types/use-subscription": "^1.0.0", + "@types/xml-crypto": "^1.4.1", + "@types/xmldom": "^0.1.30", "@typescript-eslint/eslint-plugin": "^2.34.0", "@typescript-eslint/parser": "^2.34.0", "acorn": "^6.4.1", @@ -152,19 +166,6 @@ "@rocket.chat/string-helpers": "^0.26.0", "@rocket.chat/ui-kit": "^0.26.0", "@slack/client": "^4.12.0", - "@types/dompurify": "^2.2.1", - "@types/fibers": "^3.1.0", - "@types/imap": "^0.8.33", - "@types/mailparser": "^3.0.0", - "@types/marked": "^1.2.2", - "@types/mkdirp": "^1.0.1", - "@types/nodemailer": "^6.4.0", - "@types/sharp": "^0.28.0", - "@types/string-strip-html": "^5.0.0", - "@types/underscore.string": "0.0.38", - "@types/use-subscription": "^1.0.0", - "@types/xml-crypto": "^1.4.1", - "@types/xmldom": "^0.1.30", "adm-zip": "RocketChat/adm-zip", "agenda": "^3.1.0", "apn": "2.2.0", diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index f773e5af94525..dd5111cbce58f 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1554,6 +1554,8 @@ "See_on_Engagement_Dashboard": "See on Engagement Dashboard", "Enable": "Enable", "Enable_Auto_Away": "Enable Auto Away", + "Enable_CSP": "Enable Content-Security-Policy", + "Enable_CSP_Description": "Do not disable this option unless you have a custom build and are having problems due to inline-scripts", "Enable_Desktop_Notifications": "Enable Desktop Notifications", "Enable_inquiry_fetch_by_stream": "Enable inquiry data fetch from server using a stream", "Enable_omnichannel_auto_close_abandoned_rooms": "Enable automatic closing of rooms abandoned by the visitor", @@ -4557,4 +4559,4 @@ "Your_temporary_password_is_password": "Your temporary password is [password].", "Your_TOTP_has_been_reset": "Your Two Factor TOTP has been reset.", "Your_workspace_is_ready": "Your workspace is ready to use 🎉" -} \ No newline at end of file +} diff --git a/typings.d.ts b/typings.d.ts index 312f900307918..11f69dff1ce10 100644 --- a/typings.d.ts +++ b/typings.d.ts @@ -19,3 +19,9 @@ declare module 'meteor/konecty:user-presence' { declare const Package: { 'disable-oplog': object; }; + +declare module 'meteor/meteorhacks:inject-initial' { + namespace Inject { + function rawBody(key: string, value: string): void; + } +}