Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ Flowise support different environment variables to configure your instance. You
| Variable | Description | Type | Default |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | ----------------------------------- |
| PORT | The HTTP port Flowise runs on | Number | 3000 |
| CORS_ALLOW_CREDENTIALS | Enables CORS `Access-Control-Allow-Credentials` when `true` | Boolean | false |
| CORS_ORIGINS | The allowed origins for all cross-origin HTTP calls | String | |
| IFRAME_ORIGINS | The allowed origins for iframe src embedding | String | |
| FLOWISE_FILE_SIZE_LIMIT | Upload File Size Limit | String | 50mb |
Expand Down
1 change: 1 addition & 0 deletions docker/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ PORT=3000
############################################################################################################

# NUMBER_OF_PROXIES= 1
# CORS_ALLOW_CREDENTIALS=false
# CORS_ORIGINS=*
# IFRAME_ORIGINS=*
# FLOWISE_FILE_SIZE_LIMIT=50mb
Expand Down
1 change: 1 addition & 0 deletions docker/worker/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ WORKER_PORT=5566
############################################################################################################

# NUMBER_OF_PROXIES= 1
# CORS_ALLOW_CREDENTIALS=false

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be great if a PR could also be added to updated this documentation: https://github.com/FlowiseAI/FlowiseDocs/blob/main/en/configuration/environment-variables.md?plain=1#L181-L190

# CORS_ORIGINS=*
# IFRAME_ORIGINS=*
# FLOWISE_FILE_SIZE_LIMIT=50mb
Expand Down
1 change: 1 addition & 0 deletions packages/server/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ PORT=3000
############################################################################################################

# NUMBER_OF_PROXIES= 1
# CORS_ALLOW_CREDENTIALS=false
# CORS_ORIGINS=*
# IFRAME_ORIGINS=*
# FLOWISE_FILE_SIZE_LIMIT=50mb
Expand Down
5 changes: 0 additions & 5 deletions packages/server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,6 @@ export class App {
// Add the sanitizeMiddleware to guard against XSS
this.app.use(sanitizeMiddleware)

this.app.use((req, res, next) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the approach in this PR in general (better controls with env var and the change is made at the precise area corsOptions), just wondering if anything would be impacted with the removal of this block

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The removed middleware was only ever partially effective. For any request that triggers a preflight (POST with application/json, custom headers like content-type/sentry-trace) — which is the vast majority of Flowise UI traffic — it never worked at all, because cors() intercepts OPTIONS and ends the response before the manual header middleware ran. The header only reached the client for "simple" requests (GET/HEAD, or POST with form-encoded/plain-text bodies), which is a narrow slice that doesn't cover authenticated API flows from what I can tell.

In practice, any integration that needed credentialed cross-origin access to non-simple requests was already broken. Defaulting to false and requiring explicit opt-in via CORS_ALLOW_CREDENTIALS=true is a stricter, more intentional posture with hopefully negligible regression for existing users.

But I'm open to feedback from others if anyone disagrees.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this affect users that have embedded chatbot on their website? https://docs.flowiseai.com/using-flowise/embed#cors

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it probably will, i.e. users need to set the env var to true going forward.

can I suggest that I open a PR to update the documentation?

defaulting to false seems safer because not all Flowise users will be using the embedded chat? so it seems safer to assume we don't want credentials to be passed cross-origin.

I'm open to other POVs though.

res.header('Access-Control-Allow-Credentials', 'true') // Allow credentials (cookies, etc.)
if (next) next()
})

const denylistURLs = process.env.DENYLIST_URLS ? process.env.DENYLIST_URLS.split(',') : []
const whitelistURLs = WHITELIST_URLS.filter((url) => !denylistURLs.includes(url))
const URL_CASE_INSENSITIVE_REGEX: RegExp = /\/api\/v1\//i
Expand Down
5 changes: 5 additions & 0 deletions packages/server/src/utils/XSS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export function getAllowedCorsOrigins(): string {
return process.env.CORS_ORIGINS ?? ''
}

export function getAllowCredentials(): boolean {
return process.env.CORS_ALLOW_CREDENTIALS === 'true'
}

function parseAllowedOrigins(allowedOrigins: string): string[] {
if (!allowedOrigins) {
return []
Expand All @@ -41,6 +45,7 @@ function parseAllowedOrigins(allowedOrigins: string): string[] {
export function getCorsOptions(): any {
return (req: any, callback: (err: Error | null, options?: any) => void) => {
Comment on lines 45 to 46
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve type safety and maintainability, it's best to avoid using any. You can use specific types from the cors package. Using import('cors').CorsOptionsDelegate and import('cors').CorsOptions allows for type-safe code without needing to add a new import statement at the top of the file. The Request type is already available from the existing express import.

Suggested change
export function getCorsOptions(): any {
return (req: any, callback: (err: Error | null, options?: any) => void) => {
export function getCorsOptions(): import('cors').CorsOptionsDelegate {
return (req: Request, callback: (err: Error | null, options?: import('cors').CorsOptions) => void) => {

const corsOptions = {
credentials: getAllowCredentials(),
origin: async (origin: string | undefined, originCallback: (err: Error | null, allow?: boolean) => void) => {
const allowedOrigins = getAllowedCorsOrigins()
const isPublicChatflowReq = isPublicChatflowRequest(req.url)
Expand Down
Loading