Skip to content

Commit d30901d

Browse files
authored
Merge branch 'main' into fix/agentflow-sdk-fix-duplicate-and-drag
2 parents 68d732e + 7291ab8 commit d30901d

24 files changed

Lines changed: 724 additions & 293 deletions

File tree

.github/workflows/docker-image-ecr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ on:
2525
default: 'latest'
2626

2727
permissions:
28-
contents: read # Required for checkout
28+
contents: read # Required for checkout
2929
id-token: write # Required for AWS OIDC
3030

3131
jobs:

SECURITY.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
At Flowise, we prioritize security and continuously work to safeguard our systems. However, vulnerabilities can still exist. If you identify a security issue, please report it to us so we can address it promptly. Your cooperation helps us better protect our platform and users.
44

55
### Scope
6+
67
- Flowise Cloud: cloud.flowiseai.com
78
- Public Flowise Repositories
89

@@ -31,7 +32,6 @@ At Flowise, we prioritize security and continuously work to safeguard our system
3132
- Known vulnerabilities in used libraries (unless exploitability can be proven)
3233
- Static application security testing findings
3334

34-
3535
### Reporting Guidelines
3636

3737
- Submit your findings to https://github.com/FlowiseAI/Flowise/security
@@ -46,9 +46,10 @@ At Flowise, we prioritize security and continuously work to safeguard our system
4646

4747
### Disclosure Terms
4848

49-
The Flowise team believes that transparency is important and public bug bounty reports are a valuable source of knowledge for bug bounty researchers. However, the Flowise team may have legitimate reasons not to disclose vulnerabilities.
49+
The Flowise team believes that transparency is important and public bug bounty reports are a valuable source of knowledge for bug bounty researchers. However, the Flowise team may have legitimate reasons not to disclose vulnerabilities.
5050

5151
Do not discuss or disclose vulnerability information without prior written consent. If you plan on presenting your research, please share a draft with us at least 45 days in advance for review. Avoid including:
52+
5253
- Data from any Flowise customer projects
5354
- Flowise user/customer information
5455
- Details about Flowise employees, contractors, or partners
@@ -63,7 +64,7 @@ We will validate submissions within the below timelines.
6364
| Medium | 15 business days |
6465
| Low | 15 business days |
6566

66-
Your report will be kept *confidential*, and your details will not be shared without your consent. The Flowise team will triage and adjust severity or CVSS score if necessary.
67+
Your report will be kept _confidential_, and your details will not be shared without your consent. The Flowise team will triage and adjust severity or CVSS score if necessary.
6768
We appreciate your efforts in helping us maintain a secure platform and look forward to working together to resolve any issues responsibly.
6869

6970
### Remediation
@@ -72,15 +73,16 @@ Once the report has been verified, the Flowise team will plan the remediation st
7273
Below is the estimated time to remediate the triaged security reports.
7374

7475
| Triaged Severity | Estimated Time to Remediate |
75-
| ---------------------- | ---------------- |
76-
| Critical | 30 business days |
77-
| High | 60 business days |
78-
| Medium | 90 business days |
76+
| ---------------- | --------------------------- |
77+
| Critical | 30 business days |
78+
| High | 60 business days |
79+
| Medium | 90 business days |
7980

8081
### Public Disclosure Timeline
8182

8283
Public Disclosure occurs exactly 30 days after the next official release that includes the security patch. This period gives Flowise users a time to adopt the patched version before technical vulnerability details are made public, mitigating the risk of immediate post-disclosure exploitation.
8384

8485
#### Reaching out to the Security team
86+
8587
To report a new vulnerability, please submit a Github security Security Advisory report.
86-
If you have any questions or concerns about the existing Security Advisory, please contact security-team@flowiseai.com.
88+
If you have any questions or concerns about the existing Security Advisory, please contact security-team@flowiseai.com.

packages/agentflow/package.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@
4444
"*.css"
4545
],
4646
"scripts": {
47-
"build": "tsc && cross-env NODE_ENV=production vite build",
47+
"build": "tsc && vite build",
4848
"clean": "rimraf dist",
49-
"dev": "cross-env NODE_ENV=development vite",
50-
"dev:example": "cross-env NODE_ENV=development vite --config examples/vite.config.ts",
49+
"dev": "vite",
50+
"dev:example": "vite --config examples/vite.config.ts",
5151
"format": "prettier --write \"{src,examples}/**/*.{ts,tsx,js,jsx,json,css,md}\"",
5252
"format:check": "prettier --check \"{src,examples}/**/*.{ts,tsx,js,jsx,json,css,md}\"",
5353
"lint": "eslint \"{src,examples/src}/**/*.{js,jsx,ts,tsx,json,md}\"",
@@ -89,7 +89,6 @@
8989
"eslint-plugin-simple-import-sort": "^12.0.0",
9090
"jest": "^29.7.0",
9191
"jest-environment-jsdom": "^29.7.0",
92-
"cross-env": "^7.0.3",
9392
"rimraf": "^5.0.5",
9493
"ts-jest": "^29.3.2",
9594
"typescript": "^5.4.5",

packages/agentflow/vite.config.ts

Lines changed: 53 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,59 +3,61 @@ import react from '@vitejs/plugin-react'
33
import dts from 'vite-plugin-dts'
44
import { resolve } from 'path'
55

6-
const isDev = process.env.NODE_ENV === 'development'
6+
export default defineConfig(({ mode }) => {
7+
const isDev = mode === 'development'
78

8-
export default defineConfig({
9-
plugins: [
10-
react(),
11-
dts({
12-
insertTypesEntry: true,
13-
include: ['src/**/*'],
14-
exclude: ['src/**/*.test.ts', 'src/**/*.test.tsx', 'src/__test_utils__/**']
15-
})
16-
],
17-
resolve: {
18-
alias: {
19-
'@': resolve(__dirname, 'src')
20-
}
21-
},
22-
build: {
23-
lib: {
24-
entry: resolve(__dirname, 'src/index.ts'),
25-
name: 'FlowiseAgentflow',
26-
formats: ['es', 'umd'],
27-
fileName: (format) => `index.${format === 'es' ? 'js' : 'umd.js'}`
28-
},
29-
rollupOptions: {
30-
external: [
31-
'react',
32-
'react-dom',
33-
'react/jsx-runtime',
34-
'@mui/material',
35-
'@mui/material/styles',
36-
'@mui/icons-material',
37-
'@emotion/react',
38-
'@emotion/styled',
39-
'reactflow'
40-
],
41-
output: {
42-
globals: {
43-
react: 'React',
44-
'react-dom': 'ReactDOM',
45-
'react/jsx-runtime': 'jsxRuntime',
46-
'@mui/material': 'MaterialUI',
47-
'@mui/material/styles': 'MaterialUIStyles',
48-
'@emotion/react': 'emotionReact',
49-
'@emotion/styled': 'emotionStyled',
50-
reactflow: 'ReactFlow'
51-
},
52-
assetFileNames: (assetInfo) => {
53-
if (assetInfo.name === 'style.css') return 'flowise.css'
54-
return assetInfo.name || 'asset'
55-
}
9+
return {
10+
plugins: [
11+
react(),
12+
dts({
13+
insertTypesEntry: true,
14+
include: ['src/**/*'],
15+
exclude: ['src/**/*.test.ts', 'src/**/*.test.tsx', 'src/__test_utils__/**']
16+
})
17+
],
18+
resolve: {
19+
alias: {
20+
'@': resolve(__dirname, 'src')
5621
}
5722
},
58-
cssCodeSplit: false,
59-
sourcemap: isDev ? true : false
23+
build: {
24+
lib: {
25+
entry: resolve(__dirname, 'src/index.ts'),
26+
name: 'FlowiseAgentflow',
27+
formats: ['es', 'umd'],
28+
fileName: (format) => `index.${format === 'es' ? 'js' : 'umd.js'}`
29+
},
30+
rollupOptions: {
31+
external: [
32+
'react',
33+
'react-dom',
34+
'react/jsx-runtime',
35+
'@mui/material',
36+
'@mui/material/styles',
37+
'@mui/icons-material',
38+
'@emotion/react',
39+
'@emotion/styled',
40+
'reactflow'
41+
],
42+
output: {
43+
globals: {
44+
react: 'React',
45+
'react-dom': 'ReactDOM',
46+
'react/jsx-runtime': 'jsxRuntime',
47+
'@mui/material': 'MaterialUI',
48+
'@mui/material/styles': 'MaterialUIStyles',
49+
'@emotion/react': 'emotionReact',
50+
'@emotion/styled': 'emotionStyled',
51+
reactflow: 'ReactFlow'
52+
},
53+
assetFileNames: (assetInfo) => {
54+
if (assetInfo.name === 'style.css') return 'flowise.css'
55+
return assetInfo.name || 'asset'
56+
}
57+
}
58+
},
59+
cssCodeSplit: false,
60+
sourcemap: isDev ? true : false
61+
}
6062
}
6163
})

packages/components/credentials/AWSCredential.credential.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class AWSApi implements INodeCredential {
1111
constructor() {
1212
this.label = 'AWS security credentials'
1313
this.name = 'awsApi'
14-
this.version = 1.0
14+
this.version = 1.1
1515
this.description =
1616
'Your <a target="_blank" href="https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html">AWS security credentials</a>. When unspecified, credentials will be sourced from the runtime environment according to the default AWS SDK behavior.'
1717
this.optional = true
@@ -39,6 +39,24 @@ class AWSApi implements INodeCredential {
3939
placeholder: '<AWS_SESSION_TOKEN>',
4040
description: 'The session key for your AWS account. This is only needed when you are using temporary credentials.',
4141
optional: true
42+
},
43+
{
44+
label: 'Role ARN',
45+
name: 'roleArn',
46+
type: 'string',
47+
placeholder: 'arn:aws:iam::123456789012:role/role-name',
48+
description:
49+
'The Amazon Resource Name (ARN) of the IAM role to assume. When provided, Flowise will use AWS STS AssumeRole to obtain temporary credentials. Leave empty to use static credentials directly.',
50+
optional: true
51+
},
52+
{
53+
label: 'External ID',
54+
name: 'externalId',
55+
type: 'string',
56+
placeholder: 'unique-external-id',
57+
description:
58+
'A unique identifier used for cross-account role assumption. Required when the role trust policy includes an sts:ExternalId condition.',
59+
optional: true
4260
}
4361
]
4462
}

packages/components/nodes/chatmodels/AWSBedrock/AWSChatBedrock.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { BaseCache } from '@langchain/core/caches'
22
import { ICommonObject, IMultiModalOption, INode, INodeData, INodeOptionsValue, INodeParams } from '../../../src/Interface'
3-
import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
3+
import { getBaseClasses } from '../../../src/utils'
44
import { getModels, getRegions, MODEL_TYPE } from '../../../src/modelLoader'
5+
import { getAWSCredentialConfig } from '../../../src/awsToolsUtils'
56
import { ChatBedrockConverseInput, ChatBedrockConverse } from '@langchain/aws'
67
import { BedrockChat } from './FlowiseAWSChatBedrock'
78

@@ -163,19 +164,12 @@ class AWSChatBedrock_ChatModels implements INode {
163164
* Bedrock's credential provider falls back to the AWS SDK to fetch
164165
* credentials from the running environment.
165166
* When specified, we override the default provider with configured values.
167+
* Supports STS AssumeRole when a Role ARN is configured in the credential.
166168
* @see https://github.com/aws/aws-sdk-js-v3/blob/main/packages/credential-provider-node/README.md
167169
*/
168-
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
169-
if (credentialData && Object.keys(credentialData).length !== 0) {
170-
const credentialApiKey = getCredentialParam('awsKey', credentialData, nodeData)
171-
const credentialApiSecret = getCredentialParam('awsSecret', credentialData, nodeData)
172-
const credentialApiSession = getCredentialParam('awsSession', credentialData, nodeData)
173-
174-
obj.credentials = {
175-
accessKeyId: credentialApiKey,
176-
secretAccessKey: credentialApiSecret,
177-
sessionToken: credentialApiSession
178-
}
170+
const credentialConfig = await getAWSCredentialConfig(nodeData, options, iRegion)
171+
if (credentialConfig.credentials) {
172+
obj.credentials = credentialConfig.credentials
179173
}
180174
if (cache) obj.cache = cache
181175

packages/components/nodes/documentloaders/S3Directory/S3Directory.ts

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
import { ICommonObject, INode, INodeData, INodeOptionsValue, INodeOutputsValue, INodeParams } from '../../../src/Interface'
2-
import {
3-
getCredentialData,
4-
getCredentialParam,
5-
handleDocumentLoaderDocuments,
6-
handleDocumentLoaderMetadata,
7-
handleDocumentLoaderOutput
8-
} from '../../../src/utils'
2+
import { handleDocumentLoaderDocuments, handleDocumentLoaderMetadata, handleDocumentLoaderOutput } from '../../../src/utils'
3+
import { getAWSCredentialConfig } from '../../../src/awsToolsUtils'
94
import { S3Client, GetObjectCommand, S3ClientConfig, ListObjectsV2Command, ListObjectsV2Output } from '@aws-sdk/client-s3'
105
import { getRegions, MODEL_TYPE } from '../../../src/modelLoader'
116
import { Readable } from 'node:stream'
@@ -158,18 +153,9 @@ class S3_DocumentLoaders implements INode {
158153
const output = nodeData.outputs?.output as string
159154

160155
let credentials: S3ClientConfig['credentials'] | undefined
161-
162156
if (nodeData.credential) {
163-
const credentialData = await getCredentialData(nodeData.credential, options)
164-
const accessKeyId = getCredentialParam('awsKey', credentialData, nodeData)
165-
const secretAccessKey = getCredentialParam('awsSecret', credentialData, nodeData)
166-
167-
if (accessKeyId && secretAccessKey) {
168-
credentials = {
169-
accessKeyId,
170-
secretAccessKey
171-
}
172-
}
157+
const credentialConfig = await getAWSCredentialConfig(nodeData, options, region)
158+
credentials = credentialConfig.credentials
173159
}
174160

175161
let s3Config: S3ClientConfig = {

packages/components/nodes/documentloaders/S3File/S3File.ts

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,8 @@ import {
77
SkipInferTableTypes,
88
HiResModelName
99
} from '@langchain/community/document_loaders/fs/unstructured'
10-
import {
11-
getCredentialData,
12-
getCredentialParam,
13-
handleDocumentLoaderDocuments,
14-
handleDocumentLoaderMetadata,
15-
handleDocumentLoaderOutput
16-
} from '../../../src/utils'
10+
import { handleDocumentLoaderDocuments, handleDocumentLoaderMetadata, handleDocumentLoaderOutput } from '../../../src/utils'
11+
import { getAWSCredentialConfig } from '../../../src/awsToolsUtils'
1712
import { S3Client, GetObjectCommand, HeadObjectCommand, S3ClientConfig } from '@aws-sdk/client-s3'
1813
import { getRegions, MODEL_TYPE } from '../../../src/modelLoader'
1914
import { Readable } from 'node:stream'
@@ -581,18 +576,9 @@ class S3_DocumentLoaders implements INode {
581576
}
582577

583578
let credentials: S3ClientConfig['credentials'] | undefined
584-
585579
if (nodeData.credential) {
586-
const credentialData = await getCredentialData(nodeData.credential, options)
587-
const accessKeyId = getCredentialParam('awsKey', credentialData, nodeData)
588-
const secretAccessKey = getCredentialParam('awsSecret', credentialData, nodeData)
589-
590-
if (accessKeyId && secretAccessKey) {
591-
credentials = {
592-
accessKeyId,
593-
secretAccessKey
594-
}
595-
}
580+
const credentialConfig = await getAWSCredentialConfig(nodeData, options, region)
581+
credentials = credentialConfig.credentials
596582
}
597583

598584
const s3Config: S3ClientConfig = {

packages/components/nodes/embeddings/AWSBedrockEmbedding/AWSBedrockEmbedding.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { BedrockRuntimeClient, InvokeModelCommand } from '@aws-sdk/client-bedrock-runtime'
22
import { BedrockEmbeddings, BedrockEmbeddingsParams } from '@langchain/community/embeddings/bedrock'
33
import { ICommonObject, INode, INodeData, INodeOptionsValue, INodeParams } from '../../../src/Interface'
4-
import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
4+
import { getBaseClasses } from '../../../src/utils'
5+
import { getAWSCredentialConfig } from '../../../src/awsToolsUtils'
56
import { MODEL_TYPE, getModels, getRegions } from '../../../src/modelLoader'
67

78
class AWSBedrockEmbedding_Embeddings implements INode {
@@ -129,17 +130,15 @@ class AWSBedrockEmbedding_Embeddings implements INode {
129130
region: iRegion
130131
}
131132

132-
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
133-
if (credentialData && Object.keys(credentialData).length !== 0) {
134-
const credentialApiKey = getCredentialParam('awsKey', credentialData, nodeData)
135-
const credentialApiSecret = getCredentialParam('awsSecret', credentialData, nodeData)
136-
const credentialApiSession = getCredentialParam('awsSession', credentialData, nodeData)
137-
138-
obj.credentials = {
139-
accessKeyId: credentialApiKey,
140-
secretAccessKey: credentialApiSecret,
141-
sessionToken: credentialApiSession
142-
}
133+
/**
134+
* Long-term credentials specified in embedding configuration are optional.
135+
* Bedrock's credential provider falls back to the AWS SDK to fetch
136+
* credentials from the running environment.
137+
* Supports STS AssumeRole when a Role ARN is configured in the credential.
138+
*/
139+
const credentialConfig = await getAWSCredentialConfig(nodeData, options, iRegion)
140+
if (credentialConfig.credentials) {
141+
obj.credentials = credentialConfig.credentials
143142
}
144143

145144
const client = new BedrockRuntimeClient({

0 commit comments

Comments
 (0)