diff options
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | app.js | 17 | ||||
-rw-r--r-- | config.json.example | 13 | ||||
-rw-r--r-- | lib/config/default.js | 14 | ||||
-rw-r--r-- | lib/config/environment.js | 10 | ||||
-rw-r--r-- | lib/config/index.js | 20 | ||||
-rw-r--r-- | lib/csp.js | 80 | ||||
-rw-r--r-- | lib/response.js | 3 | ||||
-rw-r--r-- | lib/web/imageRouter.js | 34 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | public/js/extra.js | 4 | ||||
-rw-r--r-- | public/js/lib/common/constant.ejs | 4 | ||||
-rw-r--r-- | public/js/mathjax-config-extra.js | 8 | ||||
-rw-r--r-- | public/vendor/inlineAttachment/inline-attachment.js | 13 | ||||
-rw-r--r-- | public/views/hackmd/foot.ejs | 4 | ||||
-rw-r--r-- | public/views/pretty.ejs | 4 | ||||
-rw-r--r-- | public/views/slide.ejs | 6 | ||||
-rw-r--r-- | yarn.lock | 57 |
18 files changed, 262 insertions, 35 deletions
@@ -197,6 +197,7 @@ There are some configs you need to change in the files below | HMD_HSTS_INCLUDE_SUBDOMAINS | `true` | set to include subdomains in HSTS (default is `true`) | | HMD_HSTS_MAX_AGE | `31536000` | max duration in seconds to tell clients to keep HSTS status (default is a year) | | HMD_HSTS_PRELOAD | `true` | whether to allow preloading of the site's HSTS status (e.g. into browsers) | +| HMD_CSP_ENABLE | `true` | whether to enable Content Security Policy (directives cannot be configured with environment variables) | ## Application settings `config.json` @@ -208,7 +209,8 @@ There are some configs you need to change in the files below | port | `80` | web app port | | alloworigin | `['localhost']` | domain name whitelist | | usessl | `true` or `false` | set to use ssl server (if true will auto turn on `protocolusessl`) | -| hsts | `{"enable": "true", "maxAgeSeconds": "31536000", "includeSubdomains": "true", "preload": "true"}` | [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) options to use with HTTPS (default is the example value, max age is a year) | +| hsts | `{"enable": true, "maxAgeSeconds": 31536000, "includeSubdomains": true, "preload": true}` | [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) options to use with HTTPS (default is the example value, max age is a year) | +| csp | `{"enable": true, "directives": {"scriptSrc": "trustworthy-scripts.example.com"}, "upgradeInsecureRequests": "auto", "addDefaults": true}` | Configures [Content Security Policy](https://helmetjs.github.io/docs/csp/). Directives are passed to Helmet - see [their documentation](https://helmetjs.github.io/docs/csp/) for more information on the format. Some defaults are added to the configured values so that the application doesn't break. To disable this behaviour, set `addDefaults` to `false`. Further, if `usecdn` is on, some CDN locations are allowed too. By default (`auto`), insecure (HTTP) requests are upgraded to HTTPS via CSP if `usessl` is on. To change this behaviour, set `upgradeInsecureRequests` to either `true` or `false`. | | protocolusessl | `true` or `false` | set to use ssl protocol for resources path (only applied when domain is set) | | urladdport | `true` or `false` | set to add port on callback url (port 80 or 443 won't applied) (only applied when domain is set) | | usecdn | `true` or `false` | set to use CDN resources or not (default is `true`) | @@ -24,6 +24,7 @@ var config = require('./lib/config') var logger = require('./lib/logger') var response = require('./lib/response') var models = require('./lib/models') +var csp = require('./lib/csp') // generate front-end constants by template var constpath = path.join(__dirname, './public/js/lib/common/constant.ejs') @@ -34,7 +35,8 @@ var data = { version: config.version, GOOGLE_API_KEY: config.google.clientSecret, GOOGLE_CLIENT_ID: config.google.clientID, - DROPBOX_APP_KEY: config.dropbox.appKey + DROPBOX_APP_KEY: config.dropbox.appKey, + allowedUploadMimeTypes: config.allowedUploadMimeTypes } ejs.renderFile(constpath, data, {}, function (err, str) { @@ -108,6 +110,19 @@ if (config.hsts.enable) { logger.info('https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security') } +// Generate a random nonce per request, for CSP with inline scripts +app.use(csp.addNonceToLocals) + +// use Content-Security-Policy to limit XSS, dangerous plugins, etc. +// https://helmetjs.github.io/docs/csp/ +if (config.csp.enable) { + app.use(helmet.contentSecurityPolicy({ + directives: csp.computeDirectives() + })) +} else { + logger.info('Content-Security-Policy is disabled. This may be a security risk.') +} + i18n.configure({ locales: ['en', 'zh', 'zh-CN', 'zh-TW', 'fr', 'de', 'ja', 'es', 'ca', 'el', 'pt', 'it', 'tr', 'ru', 'nl', 'hr', 'pl', 'uk', 'hi', 'sv', 'eo', 'da'], cookie: 'locale', diff --git a/config.json.example b/config.json.example index c2c270c3..f5ddf182 100644 --- a/config.json.example +++ b/config.json.example @@ -17,10 +17,17 @@ "production": { "domain": "localhost", "hsts": { - "enable": "true", + "enable": true, "maxAgeSeconds": "31536000", - "includeSubdomains": "true", - "preload": "true" + "includeSubdomains": true, + "preload": true + }, + csp: { + "enable": true, + "directives": { + }, + "upgradeInsecureRequests": "auto" + "addDefaults": true }, "db": { "username": "", diff --git a/lib/config/default.js b/lib/config/default.js index 000c154a..28f4490c 100644 --- a/lib/config/default.js +++ b/lib/config/default.js @@ -13,6 +13,13 @@ module.exports = { includeSubdomains: true, preload: true }, + csp: { + enable: true, + directives: { + }, + addDefaults: true, + upgradeInsecureRequests: 'auto' + }, protocolusessl: false, usecdn: true, allowanonymous: true, @@ -55,6 +62,13 @@ module.exports = { secretAccessKey: undefined, region: undefined }, + minio: { + accessKey: undefined, + secretKey: undefined, + endPoint: undefined, + secure: true, + port: 9000 + }, s3bucket: undefined, // authentication facebook: { diff --git a/lib/config/environment.js b/lib/config/environment.js index eedd4913..e2112b6a 100644 --- a/lib/config/environment.js +++ b/lib/config/environment.js @@ -14,6 +14,9 @@ module.exports = { includeSubdomains: toBooleanConfig(process.env.HMD_HSTS_INCLUDE_SUBDOMAINS), preload: toBooleanConfig(process.env.HMD_HSTS_PRELOAD) }, + csp: { + enable: toBooleanConfig(process.env.HMD_CSP_ENABLE) + }, protocolusessl: toBooleanConfig(process.env.HMD_PROTOCOL_USESSL), alloworigin: toArrayConfig(process.env.HMD_ALLOW_ORIGIN), usecdn: toBooleanConfig(process.env.HMD_USECDN), @@ -31,6 +34,13 @@ module.exports = { secretAccessKey: process.env.HMD_S3_SECRET_ACCESS_KEY, region: process.env.HMD_S3_REGION }, + minio: { + accessKey: process.env.HMD_MINIO_ACCESS_KEY, + secretKey: process.env.HMD_MINIO_SECRET_KEY, + endPoint: process.env.HMD_MINIO_ENDPOINT, + secure: toBooleanConfig(process.env.HMD_MINIO_SECURE), + port: process.env.HMD_MINIO_PORT + }, s3bucket: process.env.HMD_S3_BUCKET, facebook: { clientID: process.env.HMD_FACEBOOK_CLIENTID, diff --git a/lib/config/index.js b/lib/config/index.js index 3d22c3c3..4f6b4b6a 100644 --- a/lib/config/index.js +++ b/lib/config/index.js @@ -97,6 +97,26 @@ config.isLDAPEnable = config.ldap.url config.isSAMLEnable = config.saml.idpSsoUrl config.isPDFExportEnable = config.allowpdfexport +// figure out mime types for image uploads +switch (config.imageUploadType) { + case 'imgur': + config.allowedUploadMimeTypes = [ + 'image/jpeg', + 'image/png', + 'image/jpg', + 'image/gif' + ] + break + default: + config.allowedUploadMimeTypes = [ + 'image/jpeg', + 'image/png', + 'image/jpg', + 'image/gif', + 'image/svg+xml' + ] +} + // generate correct path config.sslcapath.forEach(function (capath, i, array) { array[i] = path.resolve(appRootPath, capath) diff --git a/lib/csp.js b/lib/csp.js new file mode 100644 index 00000000..509bc530 --- /dev/null +++ b/lib/csp.js @@ -0,0 +1,80 @@ +var config = require('./config') +var uuid = require('uuid') + +var CspStrategy = {} + +var defaultDirectives = { + defaultSrc: ['\'self\''], + scriptSrc: ['\'self\'', 'vimeo.com', 'https://gist.github.com', 'www.slideshare.net', 'https://query.yahooapis.com', 'https://*.disqus.com', '\'unsafe-eval\''], + // ^ TODO: Remove unsafe-eval - webpack script-loader issues https://github.com/hackmdio/hackmd/issues/594 + imgSrc: ['*'], + styleSrc: ['\'self\'', '\'unsafe-inline\'', 'https://assets-cdn.github.com'], // unsafe-inline is required for some libs, plus used in views + fontSrc: ['\'self\'', 'https://public.slidesharecdn.com'], + objectSrc: ['*'], // Chrome PDF viewer treats PDFs as objects :/ + childSrc: ['*'], + connectSrc: ['*'] +} + +var cdnDirectives = { + scriptSrc: ['https://cdnjs.cloudflare.com', 'https://cdn.mathjax.org'], + styleSrc: ['https://cdnjs.cloudflare.com', 'https://fonts.googleapis.com'], + fontSrc: ['https://cdnjs.cloudflare.com', 'https://fonts.gstatic.com'] +} + +CspStrategy.computeDirectives = function () { + var directives = {} + mergeDirectives(directives, config.csp.directives) + mergeDirectivesIf(config.csp.addDefaults, directives, defaultDirectives) + mergeDirectivesIf(config.usecdn, directives, cdnDirectives) + if (!areAllInlineScriptsAllowed(directives)) { + addInlineScriptExceptions(directives) + } + addUpgradeUnsafeRequestsOptionTo(directives) + return directives +} + +function mergeDirectives (existingDirectives, newDirectives) { + for (var propertyName in newDirectives) { + var newDirective = newDirectives[propertyName] + if (newDirective) { + var existingDirective = existingDirectives[propertyName] || [] + existingDirectives[propertyName] = existingDirective.concat(newDirective) + } + } +} + +function mergeDirectivesIf (condition, existingDirectives, newDirectives) { + if (condition) { + mergeDirectives(existingDirectives, newDirectives) + } +} + +function areAllInlineScriptsAllowed (directives) { + return directives.scriptSrc.indexOf('\'unsafe-inline\'') !== -1 +} + +function addInlineScriptExceptions (directives) { + directives.scriptSrc.push(getCspNonce) + // TODO: This is the SHA-256 hash of the inline script in build/reveal.js/plugins/notes/notes.html + // Any more clean solution appreciated. + directives.scriptSrc.push('\'sha256-EtvSSxRwce5cLeFBZbvZvDrTiRoyoXbWWwvEVciM5Ag=\'') +} + +function getCspNonce (req, res) { + return "'nonce-" + res.locals.nonce + "'" +} + +function addUpgradeUnsafeRequestsOptionTo (directives) { + if (config.csp.upgradeInsecureRequests === 'auto' && config.usessl) { + directives.upgradeInsecureRequests = true + } else if (config.csp.upgradeInsecureRequests === true) { + directives.upgradeInsecureRequests = true + } +} + +CspStrategy.addNonceToLocals = function (req, res, next) { + res.locals.nonce = uuid.v4() + next() +} + +module.exports = CspStrategy diff --git a/lib/response.js b/lib/response.js index 1c04f9f6..445aa0d7 100644 --- a/lib/response.js +++ b/lib/response.js @@ -598,7 +598,8 @@ function showPublishSlide (req, res, next) { lastchangeuserprofile: note.lastchangeuser ? models.User.getProfile(note.lastchangeuser) : null, robots: meta.robots || false, // default allow robots GA: meta.GA, - disqus: meta.disqus + disqus: meta.disqus, + cspNonce: res.locals.nonce } return renderPublishSlide(data, res) }).catch(function (err) { diff --git a/lib/web/imageRouter.js b/lib/web/imageRouter.js index bebab302..b17cccbd 100644 --- a/lib/web/imageRouter.js +++ b/lib/web/imageRouter.js @@ -73,6 +73,40 @@ imageRouter.post('/uploadimage', function (req, res) { }) }) break + + case 'minio': + var utils = require('../utils') + var Minio = require('minio') + var minioClient = new Minio.Client({ + endPoint: config.minio.endPoint, + port: config.minio.port, + secure: config.minio.secure, + accessKey: config.minio.accessKey, + secretKey: config.minio.secretKey + }) + fs.readFile(files.image.path, function (err, buffer) { + if (err) { + logger.error(err) + res.status(500).end('upload image error') + return + } + + var key = path.join('uploads', path.basename(files.image.path)) + var protocol = config.minio.secure ? 'https' : 'http' + + minioClient.putObject(config.s3bucket, key, buffer, buffer.size, utils.getImageMimeType(files.image.path), function (err, data) { + if (err) { + logger.error(err) + res.status(500).end('upload image error') + return + } + res.send({ + link: `${protocol}://${config.minio.endPoint}:${config.minio.port}/${config.s3bucket}/${key}` + }) + }) + }) + break + case 'imgur': default: imgur.setClientId(config.imgur.clientID) diff --git a/package.json b/package.json index bdb59635..94107783 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "mattermost": "^3.4.0", "meta-marked": "^0.4.2", "method-override": "^2.3.7", + "minio": "^3.1.3", "moment": "^2.17.1", "morgan": "^1.7.0", "mysql": "^2.12.0", @@ -118,6 +119,7 @@ "tedious": "^1.14.0", "to-markdown": "^3.0.3", "toobusy-js": "^0.5.1", + "uuid": "^3.1.0", "uws": "~0.14.1", "validator": "^6.2.0", "velocity-animate": "^1.4.0", diff --git a/public/js/extra.js b/public/js/extra.js index ec7d39da..dbb0f458 100644 --- a/public/js/extra.js +++ b/public/js/extra.js @@ -713,11 +713,11 @@ $.fn.sortByDepth = function () { function toggleTodoEvent (e) { const startline = $(this).closest('li').attr('data-startline') - 1 const line = window.editor.getLine(startline) - const matches = line.match(/^[>\s]*[-+*]\s\[([x ])\]/) + const matches = line.match(/^[>\s-]*[-+*]\s\[([x ])\]/) if (matches && matches.length >= 2) { let checked = null if (matches[1] === 'x') { checked = true } else if (matches[1] === ' ') { checked = false } - const replacements = matches[0].match(/(^[>\s]*[-+*]\s\[)([x ])(\])/) + const replacements = matches[0].match(/(^[>\s-]*[-+*]\s\[)([x ])(\])/) window.editor.replaceRange(checked ? ' ' : 'x', { line: startline, ch: replacements[1].length diff --git a/public/js/lib/common/constant.ejs b/public/js/lib/common/constant.ejs index e4a1cf0a..c0963635 100644 --- a/public/js/lib/common/constant.ejs +++ b/public/js/lib/common/constant.ejs @@ -3,6 +3,8 @@ window.urlpath = '<%- urlpath %>' window.debug = <%- debug %> window.version = '<%- version %>' +window.allowedUploadMimeTypes = <%- JSON.stringify(allowedUploadMimeTypes) %> + window.GOOGLE_API_KEY = '<%- GOOGLE_API_KEY %>' window.GOOGLE_CLIENT_ID = '<%- GOOGLE_CLIENT_ID %>' -window.DROPBOX_APP_KEY = '<%- DROPBOX_APP_KEY %>'
\ No newline at end of file +window.DROPBOX_APP_KEY = '<%- DROPBOX_APP_KEY %>' diff --git a/public/js/mathjax-config-extra.js b/public/js/mathjax-config-extra.js new file mode 100644 index 00000000..11ba59c6 --- /dev/null +++ b/public/js/mathjax-config-extra.js @@ -0,0 +1,8 @@ +window.MathJax = { + messageStyle: 'none', + skipStartupTypeset: true, + tex2jax: { + inlineMath: [['$', '$'], ['\\(', '\\)']], + processEscapes: true + } +} diff --git a/public/vendor/inlineAttachment/inline-attachment.js b/public/vendor/inlineAttachment/inline-attachment.js index 0ffd3f9f..d9503d62 100644 --- a/public/vendor/inlineAttachment/inline-attachment.js +++ b/public/vendor/inlineAttachment/inline-attachment.js @@ -141,12 +141,7 @@ /** * Allowed MIME types */ - allowedTypes: [ - 'image/jpeg', - 'image/png', - 'image/jpg', - 'image/gif' - ], + allowedTypes: window.allowedUploadMimeTypes, /** * Text which will be inserted when dropping or pasting a file. @@ -304,7 +299,7 @@ if (this.settings.onFileUploadResponse.call(this, xhr) !== false) { var result = JSON.parse(xhr.responseText), filename = result[this.settings.jsonFieldName]; - + if (result && filename) { var replacements = []; var string = this.settings.progressText.replace(this.filenameTag, id); @@ -415,7 +410,7 @@ // <http://wiki.ecmascript.org/doku.php?id=strawman:names>. // // The goals of this function are twofold: -// +// // * Provide a way to generate a string guaranteed to be unique when compared // to other strings generated by this function. // * Make the string complex enough that it is highly unlikely to be @@ -432,4 +427,4 @@ var ID = function () { // Convert it to base 36 (numbers + letters), and grab the first 9 characters // after the decimal. return '_' + Math.random().toString(36).substr(2, 9); -};
\ No newline at end of file +}; diff --git a/public/views/hackmd/foot.ejs b/public/views/hackmd/foot.ejs index 16ef5737..fc971132 100644 --- a/public/views/hackmd/foot.ejs +++ b/public/views/hackmd/foot.ejs @@ -1,6 +1,4 @@ -<script type="text/x-mathjax-config"> - MathJax.Hub.Config({ messageStyle: "none", skipStartupTypeset: true ,tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']], processEscapes: true }}); -</script> +<script src="<%= url %>/js/mathjax-config-extra.js"></script> <% if(useCDN) { %> <script src="https://cdnjs.cloudflare.com/ajax/libs/spin.js/2.3.2/spin.min.js" integrity="sha256-PieqE0QdEDMppwXrTzSZQr6tWFX3W5KkyRVyF1zN3eg=" crossorigin="anonymous" defer></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script> diff --git a/public/views/pretty.ejs b/public/views/pretty.ejs index db72fdc4..91d9c36c 100644 --- a/public/views/pretty.ejs +++ b/public/views/pretty.ejs @@ -72,9 +72,7 @@ </body> </html> -<script type="text/x-mathjax-config"> - MathJax.Hub.Config({ messageStyle: "none", skipStartupTypeset: true ,tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']], processEscapes: true }}); -</script> +<script src="<%= url %>/js/mathjax-config-extra.js"></script> <% if(useCDN) { %> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.4.0/velocity.min.js" integrity="sha256-bhm0lgEt6ITaZCDzZpkr/VXVrLa5RP4u9v2AYsbzSUk=" crossorigin="anonymous" defer></script> diff --git a/public/views/slide.ejs b/public/views/slide.ejs index 3572476f..942add4f 100644 --- a/public/views/slide.ejs +++ b/public/views/slide.ejs @@ -41,7 +41,7 @@ <link rel="stylesheet" href="<%- url %>/css/slide.css"> <!-- Printing and PDF exports --> - <script> + <script nonce="<%= cspNonce %>"> var link = document.createElement( 'link' ); link.rel = 'stylesheet'; link.type = 'text/css'; @@ -89,9 +89,7 @@ </div> </div> - <script type="text/x-mathjax-config"> - MathJax.Hub.Config({ messageStyle: "none", skipStartupTypeset: true ,tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']], processEscapes: true }}); - </script> + <script src="<%= url %>/js/mathjax-config-extra.js"></script> <% if(useCDN) { %> <script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.3.0/lib/js/head.min.js" integrity="sha256-+09kLhwACKXFPDvqo4xMMvi4+uXFsRZ2uYGbeN1U8sI=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.3.0/js/reveal.min.js" integrity="sha256-lvaInSKflJWLPqf5N5oHr/UZFwXKD6gckerdwoHqECY=" crossorigin="anonymous"></script> @@ -877,6 +877,14 @@ block-elements@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/block-elements/-/block-elements-1.2.0.tgz#8e04ccab638c7e2596f5065fb6c1c7518c905a5d" +block-stream2@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/block-stream2/-/block-stream2-1.1.0.tgz#c738e3a91ba977ebb5e1fef431e13ca11d8639e2" + dependencies: + defined "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.4" + block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" @@ -1378,7 +1386,7 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@1.6.0, concat-stream@^1.4.1, concat-stream@^1.4.7, concat-stream@^1.5.2: +concat-stream@1.6.0, concat-stream@^1.4.1, concat-stream@^1.4.7, concat-stream@^1.4.8, concat-stream@^1.5.2: version "1.6.0" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" dependencies: @@ -2100,6 +2108,10 @@ es5-ext@^0.10.12, es5-ext@^0.10.14, es5-ext@^0.10.30, es5-ext@^0.10.9, es5-ext@~ es6-iterator "2" es6-symbol "~3.1" +es6-error@^2.0.2: + version "2.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-2.1.1.tgz#91384301ec5ed1c9a7247d1128247216f03547cd" + es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512" @@ -3864,6 +3876,10 @@ json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: dependencies: jsonify "~0.0.0" +json-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-stream/-/json-stream-1.0.0.tgz#1a3854e28d2bbeeab31cc7ddf683d2ddc5652708" + json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -4244,7 +4260,7 @@ lodash@^3.6.0: version "3.10.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" -lodash@^4.0.0, lodash@^4.11.1, lodash@^4.14.0, lodash@^4.17.0, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.3.0: +lodash@^4.0.0, lodash@^4.11.1, lodash@^4.14.0, lodash@^4.14.2, lodash@^4.17.0, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.3.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -4566,7 +4582,7 @@ micromatch@^2.1.5, micromatch@^2.3.7: version "1.30.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" -mime-types@^2.1.12, mime-types@^2.1.3, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.7: +mime-types@^2.1.12, mime-types@^2.1.14, mime-types@^2.1.3, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.7: version "2.1.17" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" dependencies: @@ -4619,6 +4635,25 @@ minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" +minio@^3.1.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/minio/-/minio-3.2.3.tgz#00a2ec46cba41596cf73fca162192718d0197c49" + dependencies: + async "^1.5.2" + block-stream2 "^1.0.0" + concat-stream "^1.4.8" + es6-error "^2.0.2" + json-stream "^1.0.0" + lodash "^4.14.2" + mime-types "^2.1.14" + mkdirp "^0.5.1" + querystring "0.2.0" + source-map-support "^0.4.12" + through2 "^0.6.5" + uuid "^3.1.0" + xml "^1.0.0" + xml2js "^0.4.15" + mkdirp@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12" @@ -5915,7 +5950,7 @@ readable-stream@1.1, readable-stream@~1.1.9: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@2.3.3, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6: +readable-stream@2.3.3, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" dependencies: @@ -6515,7 +6550,7 @@ source-list-map@^0.1.7, source-list-map@~0.1.7: version "0.1.8" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106" -source-map-support@^0.4.0, source-map-support@^0.4.15: +source-map-support@^0.4.0, source-map-support@^0.4.12, source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" dependencies: @@ -6906,7 +6941,7 @@ throttleit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" -through2@^0.6.1: +through2@^0.6.1, through2@^0.6.5: version "0.6.5" resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" dependencies: @@ -7296,6 +7331,10 @@ uuid@3.0.1, uuid@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" +uuid@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" + uws@~0.14.1: version "0.14.5" resolved "https://registry.yarnpkg.com/uws/-/uws-0.14.5.tgz#67aaf33c46b2a587a5f6666d00f7691328f149dc" @@ -7619,13 +7658,17 @@ xml2js@0.4.17: sax ">=0.6.0" xmlbuilder "^4.1.0" -xml2js@0.4.x: +xml2js@0.4.x, xml2js@^0.4.15: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" dependencies: sax ">=0.6.0" xmlbuilder "~9.0.1" +xml@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" + xmlbuilder@4.2.1, xmlbuilder@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-4.2.1.tgz#aa58a3041a066f90eaa16c2f5389ff19f3f461a5" |