Bugfix/Auth URL Bypass (#3095)

add fixes to prevent bypassing api url
This commit is contained in:
Henry Heng
2024-08-27 16:35:52 +01:00
committed by GitHub
parent ace8b852cb
commit 286121e4e3
+40 -20
View File
@@ -135,6 +135,8 @@ export class App {
'/api/v1/ip', '/api/v1/ip',
'/api/v1/ping' '/api/v1/ping'
] ]
const URL_CASE_INSENSITIVE_REGEX: RegExp = /\/api\/v1\//i
const URL_CASE_SENSITIVE_REGEX: RegExp = /\/api\/v1\//
if (process.env.FLOWISE_USERNAME && process.env.FLOWISE_PASSWORD) { if (process.env.FLOWISE_USERNAME && process.env.FLOWISE_PASSWORD) {
const username = process.env.FLOWISE_USERNAME const username = process.env.FLOWISE_USERNAME
@@ -143,37 +145,55 @@ export class App {
users: { [username]: password } users: { [username]: password }
}) })
this.app.use(async (req, res, next) => { this.app.use(async (req, res, next) => {
if (/\/api\/v1\//i.test(req.url)) { // Step 1: Check if the req path contains /api/v1 regardless of case
if (whitelistURLs.some((url) => new RegExp(url, 'i').test(req.url))) { if (URL_CASE_INSENSITIVE_REGEX.test(req.path)) {
next() // Step 2: Check if the req path is case sensitive
} else if (req.headers['x-request-from'] === 'internal') { if (URL_CASE_SENSITIVE_REGEX.test(req.path)) {
basicAuthMiddleware(req, res, next) // Step 3: Check if the req path is in the whitelist
} else { const isWhitelisted = whitelistURLs.some((url) => req.path.startsWith(url))
const isKeyValidated = await validateAPIKey(req) if (isWhitelisted) {
if (!isKeyValidated) { next()
return res.status(401).json({ error: 'Unauthorized Access' }) } else if (req.headers['x-request-from'] === 'internal') {
basicAuthMiddleware(req, res, next)
} else {
const isKeyValidated = await validateAPIKey(req)
if (!isKeyValidated) {
return res.status(401).json({ error: 'Unauthorized Access' })
}
next()
} }
next() } else {
return res.status(401).json({ error: 'Unauthorized Access' })
} }
} else { } else {
// If the req path does not contain /api/v1, then allow the request to pass through, example: /assets, /canvas
next() next()
} }
}) })
} else { } else {
this.app.use(async (req, res, next) => { this.app.use(async (req, res, next) => {
if (/\/api\/v1\//i.test(req.url)) { // Step 1: Check if the req path contains /api/v1 regardless of case
if (whitelistURLs.some((url) => new RegExp(url, 'i').test(req.url))) { if (URL_CASE_INSENSITIVE_REGEX.test(req.path)) {
next() // Step 2: Check if the req path is case sensitive
} else if (req.headers['x-request-from'] === 'internal') { if (URL_CASE_SENSITIVE_REGEX.test(req.path)) {
next() // Step 3: Check if the req path is in the whitelist
} else { const isWhitelisted = whitelistURLs.some((url) => req.path.startsWith(url))
const isKeyValidated = await validateAPIKey(req) if (isWhitelisted) {
if (!isKeyValidated) { next()
return res.status(401).json({ error: 'Unauthorized Access' }) } else if (req.headers['x-request-from'] === 'internal') {
next()
} else {
const isKeyValidated = await validateAPIKey(req)
if (!isKeyValidated) {
return res.status(401).json({ error: 'Unauthorized Access' })
}
next()
} }
next() } else {
return res.status(401).json({ error: 'Unauthorized Access' })
} }
} else { } else {
// If the req path does not contain /api/v1, then allow the request to pass through, example: /assets, /canvas
next() next()
} }
}) })