Merge pull request #3872 from codecombat/filter-domains

Code Review: Filter domains for webdev iFrame
This commit is contained in:
Rob Blanckaert 2016-09-08 17:46:00 -04:00 committed by GitHub
commit af3e069828
5 changed files with 33 additions and 9 deletions

View file

@ -17,13 +17,9 @@ var virtualScripts;
var goalStates; var goalStates;
var allowedOrigins = [ var allowedOrigins = [
/https:\/\/codecombat\.com/, /^https?:\/\/(.*\.)?codecombat\.com$/,
/https?:\/\/cn\.codecombat\.com/, /^https?:\/\/localhost:3000$/,
/http:\/\/localhost:3000/, /^https?:\/\/.*codecombat-staging-codecombat\.runnableapp\.com$/,
/http:\/\/direct\.codecombat\.com/,
/http:\/\/staging\.codecombat\.com/,
/http:\/\/next\.codecombat\.com/,
/http:\/\/.*codecombat-staging-codecombat\.runnableapp\.com/,
]; ];
function receiveMessage(event) { function receiveMessage(event) {

View file

@ -1 +1 @@
iframe(src="/web-dev-iframe.html") iframe(src="http://" + fullUnsafeContentHostname + "/web-dev-iframe.html")

View file

@ -13,6 +13,9 @@ module.exports = class WebSurfaceView extends CocoView
# Consider https://www.npmjs.com/package/css-select to do this on virtualDom instead of in iframe on concreteDOM # Consider https://www.npmjs.com/package/css-select to do this on virtualDom instead of in iframe on concreteDOM
super(options) super(options)
getRenderData: ->
_.merge super(), { fullUnsafeContentHostname: serverConfig.fullUnsafeContentHostname }
afterRender: -> afterRender: ->
super() super()
@iframe = @$('iframe')[0] @iframe = @$('iframe')[0]
@ -81,7 +84,7 @@ module.exports = class WebSurfaceView extends CocoView
onIframeMessage: (event) => onIframeMessage: (event) =>
origin = event.origin or event.originalEvent.origin origin = event.origin or event.originalEvent.origin
unless origin is window.location.origin unless new RegExp("^https?:\/\/#{serverConfig.fullUnsafeContentHostname}$").test origin
return console.log 'Ignoring message from bad origin:', origin return console.log 'Ignoring message from bad origin:', origin
unless event.source is @iframe.contentWindow unless event.source is @iframe.contentWindow
return console.log 'Ignoring message from somewhere other than our iframe:', event.source return console.log 'Ignoring message from somewhere other than our iframe:', event.source

View file

@ -91,6 +91,11 @@ config.cookie_secret = process.env.COCO_COOKIE_SECRET or 'chips ahoy'
config.isProduction = config.mongo.host isnt 'localhost' config.isProduction = config.mongo.host isnt 'localhost'
# Domains (without subdomain prefix, with port number) for main hostname (usually codecombat.com)
# and unsafe web-dev iFrame content (usually codecombatprojects.com).
config.mainHostname = process.env.COCO_MAIN_HOSTNAME or 'localhost:3000'
config.unsafeContentHostname = process.env.COCO_UNSAFE_CONTENT_HOSTNAME or 'localhost:3000'
if process.env.COCO_PICOCTF if process.env.COCO_PICOCTF
config.picoCTF = true config.picoCTF = true
config.picoCTF_api_url = 'http://staging.picoctf.com/api' config.picoCTF_api_url = 'http://staging.picoctf.com/api'

View file

@ -52,6 +52,22 @@ developmentLogging = (tokens, req, res) ->
s += ' (proxied)' if req.proxied s += ' (proxied)' if req.proxied
return s return s
setupDomainFilterMiddleware = (app) ->
if config.isProduction
unsafePaths = [
/^\/web-dev-iframe\.html$/
/^\/javascripts\/web-dev-listener\.js$/
]
app.use (req, res, next) ->
domainRegex = new RegExp("(.*\.)?(#{config.mainHostname}|#{config.unsafeContentHostname})")
domainPrefix = req.host.match(domainRegex)?[1] or ''
if _.any(unsafePaths, (pathRegex) -> pathRegex.test(req.path)) and (req.host isnt domainPrefix + config.unsafeContentHostname)
res.redirect('http://' + domainPrefix + config.unsafeContentHostname + req.path)
else if not _.any(unsafePaths, (pathRegex) -> pathRegex.test(req.path)) and req.host is domainPrefix + config.unsafeContentHostname
res.redirect('http://' + domainPrefix + config.mainHostname + req.path)
else
next()
setupErrorMiddleware = (app) -> setupErrorMiddleware = (app) ->
app.use (err, req, res, next) -> app.use (err, req, res, next) ->
if err if err
@ -177,6 +193,7 @@ exports.setupMiddleware = (app) ->
setupPerfMonMiddleware app setupPerfMonMiddleware app
setupCountryRedirectMiddleware app, "china", "CN", "zh", config.chinaDomain setupCountryRedirectMiddleware app, "china", "CN", "zh", config.chinaDomain
setupCountryRedirectMiddleware app, "brazil", "BR", "pt-BR", config.brazilDomain setupCountryRedirectMiddleware app, "brazil", "BR", "pt-BR", config.brazilDomain
setupDomainFilterMiddleware app
setupMiddlewareToSendOldBrowserWarningWhenPlayersViewLevelDirectly app setupMiddlewareToSendOldBrowserWarningWhenPlayersViewLevelDirectly app
setupExpressMiddleware app setupExpressMiddleware app
setupPassportMiddleware app setupPassportMiddleware app
@ -206,6 +223,9 @@ setupFallbackRouteToIndex = (app) ->
configData = _.omit mandate?.toObject() or {}, '_id' configData = _.omit mandate?.toObject() or {}, '_id'
configData.picoCTF = config.picoCTF configData.picoCTF = config.picoCTF
configData.production = config.isProduction configData.production = config.isProduction
domainRegex = new RegExp("(.*\.)?(#{config.mainHostname}|#{config.unsafeContentHostname})")
domainPrefix = req.host.match(domainRegex)?[1] or ''
configData.fullUnsafeContentHostname = domainPrefix + config.unsafeContentHostname
data = data.replace '"serverConfigTag"', JSON.stringify configData data = data.replace '"serverConfigTag"', JSON.stringify configData
data = data.replace('"userObjectTag"', user) data = data.replace('"userObjectTag"', user)
data = data.replace('"amActuallyTag"', JSON.stringify(req.session.amActually)) data = data.replace('"amActuallyTag"', JSON.stringify(req.session.amActually))