Просмотр исходного кода

Merge branch 'feat/tag-list-page-for-master-merge' into feat/search-with-tag-brush-up

# Conflicts:
#	yarn.lock
yusuketk 7 лет назад
Родитель
Сommit
39c99ecb65

+ 5 - 0
CHANGES.md

@@ -2,8 +2,13 @@
 
 ## 3.4.5-RC
 
+* Improvement: Pass autolink through the XSS filter according to CommonMark Spec
+* Fix: Update ElasticSearch index when deleting/duplicating pages
+* Fix: Xss filter breaks PlantUML arrows
+* Support: Support growi-plugin-lsx@2.2.0
 * Support: Upgrade libs
     * growi-commons
+    * xss
 
 ## 3.4.4
 

+ 2 - 2
package.json

@@ -88,7 +88,7 @@
     "express-webpack-assets": "^0.1.0",
     "googleapis": "^39.1.0",
     "graceful-fs": "^4.1.11",
-    "growi-commons": "^4.0.0",
+    "growi-commons": "^4.0.1",
     "helmet": "^3.13.0",
     "i18next": "^15.0.9",
     "i18next-express-middleware": "^1.4.1",
@@ -124,7 +124,7 @@
     "swig-templates": "^2.0.2",
     "uglifycss": "^0.0.29",
     "url-join": "^4.0.0",
-    "xss": "^1.0.3"
+    "xss": "^1.0.6"
   },
   "devDependencies": {
     "@alienfast/i18next-loader": "^1.0.16",

+ 42 - 0
src/lib/service/xss/commonmark-spec.js

@@ -0,0 +1,42 @@
+/**
+ * Valid schemes
+ * @see https://spec.commonmark.org/0.16/#autolinks
+ */
+const schemesForAutolink = [
+  'coap', 'doi', 'javascript', 'aaa', 'aaas', 'about', 'acap', 'cap', 'cid', 'crid', 'data', 'dav', 'dict', 'dns',
+  'file', 'ftp', 'geo', 'go', 'gopher', 'h323', 'http', 'https', 'iax', 'icap', 'im', 'imap', 'info', 'ipp', 'iris',
+  'iris.beep', 'iris.xpc', 'iris.xpcs', 'iris.lwz', 'ldap', 'mailto', 'mid', 'msrp', 'msrps', 'mtqp', 'mupdate',
+  'news', 'nfs', 'ni', 'nih', 'nntp', 'opaquelocktoken', 'pop', 'pres', 'rtsp', 'service', 'session', 'shttp',
+  'sieve', 'sip', 'sips', 'sms', 'snmp,soap.beep', 'soap.beeps', 'tag', 'tel', 'telnet', 'tftp', 'thismessage',
+  'tn3270', 'tip', 'tv', 'urn', 'vemmi', 'ws', 'wss', 'xcon', 'xcon-userid', 'xmlrpc.beep', 'xmlrpc.beeps', 'xmpp',
+  'z39.50r', 'z39.50s', 'adiumxtra', 'afp', 'afs', 'aim', 'apt,attachment', 'aw', 'beshare', 'bitcoin', 'bolo',
+  'callto', 'chrome,chrome-extension', 'com-eventbrite-attendee', 'content', 'cvs,dlna-playsingle', 'dlna-playcontainer',
+  'dtn', 'dvb', 'ed2k', 'facetime', 'feed', 'finger', 'fish', 'gg', 'git', 'gizmoproject', 'gtalk', 'hcp', 'icon',
+  'ipn', 'irc', 'irc6', 'ircs', 'itms', 'jar', 'jms', 'keyparc', 'lastfm', 'ldaps', 'magnet', 'maps', 'market,message',
+  'mms', 'ms-help', 'msnim', 'mumble', 'mvn', 'notes', 'oid', 'palm', 'paparazzi', 'platform', 'proxy', 'psyc',
+  'query', 'res', 'resource', 'rmi', 'rsync', 'rtmp', 'secondlife', 'sftp', 'sgn', 'skype', 'smb', 'soldat', 'spotify',
+  'ssh', 'steam', 'svn', 'teamspeak', 'things', 'udp', 'unreal', 'ut2004', 'ventrilo', 'view-source', 'webcal',
+  'wtai', 'wyciwyg', 'xfire', 'xri', 'ymsgr',
+];
+const schemesCondition = schemesForAutolink.join('|');
+
+/**
+ * RegExp for URI
+ * @type {RegExp}
+ * @see https://spec.commonmark.org/0.16/#autolinks
+ */
+const uriAutolinkRegexp = new RegExp(`^(${schemesCondition}):\\/\\/.+$`);
+
+/**
+ * RegExp for email
+ * @type {RegExp}
+ * @see https://spec.commonmark.org/0.16/#autolinks
+ */
+// eslint-disable-next-line max-len
+const emailAutolinkRegexp = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
+
+
+module.exports = {
+  uriAutolinkRegexp,
+  emailAutolinkRegexp,
+};

+ 9 - 1
src/lib/service/xss/index.js

@@ -1,7 +1,9 @@
+const xss = require('xss');
+const commonmarkSpec = require('./commonmark-spec');
+
 class Xss {
 
   constructor(xssOption) {
-    const xss = require('xss');
 
     xssOption = xssOption || {}; // eslint-disable-line no-param-reassign
 
@@ -17,6 +19,12 @@ class Xss {
       css: false,
       whiteList: whiteListContent,
       escapeHtml: (html) => { return html }, // resolve https://github.com/weseek/growi/issues/221
+      onTag: (tag, html, options) => {
+        // pass autolink
+        if (tag.match(commonmarkSpec.uriAutolinkRegexp) || tag.match(commonmarkSpec.emailAutolinkRegexp)) {
+          return html;
+        }
+      },
     };
 
     tagWhiteList.forEach((tag) => {

+ 1 - 1
src/lib/service/xss/recommendedXssWhiteList.js → src/lib/service/xss/recommended-whitelist.js

@@ -5,7 +5,7 @@
  */
 
 const tags = [
-  'a', 'b', 'blockquote', 'blockquote', 'code', 'del', 'dd', 'dl', 'dt', 'em',
+  '-', 'a', 'b', 'blockquote', 'blockquote', 'code', 'del', 'dd', 'dl', 'dt', 'em',
   'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'i', 'img', 'kbd', 'li', 'ol', 'p', 'pre',
   's', 'sup', 'sub', 'strong', 'strike', 'ul', 'br', 'hr', 'span', 'div', 'iframe',
   'table', 'thead', 'tbody', 'tfoot', 'th', 'td', 'tr', 'colgroup', 'col',

+ 3 - 3
src/lib/service/xss/xssOption.js

@@ -1,12 +1,12 @@
 class XssOption {
 
   constructor(config) {
-    const recommendedXssWhiteList = require('./recommendedXssWhiteList');
+    const recommendedWhitelist = require('./recommended-whitelist');
     const initializedConfig = (config != null) ? config : {};
 
     this.isEnabledXssPrevention = initializedConfig.isEnabledXssPrevention || true;
-    this.tagWhiteList = initializedConfig.tagWhiteList || recommendedXssWhiteList.tags;
-    this.attrWhiteList = initializedConfig.attrWhiteList || recommendedXssWhiteList.attrs;
+    this.tagWhiteList = initializedConfig.tagWhiteList || recommendedWhitelist.tags;
+    this.attrWhiteList = initializedConfig.attrWhiteList || recommendedWhitelist.attrs;
   }
 
 }

+ 3 - 3
src/server/models/config.js

@@ -7,7 +7,7 @@ module.exports = function(crowi) {
   const mongoose = require('mongoose');
   const debug = require('debug')('growi:models:config');
   const uglifycss = require('uglifycss');
-  const recommendedXssWhiteList = require('@commons/service/xss/recommendedXssWhiteList');
+  const recommendedWhitelist = require('@commons/service/xss/recommended-whitelist');
 
   const SECURITY_RESTRICT_GUEST_MODE_DENY = 'Deny';
   const SECURITY_RESTRICT_GUEST_MODE_READONLY = 'Readonly';
@@ -430,7 +430,7 @@ module.exports = function(crowi) {
           return [];
 
         case 2: // recommended
-          return recommendedXssWhiteList.tags;
+          return recommendedWhitelist.tags;
 
         case 3: // custom white list
           return config.markdown[key];
@@ -453,7 +453,7 @@ module.exports = function(crowi) {
           return [];
 
         case 2: // recommended
-          return recommendedXssWhiteList.attrs;
+          return recommendedWhitelist.attrs;
 
         case 3: // custom white list
           return config.markdown[key];

+ 2 - 2
src/server/routes/admin.js

@@ -14,7 +14,7 @@ module.exports = function(crowi, app) {
   const GlobalNotificationMailSetting = models.GlobalNotificationMailSetting;
   const GlobalNotificationSlackSetting = models.GlobalNotificationSlackSetting; // eslint-disable-line no-unused-vars
 
-  const recommendedXssWhiteList = require('@commons/service/xss/recommendedXssWhiteList');
+  const recommendedWhitelist = require('@commons/service/xss/recommended-whitelist');
   const PluginUtils = require('../plugins/plugin-utils');
   const ApiResponse = require('../util/apiResponse');
   const importer = require('../util/importer')(crowi);
@@ -117,7 +117,7 @@ module.exports = function(crowi, app) {
 
     return res.render('admin/markdown', {
       markdownSetting,
-      recommendedXssWhiteList,
+      recommendedWhitelist,
     });
   };
 

+ 2 - 2
src/server/views/admin/markdown.html

@@ -193,11 +193,11 @@
               <p class="font-weight-bold">{{ t('markdown_setting.Recommended setting') }}</p>
               <div class="m-t-15">
                 {{ t('markdown_setting.Tag names') }}
-                <textarea class="form-control xss-list" name="recommendedTags" rows="6" cols="40" readonly>{{ recommendedXssWhiteList.tags }}</textarea>
+                <textarea class="form-control xss-list" name="recommendedTags" rows="6" cols="40" readonly>{{ recommendedWhitelist.tags }}</textarea>
               </div>
               <div class="m-t-15">
                 {{ t('markdown_setting.Tag attributes') }}
-                <textarea class="form-control xss-list" name="recommendedAttrs" rows="6" cols="40" readonly>{{ recommendedXssWhiteList.attrs }}</textarea>
+                <textarea class="form-control xss-list" name="recommendedAttrs" rows="6" cols="40" readonly>{{ recommendedWhitelist.attrs }}</textarea>
               </div>
             </label>
           </div>

+ 8 - 6
yarn.lock

@@ -4644,9 +4644,10 @@ graceful-fs@^4.1.15:
   version "4.1.15"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
 
-growi-commons@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/growi-commons/-/growi-commons-4.0.0.tgz#f0c0b0f2bac218111555869d7d405e235fb053c6"
+growi-commons@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/growi-commons/-/growi-commons-4.0.1.tgz#e0e71c9c286f493e11c0703c809385bcdc6a97a9"
+  integrity sha512-haH4Av1WuQIHic4Jv2RRwDprbKecRKF/3C0wVk9ssBzWtB3V6Oghj5gksajDpYOd7tOKdvkVEqqkFfIV4JQUyQ==
 
 growl@1.10.5:
   version "1.10.5"
@@ -11163,9 +11164,10 @@ xpath@0.0.27:
   version "0.0.27"
   resolved "https://registry.yarnpkg.com/xpath/-/xpath-0.0.27.tgz#dd3421fbdcc5646ac32c48531b4d7e9d0c2cfa92"
 
-xss@^1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.3.tgz#d04bd2558fd6c29c46113824d5e8b2a910054e23"
+xss@^1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.6.tgz#eaf11e9fc476e3ae289944a1009efddd8a124b51"
+  integrity sha512-6Q9TPBeNyoTRxgZFk5Ggaepk/4vUOYdOsIUYvLehcsIZTFjaavbVnsuAkLA5lIFuug5hw8zxcB9tm01gsjph2A==
   dependencies:
     commander "^2.9.0"
     cssfilter "0.0.10"