Fix up API CORS header processing (#277)

* Fix ultra embarrassing bug not restricting CORS origins

* Put CORS origin regexps in common

* Static types so I don't muck it up again

* Fixup CORS regex to be more strict

* Fix sloppy imports to actually work
This commit is contained in:
Marshall Polaris 2022-05-20 19:34:26 -07:00 committed by GitHub
parent 540476f65a
commit 98c5329e03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 6 deletions

View File

@ -1,3 +1,4 @@
import { escapeRegExp } from 'lodash'
import { DEV_CONFIG } from './dev' import { DEV_CONFIG } from './dev'
import { EnvConfig, PROD_CONFIG } from './prod' import { EnvConfig, PROD_CONFIG } from './prod'
import { THEOREMONE_CONFIG } from './theoremone' import { THEOREMONE_CONFIG } from './theoremone'
@ -28,3 +29,10 @@ export const DOMAIN = ENV_CONFIG.domain
export const FIREBASE_CONFIG = ENV_CONFIG.firebaseConfig export const FIREBASE_CONFIG = ENV_CONFIG.firebaseConfig
export const PROJECT_ID = ENV_CONFIG.firebaseConfig.projectId export const PROJECT_ID = ENV_CONFIG.firebaseConfig.projectId
export const IS_PRIVATE_MANIFOLD = ENV_CONFIG.visibility === 'PRIVATE' export const IS_PRIVATE_MANIFOLD = ENV_CONFIG.visibility === 'PRIVATE'
// Manifold's domain or any subdomains thereof
export const CORS_ORIGIN_MANIFOLD = new RegExp(
'^https?://(?:[a-zA-Z0-9\\-]+\\.)*' + escapeRegExp(ENV_CONFIG.domain) + '$'
)
// Any localhost server on any port
export const CORS_ORIGIN_LOCALHOST = /^http:\/\/localhost:\d+$/

View File

@ -2,7 +2,11 @@ import * as admin from 'firebase-admin'
import * as functions from 'firebase-functions' import * as functions from 'firebase-functions'
import * as Cors from 'cors' import * as Cors from 'cors'
import { User, PrivateUser } from 'common/user' import { User, PrivateUser } from '../../common/user'
import {
CORS_ORIGIN_MANIFOLD,
CORS_ORIGIN_LOCALHOST,
} from '../../common/envs/constants'
type Request = functions.https.Request type Request = functions.https.Request
type Response = functions.Response type Response = functions.Response
@ -90,10 +94,11 @@ export const lookupUser = async (creds: Credentials): Promise<AuthedUser> => {
} }
} }
export const CORS_ORIGIN_MANIFOLD = /^https?:\/\/.+\.manifold\.markets$/ export const applyCors = (
export const CORS_ORIGIN_LOCALHOST = /^http:\/\/localhost:\d+$/ req: Request,
res: Response,
export const applyCors = (req: any, res: any, params: object) => { params: Cors.CorsOptions
) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
Cors(params)(req, res, (result) => { Cors(params)(req, res, (result) => {
if (result instanceof Error) { if (result instanceof Error) {
@ -107,7 +112,7 @@ export const applyCors = (req: any, res: any, params: object) => {
export const newEndpoint = (methods: [string], fn: Handler) => export const newEndpoint = (methods: [string], fn: Handler) =>
functions.runWith({ minInstances: 1 }).https.onRequest(async (req, res) => { functions.runWith({ minInstances: 1 }).https.onRequest(async (req, res) => {
await applyCors(req, res, { await applyCors(req, res, {
origins: [CORS_ORIGIN_MANIFOLD, CORS_ORIGIN_LOCALHOST], origin: [CORS_ORIGIN_MANIFOLD, CORS_ORIGIN_LOCALHOST],
methods: methods, methods: methods,
}) })
try { try {