diff --git a/config/server/index.js b/config/server/index.js index bf12b548c..8fa618326 100644 --- a/config/server/index.js +++ b/config/server/index.js @@ -2,6 +2,7 @@ const auth = require('./auth'); const consumer = require('./consumer'); +const isIp = require('is-ip'); const isLocalhost = require('is-localhost'); const mail = require('./mail'); const parse = require('url-parse'); @@ -15,6 +16,8 @@ const port = resolvePort(); const origin = resolveOrigin(hostname, protocol, port); const previewUrl = process.env.PREVIEW_URL; +validateStorageProxy(storage.proxy, hostname); + module.exports = { protocol, hostname, @@ -58,3 +61,9 @@ function resolveOriginPort(hostname) { if (REVERSE_PROXY_PORT === '80' || REVERSE_PROXY_PORT === '443') return ''; return `:${REVERSE_PROXY_PORT}`; } + +function validateStorageProxy(proxy, hostname) { + if (isIp.v4(hostname) && /cloudfront/i.test(proxy.provider)) { + throw new Error('CloudFront storage proxy cannot be used alongside IPv4 host name'); + } +} diff --git a/package-lock.json b/package-lock.json index b5fc58adf..679f245bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11229,6 +11229,11 @@ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true }, + "ip-regex": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==" + }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -11471,6 +11476,14 @@ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" }, + "is-ip": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-ip/-/is-ip-3.1.0.tgz", + "integrity": "sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==", + "requires": { + "ip-regex": "^4.0.0" + } + }, "is-localhost": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/is-localhost/-/is-localhost-0.0.2.tgz", diff --git a/package.json b/package.json index fd30c2226..6c71cc13c 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,7 @@ "humanize-string": "^2.1.0", "ioredis": "^4.24.2", "is-iexplorer": "^1.0.0", + "is-ip": "^3.1.0", "is-localhost": "0.0.2", "is-safari": "^1.0.0", "is-url": "^1.2.2", diff --git a/server/shared/storage/proxy/mw.js b/server/shared/storage/proxy/mw.js index 5b43bad14..59d5ea209 100644 --- a/server/shared/storage/proxy/mw.js +++ b/server/shared/storage/proxy/mw.js @@ -2,11 +2,17 @@ const config = require('../../../../config/server'); const { FORBIDDEN } = require('http-status-codes'); +const isIp = require('is-ip'); const miss = require('mississippi'); const path = require('path'); const router = require('express').Router(); const psl = require('psl'); +function getDomain() { + if (isIp.v4(config.hostname)) return null; + return psl.parse(config.hostname).domain; +} + module.exports = (storage, proxy) => { function getFile(req, res, next) { const key = req.params[0]; @@ -24,7 +30,7 @@ module.exports = (storage, proxy) => { if (proxy.hasCookies(req.cookies, repositoryId)) return next(); const maxAge = 1000 * 60 * 60; // 1 hour in ms const cookies = proxy.getSignedCookies(repositoryId, maxAge); - const { domain } = psl.parse(config.hostname); + const domain = getDomain(); const cookieOptions = { domain, maxAge, httpOnly: true }; Object.entries(cookies).forEach(([cookie, value]) => { res.cookie(cookie, value, cookieOptions);