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;
+ }
+}