Back to skill

Security audit

S2G - General Purpose Workflow Engine

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real S2G bridge, but it exposes powerful workflow execution too broadly and logs sensitive data, so it needs review before installation.

Install only if you trust the S2G workflows and can restrict the bridge. Run it bound to localhost or behind a firewall, add authentication before exposing execution endpoints, avoid connecting high-impact nodes unless needed, protect or disable logs that may contain secrets, and review any workflow or knowledge-base delete/update operations before letting an agent call them.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (6)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/s2g-bridge.js:257
Finding

Unauthenticated Privileged Workflow API Exposed on All Network Interfaces

Content
View full analysis
{ const url = new URL(req.url, `http://localhost:${HTTP_PORT}`); const p = url.pathname; res.setHeader('Content-Type', 'application/json'); res.setHeader('Access-Control-Allow-Origin', '*'); if (req.method === 'OPTIONS') { res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); res.statusCode = 204; res.end(); return; } if (req.method === 'GET' && p === '/status') { res.end(JSON.stringify({ connected, s2gHost: S2G_WS_HOST, nodeId: NODE_ID, lastConnected, lastError, stats, pendingRequests: pendingRequests.size, nodes: availableNodes.map(n => ({ name: n.name, type: n.nodeType, id: n.nodeId, outputs: n.outputParams })) }, null, 2)); return; } if (req.method === 'GET' && p === '/nodes') { res.end(JSON.stringify({ connected, nodes: availableNodes }, null, 2)); return; } if (req.method === 'POST' && p === '/execute') { const body = await readBody(req); if (!body.nodeId) { res.statusCode = 400; res.end(JSON.stringify({ error: 'Missing nodeId' })); return; } const result = await executeNode(body.nodeId, body.params || {}, body.timeout || DEFAULT_TIMEOUT); res.end(JSON.stringify(result, null, 2)); return; } if (req.method === 'POST' && p.startsWith('/execute/')) { const name = decodeURIComponent(p.slice('/execute/'.length)); const node = findNode(name); if (!node) { res.statusCode = 404; res.end(JSON.stringify({ error: `Node "${name}" not found`, available: availableNodes.map(n => n.name) })); return; } const body = await readBody(req); const params = body ...[truncated 2499 chars]
Remediation
View remediation
{ // ... }); ``` 2. Require a cryptographically strong bearer token or use a Unix-domain socket. Compare tokens using a timing-safe comparison. 3. Do not reuse the S2G WebSocket secret as the local API credential. 4. Require an explicit option such as `--allow-remote` before accepting non-loopback bindings. 5. Add per-node authorization or an allowlist so callers cannot execute every discovered node. 6. Disable high-impact nodes by default, particularly database, cloud, HTTP, scripting, and destructive knowledge-base operations. 7. Apply firewall rules as defense in depth, not as the primary access-control mechanism. 8. Return minimal information from `/status` and `/nodes` to unauthenticated health checks. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/s2g-bridge.js:261
Finding

Wildcard CORS Enables Browser-Based Workflow Invocation

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/s2g-bridge.js:30
Finding

Sensitive Execution Parameters and Pushed Data Persisted in Plaintext Logs

Content
View full analysis
MAX_LOG_SIZE) { const bak = LOG_FILE + '.1'; if (fs.existsSync(bak)) fs.unlinkSync(bak); fs.renameSync(LOG_FILE, bak); } } catch (_) {} } function writeLog(line) { rotateIfNeeded(); try { fs.appendFileSync(LOG_FILE, line + '\n'); } catch (_) {} } ``` ```js default: log(`📨 Received [${msg.type}]: ${JSON.stringify(msg.data || msg).slice(0, 500)}`); ``` ```js log(`Execute ${requestId} -> ${nodeId} params=${JSON.stringify(params)}`); ``` ### Technical Analysis Every execution request serializes its complete `params` object into the persistent log. Unrecognized inbound messages, including S2G data-push messages, are also serialized up to 500 characters. The Skill explicitly supports password-related nodes, SQL queries, webhook forwarding, AI prompts, cloud connectors, knowledge-base content, and other custom operations. Parameters and pushed payloads can therefore contain credentials, personal information, database content, tokens, customer records, confidential prompts, and other sensitive material. The log and rotated backup are created without explicit restrictive file modes. Their effective permissions depend on process umask and directory permissions. Logging is enabled by default, and rotation limits only file size rather than preventing disclosure. ### Attack Path 1. A legitimate caller submits a sensitive value through `/execute`, or S2G sends sensitive Input Forwa ...[truncated 951 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/s2g-bridge.js:293
Finding

Unbounded Request Bodies and Client-Controlled Execution Timeouts Allow Resource Exhaustion

Content
View full analysis
n.name) })); return; } const body = await readBody(req); const params = body.params || body; const timeout = body.timeout || DEFAULT_TIMEOUT; const result = await executeNode(node.nodeId, params, timeout); res.end(JSON.stringify(result, null, 2)); return; } ``` ```js function readBody(req) { return new Promise((resolve) => { let data = ''; req.on('data', chunk => data += chunk); req.on('end', () => { try { resolve(JSON.parse(data)); } catch { resolve({}); } }); }); } ``` ### Technical Analysis `readBody` appends every received chunk to an in-memory string without enforcing a maximum request size. A client can send a very large body or slowly continue transmitting data, consuming memory and retaining server resources. The `timeout` property is also passed directly to `setTimeout` through `executeNode` without type, minimum, or maximum validation. In addition, the server imposes no rate limit or cap on concurrent pending executions. These conditions are especially dangerous because the service is unauthenticated and listens on every interface. ### Atta ...[truncated 976 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
README.md:80
Finding

Security Documentation Misrepresents a Network-Exposed API as Local-Only

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
SKILL.md:71
Finding

Unpinned Runtime Dependencies Create Non-Reproducible Installations

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
Findings (43)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 64)May include surrounding context.

md
cp scripts/s2g-bridge.js ~/.openclaw/workspace/s2g-bridge.js

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The docs explicitly show programmatic extraction of an API key from a local credentials file, which is a credential access pattern. In an agent-skill setting, this is especially dangerous because an automated system may adopt the pattern to retrieve secrets without sufficient user awareness, potentially exposing keys through logs, prompts, subprocesses, or unintended command execution.

Content

Scanner excerpt · references/api.md (reported line 7)May include surrounding context.

Auth: All endpoints require X-API-Key header.

bash
KEY=$(python3 -c 'import json;print(json.load(open("'$HOME'/.config/s2g/credentials.json"))["apiKey"])')
BASE="https://s2g.run/api/v1"

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · references/api.md (reported line 85)May include surrounding context.

Add a Node (preserves existing IDs)

bash
curl -X POST "$BASE/workflows/$WF_ID/nodes" \
  -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"nodeType":"Custom_HashGenerator","name":"HashGenerator","x":320,"y":600}'
# Returns: { "id": "new-uuid", "name": "HashGenerator", ... }

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · references/api.md (reported line 130)May include surrounding context.

List Categories

bash
curl -H "X-API-Key: $KEY" "$BASE/catalog/categories"
# [{"name":"HTTP","type":"builtin","nodeCount":3},
#  {"name":"AI","type":"builtin","nodeCount":13},
#  {"name":"Knowledge","type":"builtin","nodeCount":1}, ...]

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · references/api.md (reported line 178)May include surrounding context.

md
for t in sorted(types): print(t)
" | while read ntype; do
  echo "=== $ntype ==="
  curl -s -H "X-API-Key: $KEY" "$BASE/catalog/nodes/$ntype/schema" | python3 -c "
import json, sys
d = json.load(sys.stdin)
print(', '.join(f['fieldName'] for f in d.get('inputFields',[])))

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · references/operations.md (reported line 101)May include surrounding context.

Health Check

bash
curl -s http://localhost:18792/health
# {"healthy":true,"uptime":3600.5}     ← connected
# {"healthy":false,"uptime":3600.5}    ← disconnected

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The bridge starts an HTTP server on 0.0.0.0 and exposes powerful endpoints with no authentication or authorization checks. Any host that can reach the port can execute arbitrary discovered S2G nodes, refresh node inventory, reconnect the bridge, and query operational state, which is especially risky because the skill is explicitly designed to invoke workflow nodes that may include database queries, knowledge-base access, and custom actions.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 13)May include surrounding context.

md
- **AI integration** — OpenAI, Anthropic, Gemini, DeepSeek, Mistral, Groq with built-in prompt management
- **Vector storage** — Built-in vector database for RAG applications
- **Knowledge Base** — Graph-based knowledge store with semantic search, entities, and relations
- **Custom Node Designer** — Create your own nodes with JavaScript logic (sandboxed runtime)
- **HTTP triggers & webhooks** — Public endpoints that start workflows from any external service
- **Visual drag-and-drop editor** — Design workflows with real-time execution visualization
- **AI Workflow Generator** — Describe what you want in natural language, S2G builds the workflow

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README advertises execution of database queries, knowledge-base operations, AI models, file operations, webhooks, and cloud connectors, but does not prominently warn that these actions can transmit sensitive data off-host or modify external systems. In a skill whose purpose is to bridge an agent to 200+ remote workflow nodes, the lack of privacy and system-impact cautions increases the chance of unsafe deployment or overbroad agent use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The setup instructions tell users to start a local HTTP bridge on port 18792 and expose endpoints that execute arbitrary workflow nodes, but they do not warn that any local process on the machine may be able to call that API if it binds beyond a protected interface or lacks authentication. Because the bridge can trigger database, cloud, webhook, and custom-node actions, local malware or an untrusted user session could abuse it as a privilege-escalation or data-exfiltration channel.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · README.md (reported line 149)May include surrounding context.

bash
# Check connection
curl http://localhost:18792/health
# {"healthy":true,"uptime":42.5}

# List discovered nodes

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill explicitly enables network access and environment-dependent execution behavior but does not declare any scope restrictions such as allowed tools, destinations, or permission boundaries. In practice this creates an over-privileged integration surface where an agent could connect to arbitrary S2G endpoints, read secrets from environment variables, and expose local execution APIs without policy-level constraints.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The invocation description uses broad triggers such as 'manage S2G workflows' and 'interact with the S2G platform API,' which can match vague user requests and cause the skill to be selected in contexts involving sensitive automation or data access. Because the connected workflow may expose database, knowledge base, AI, or custom nodes, overbroad routing materially raises the risk of unintended execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The documentation describes bidirectional data forwarding from workflows to the agent and a local HTTP execution surface, but it does not provide clear warnings about sensitive data exposure, trust boundaries, or the consequences of executing remote-defined nodes. In this context, upstream workflow data may contain secrets or untrusted payloads, and local endpoints can become a control plane for triggering privileged actions.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

The skill instructs users to create persistent workflows and connect an OpenClaw bridge to any chosen tool nodes, establishing a durable session-like integration that can remain available across requests. This persistence increases risk because exposed nodes, forwarded data, and reconnection behavior can extend the lifetime of access beyond a single user-approved action.

Content

Scanner excerpt · SKILL.md (reported line 31)May include surrounding context.

md
### Setting Up the OpenClaw Node

1. **Open the S2G designer** at [s2g.run](https://s2g.run)
2. **Create or open a workflow**
3. **Add an OpenClaw node** from the AI category in the node palette
4. **Add tool nodes** — any nodes you want the agent to access (e.g., PasswordGenerator, HashGenerator, DateMath, SqlServer, Knowledge Base)
5. **Connect** the OpenClaw node to the tool nodes (the connection wiring tells S2G which nodes to expose)

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 114)May include surrounding context.

By name (recommended)

bash
curl -X POST http://localhost:18792/execute/PasswordGenerator \
  -H "Content-Type: application/json" \
  -d '{"params": {"length": "20", "mode": "strong"}}'

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill description broadens from a bridge for workflow node execution into full S2G platform administration, including workflow management, connections, logs, usage, and AI workflow generation. This scope expansion increases the chance that an agent will perform privileged administrative actions not clearly aligned with the user's request or the skill's original purpose.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation instructs readers to read an API key directly from a local credentials file and use it in commands, but provides no warning about secret handling, shell history exposure, terminal logging, or least-privilege use. In an agent skill context, examples like this normalize automated credential access and can lead downstream tooling or users to expose or misuse stored secrets.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The API reference documents a destructive DELETE workflow endpoint without emphasizing irreversibility, authorization expectations, confirmation requirements, or backup considerations. In a workflow automation platform, this can contribute to accidental or scripted destructive actions against production workflows.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/api.md (reported line 32)May include surrounding context.

Create a Workflow

bash
curl -X POST "$BASE/workflows" \
  -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{
    "name": "Webhook Processor",

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · references/api.md (reported line 39)May include surrounding context.

md
"description": "Listens for webhooks and responds",
    "nodes": [
      {
        "nodeType": "HttpListener",
        "name": "Webhook",
        "isTrigger": true,
        "configuration": "{\"path\": \"/hook\", \"method\": \"POST\"}"

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · references/api.md (reported line 66)May include surrounding context.

md
"description": "Listens for webhooks and responds",
    "nodes": [
      {
        "nodeType": "HttpListener",
        "name": "Webhook",
        "isTrigger": true,
        "configuration": "{\"path\": \"/hook\", \"method\": \"POST\"}"

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/api.md (reported line 85)May include surrounding context.

Add a Node (preserves existing IDs)

bash
curl -X POST "$BASE/workflows/$WF_ID/nodes" \
  -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"nodeType":"Custom_HashGenerator","name":"HashGenerator","x":320,"y":600}'
# Returns: { "id": "new-uuid", "name": "HashGenerator", ... }

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The knowledge base section exposes delete operations for entities and relations without warning about permanent data loss, integrity impact, or required safeguards. Because the knowledge base may hold organizational data, omission of deletion safety guidance increases the chance of harmful misuse or accidental destruction.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/api.md (reported line 203)May include surrounding context.

bash
# Search the knowledge base
curl -X POST http://localhost:18792/execute/Knowledge \
  -H "Content-Type: application/json" \
  -d '{"params": {"operation": "Search", "query": "customer billing issues"}}'

Static analysis

No suspicious patterns detected.