Back to skill

Security audit

Rag Memory

Security checks for vulnerabilities and agentic risk

Overview

This memory-search skill is mostly purpose-aligned, but it installs broad automatic prompt injection and advertises privileged background services that users should review carefully.

Review this before installing. Use it only if you trust your Qdrant and embedding endpoints with memory contents, disable auto_inject unless you specifically want memory inserted into every prompt, prefer HTTPS or loopback-only endpoints, avoid sudo systemd deployment unless you have reviewed the unit files, and run sync under a narrowly scoped account.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
Findings (5)

T01 · Skill Instruction Hijacking

Error
Location
plugin/index.js:155
Finding

Untrusted persistent content is automatically injected into prompt context

Content
View full analysis
{ const lastUser = [...ctx.messages].reverse().find((m) => m.role === "user"); if (!lastUser?.content) return {}; const query = typeof lastUser.content === "string" ? lastUser.content : lastUser.content.map((b) => b.text ?? "").join(" "); if (query.trim().length < (cfg.auto_inject_min_query_len ?? 20)) return {}; try { const vector = await embed(cfg, query.slice(0, 500)); const results = await searchQdrant(cfg, cols, "all", vector, cfg.top_k); if (!results.length) return {}; return { prependContext: formatResults(results, query, cfg.auto_inject_max_result_chars ?? 500) }; } catch { return {}; } }, { name: "rag-memory-inject", priority: 100 }); } ``` The indexed text is stored directly as a Qdrant payload in `sync_to_qdrant.py:213-229`: ```python for j, (text, vec) in enumerate(zip(batch, vectors)): point_id = stable_id(source_id, i + j, text) points.append( PointStruct( id=point_id, vector=vec, payload={ "text": text, "chunk_index": i + j, **metadata, }, ) ) ``` ### Technical Analysis The plugin retrieves text from Qdrant and prepends it directly to the model's prompt context. The configuration schema enables `auto_inject` by default. Indexed Markdown and PostgreSQL content is not treated as untrusted data and is not neutralized before injection. The synchronization script's `strip_boilerplate()` function only removes session labels. It does not identify or neutralize embedded instructions, tool-use requests, role impersonation, or attempts to override system constraints. This creates a pers ...[truncated 1595 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
plugin/index.js:9
Finding

Configurable plaintext HTTP endpoints can expose queries, memory content, and API keys

Content
View full analysis
{ const parsed = new URL(url); const lib = parsed.protocol === "https:" ? https : http; const payload = JSON.stringify(body); const req = lib.request( { hostname: parsed.hostname, port: parsed.port || (parsed.protocol === "https:" ? 443 : 80), path: parsed.pathname + parsed.search, method: "POST", headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(payload), ...extraHeaders, }, }, (res) => { let data = ""; res.on("data", (c) => (data += c)); res.on("end", () => { try { resolve(JSON.parse(data)); } catch (e) { reject(new Error(`JSON parse failed: ${data.slice(0, 200)}`)); } }); }, ); req.on("error", reject); req.write(payload); req.end(); }); } async function embed(cfg, text) { const headers = {}; if (cfg.embed_api_key) headers["Authorization"] = `Bearer ${cfg.embed_api_key}`; const res = await post( `${cfg.embed_base_url}/v1/embeddings`, { model: cfg.embed_model, input: [text] }, headers, ); if (!res.data?.[0]?.embedding) throw new Error("embed: no embedding in response"); return res.data[0].embedding; } ``` The synchronization path has the same issue in `sync_to_qdrant.py:112-124`: ```python def embed_batch(texts: list[str]) -> list[list[float]]: """Call OpenAI-compatible /v1/embeddings endpoint for a batch of texts.""" headers = {"Content-Type": "application/json"} if EMBED_API_KEY: headers["Authorization"] = f"Bearer {EMBED_API_KEY}" with httpx.Client(timeout=60) as client: r ...[truncated 2196 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
sync_to_qdrant.py:385
Finding

Single-file synchronization can exfiltrate any readable local file

Content
View full analysis
int: content = strip_boilerplate(path.read_text(encoding="utf-8", errors="replace")) chunks = chunk_text(content, source_hint=str(path)) meta = { "source": source_type, "source_id": str(path), "file_path": str(path), "file_name": path.name, "indexed_at": datetime.now(timezone.utc).isoformat(), **(extra_meta or {}), } count = upsert_chunks(client, collection, chunks, meta) ``` ### Technical Analysis The command-line help states that `--file` synchronizes a Markdown file, but no extension, file type, ownership, symlink, or allowed-directory check enforces that contract. `Path.resolve()` canonicalizes the path but does not ensure it remains under `MEMORY_DIR`. Consequently, any regular file readable by the account running the script can be passed to `sync_markdown_file()`. Its content is chunked, sent to the embedding endpoint, and then included as plaintext payload m ...[truncated 1269 chars]
Remediation
View remediation

T06 · System Persistence

Warning
Location
systemd/deploy.sh:1
Finding

Deployment script installs system-wide persistent services with root privileges

Content
View full analysis
"/etc/systemd/system/${unit}" echo " installed /etc/systemd/system/${unit}" done systemctl daemon-reload systemctl enable --now sysclaw-rag-sync.timer sysclaw-rag-watch.path echo "Done. Timer and path watcher enabled for user: ${TARGET_USER}" ``` ### Technical Analysis Scheduled and file-triggered synchronization is consistent with the declared automatic-sync functionality. However, installing units under `/etc/systemd/system` and requiring `sudo` creates system-wide persistence when user-level systemd services would ordinarily be sufficient. The script copies unit definitions from the Skill directory into a root-managed startup location and immediately enables a timer and path watcher. If the source directory or unit definitions are modified before deployment, attacker-controlled commands could become persistent. The audited package does not contain the four unit files referenced by the script. Because `set -e` is active, the current package will stop at the first failed `sed` operation and will not reach `systemctl enable`. Thus, the persistence mechanism is advertised and implemented by the script, but deployment is presently incomplete and broken without additional files. ### Attack Path 1. The mis ...[truncated 1118 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unbounded dependencies and npm lifecycle scripts increase supply-chain execution risk

Content
View full analysis
=1.9.0 psycopg2-binary>=2.9.9 httpx>=0.27.0 python-dotenv>=1.0.0 ``` The plugin dependency is also specified using a compatible-version range in `plugin/package.json:16-18`: ```json "dependencies": { "openclaw": "^2026.4.2" } ``` The resolved package executes an installation lifecycle script, as shown in `plugin/package-lock.json:5594-5599`: ```json "node_modules/openclaw": { "version": "2026.4.2", "resolved": "https://registry.npmjs.org/openclaw/-/openclaw-2026.4.2.tgz", "integrity": "sha512-vtPmvWeGoLdtE17mgznxoP2Qi/lKC5yEwPv+BE5CmS15wJ4WbcbYUa01zI7EkyIq8+Ym84Xc2q6ToRq6UF7gPg==", "hasInstallScript": true, "license": "MIT", ``` ### Technical Analysis The Python requirements use minimum versions without upper bounds, exact pins, or package hashes. A future installation can therefore resolve to package versions that were not part of this audit. The npm lockfile pins the currently resolved OpenClaw package to the official npm registry and includes an integrity hash; no suspicious package source was identified. Nevertheless, the direct dependency range permits compatible future versions when the lockfile is regenerated or ignored, and the resolved package declares an installation script. npm lifecycle scripts execute code during installation with the installer's privileges. The plugin imports only an OpenClaw SDK entry point but depends on the complete OpenClaw package and its extensive transitive dependency tree, increasing the reviewed and trusted supply-chain surface. ### Attack Path 1. A user installs Python dependencies without a hash-locked constraints file, or regenerates/ignores the npm lockfile. 2. The package manager resolves a newer compatible dependency version. 3. An upstream package, maintainer account, or lifecyc ...[truncated 876 chars]
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (42)

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The skill is presented as a memory-search/RAG capability, but the documentation also includes system-level deployment steps that install and restart systemd units under sudo. Combining a seemingly narrow data-retrieval skill with privileged persistence and background services materially raises risk because operators may not expect host-level changes.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill is presented as a memory-search/RAG capability, but the documentation also includes system-level deployment steps that install and restart systemd units under sudo. Combining a seemingly narrow data-retrieval skill with privileged persistence and background services materially raises risk because operators may not expect host-level changes.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill is presented as a memory-search/RAG capability, but the documentation also includes system-level deployment steps that install and restart systemd units under sudo. Combining a seemingly narrow data-retrieval skill with privileged persistence and background services materially raises risk because operators may not expect host-level changes.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill is presented as a memory-search/RAG capability, but the documentation also includes system-level deployment steps that install and restart systemd units under sudo. Combining a seemingly narrow data-retrieval skill with privileged persistence and background services materially raises risk because operators may not expect host-level changes.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill is presented as a memory-search/RAG capability, but the documentation also includes system-level deployment steps that install and restart systemd units under sudo. Combining a seemingly narrow data-retrieval skill with privileged persistence and background services materially raises risk because operators may not expect host-level changes.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| `requirements.txt` | Python deps for sync script |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| `plugin/index.js` | OpenClaw plugin — registers `vector_search` tool and `before_prompt_build` hook |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| `plugin/index.js` | OpenClaw plugin — registers `vector_search` tool and `before_prompt_build` hook |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| `plugin/package.json` | Plugin manifest |

Chaining Abuse

High
Category
Tool Misuse
Confidence
91% confidence
Finding

The pipeline from sed into sudo tee is a chaining pattern that converts repository-controlled text into privileged system configuration in a single command. This reduces transparency, bypasses safer review checkpoints, and can be leveraged to establish malicious or unsafe systemd services with persistence.

Content

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

bash
sudo sed "s/User=openclaw/User=youruser/g" ~/.openclaw/skills/rag-memory/systemd/*.service \
  | sudo tee /etc/systemd/system/sysclaw-rag-{sync,watch}.service > /dev/null
sudo cp ~/.openclaw/skills/rag-memory/systemd/sysclaw-rag-sync.timer /etc/systemd/system/
sudo cp ~/.openclaw/skills/rag-memory/systemd/sysclaw-rag-watch.path /etc/systemd/system/
sudo systemctl daemon-reload

Known Vulnerable Dependency: @mariozechner/pi-coding-agent==0.64.0 — 3 advisory(ies): CVE-2026-54326 (Pi Agent: Potential XSS in HTML session exports via Markdown URL sanitization by); CVE-2026-54328 (Pi Agent: Predictable temporary extension install paths allow local privilege es); CVE-2026-54327 (Pi Agent: Race condition in Pi auth.json writes could expose stored credentials)

High
Category
Supply Chain
Confidence
95% confidence
Finding

@mariozechner/pi-coding-agent 0.64.0 has multiple high-severity advisories affecting XSS in exported HTML, predictable temp paths, and credential exposure races. These are real vulnerabilities in a transitive dependency, and the skill context increases concern because agent tooling often handles workspace files, auth material, and user-generated markdown. A memory/RAG skill may process untrusted markdown and run in environments where local credential or temp-path abuse is meaningful.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: axios==1.14.0 — 16 advisory(ies): CVE-2026-44494 (axios Vulnerable to Full Man-in-the-Middle via Prototype Pollution Gadget in `co); CVE-2026-44495 (axios Vulnerable to Credential Theft and Response Hijacking via Prototype Pollut); CVE-2025-62718 (Axios has a NO_PROXY Hostname Normalization Bypass that Leads to SSRF) +13 more

High
Category
Supply Chain
Confidence
97% confidence
Finding

axios 1.14.0 is flagged with numerous advisories, including SSRF-related NO_PROXY bypasses and prototype-pollution-linked MITM/credential theft scenarios. This is a real vulnerability signal, especially in an agent skill that likely performs outbound network access for embeddings, vector DB sync, or remote content ingestion. In a RAG/memory context, SSRF or proxy bypass can expose internal services, metadata endpoints, or secrets during sync/search workflows.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: basic-ftp==5.2.0 — 4 advisory(ies): GHSA-6v7q-wjvx-w8wg (basic-ftp: Incomplete CRLF Injection Protection Allows Arbitrary FTP Command Exe); CVE-2026-39983 (basic-ftp has FTP Command Injection via CRLF); CVE-2026-41324 (basic-ftp vulnerable to denial of service via unbounded memory consumption in Cl) +1 more

High
Category
Supply Chain
Confidence
93% confidence
Finding

basic-ftp 5.2.0 has known FTP command injection and denial-of-service issues. This is a true vulnerable dependency, and if any part of the surrounding platform supports remote fetch/import over FTP, attacker-controlled endpoints or paths could trigger command injection semantics or resource exhaustion. For a memory-sync skill that may ingest external content, unsafe network fetch dependencies materially increase attack surface.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: brace-expansion==5.0.5 — 4 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-45149 (brace-expansion: Large numeric range defeats documented `max` DoS protection); CVE-2026-14257 (brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro) +1 more

High
Category
Supply Chain
Confidence
92% confidence
Finding

brace-expansion 5.0.5 has multiple denial-of-service advisories related to pathological expansion patterns and memory exhaustion. This is a genuine supply-chain issue, particularly concerning in agent ecosystems that process globs, file patterns, or user-influenced path expressions during sync/indexing. In a RAG-memory skill that auto-syncs markdown files, attacker-controlled filenames or glob patterns could potentially trigger expensive expansion and degrade availability.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill declares broad capabilities through required environment variables, file access, and outbound network usage, but does not define an explicit permission or allowed-tools scope. That makes the trust boundary unclear and increases the chance the runtime grants more access than users expect for a memory-search skill.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
88% confidence
Finding

The skill documentation instructs operators to run a bundled deploy script with sudo, which grants root execution to repository-controlled content. If the script is modified maliciously or reviewed insufficiently, it could make arbitrary system changes with full privileges.

Content

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

Edit files in systemd/ (source of truth), then deploy using the included script — it substitutes the correct username automatically:

bash
sudo ~/.openclaw/skills/rag-memory/systemd/deploy.sh

Or manually, replacing youruser with the local OpenClaw user:

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
85% confidence
Finding

The manual deployment sequence performs privileged writes into /etc/systemd/system using sudo, expanding the skill's effect from user-space retrieval to host configuration changes. This is risky because it creates durable system-level behavior and can be abused if service definitions are unsafe or tampered with.

Content

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

Or manually, replacing youruser with the local OpenClaw user:

bash
sudo sed "s/User=openclaw/User=youruser/g" ~/.openclaw/skills/rag-memory/systemd/*.service \
  | sudo tee /etc/systemd/system/sysclaw-rag-{sync,watch}.service > /dev/null
sudo cp ~/.openclaw/skills/rag-memory/systemd/sysclaw-rag-sync.timer /etc/systemd/system/
sudo cp ~/.openclaw/skills/rag-memory/systemd/sysclaw-rag-watch.path /etc/systemd/system/

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
90% confidence
Finding

This command pipes transformed service definitions directly into sudo tee targeting /etc/systemd/system, creating privileged configuration from repository content in one step. That pattern is dangerous because it reduces review opportunities and can install altered or malicious service content with persistence on the host.

Content

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

bash
sudo sed "s/User=openclaw/User=youruser/g" ~/.openclaw/skills/rag-memory/systemd/*.service \
  | sudo tee /etc/systemd/system/sysclaw-rag-{sync,watch}.service > /dev/null
sudo cp ~/.openclaw/skills/rag-memory/systemd/sysclaw-rag-sync.timer /etc/systemd/system/
sudo cp ~/.openclaw/skills/rag-memory/systemd/sysclaw-rag-watch.path /etc/systemd/system/
sudo systemctl daemon-reload

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
84% confidence
Finding

Copying timer units into /etc/systemd/system with sudo installs persistent privileged scheduling behavior tied to the skill. While not inherently malicious, it increases blast radius and can be abused to execute future actions automatically under system control.

Content

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

bash
sudo sed "s/User=openclaw/User=youruser/g" ~/.openclaw/skills/rag-memory/systemd/*.service \
  | sudo tee /etc/systemd/system/sysclaw-rag-{sync,watch}.service > /dev/null
sudo cp ~/.openclaw/skills/rag-memory/systemd/sysclaw-rag-sync.timer /etc/systemd/system/
sudo cp ~/.openclaw/skills/rag-memory/systemd/sysclaw-rag-watch.path /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl restart sysclaw-rag-sync.timer sysclaw-rag-watch.path

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
84% confidence
Finding

Copying path watcher units into /etc/systemd/system with sudo creates automatic host-level monitoring and triggers. For a skill advertised primarily as vector search, that is a meaningful privilege expansion and persistence mechanism.

Content

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

sudo sed "s/User=openclaw/User=youruser/g" ~/.openclaw/skills/rag-memory/systemd/*.service
| sudo tee /etc/systemd/system/sysclaw-rag-{sync,watch}.service > /dev/null sudo cp ~/.openclaw/skills/rag-memory/systemd/sysclaw-rag-sync.timer /etc/systemd/system/ sudo cp ~/.openclaw/skills/rag-memory/systemd/sysclaw-rag-watch.path /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl restart sysclaw-rag-sync.timer sysclaw-rag-watch.path

text

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
82% confidence
Finding

Running systemctl daemon-reload under sudo activates newly installed unit definitions and advances the privileged installation flow. This contributes to persistence and makes any prior unsafe unit-file content immediately actionable.

Content

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

| sudo tee /etc/systemd/system/sysclaw-rag-{sync,watch}.service > /dev/null sudo cp ~/.openclaw/skills/rag-memory/systemd/sysclaw-rag-sync.timer /etc/systemd/system/ sudo cp ~/.openclaw/skills/rag-memory/systemd/sysclaw-rag-watch.path /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl restart sysclaw-rag-sync.timer sysclaw-rag-watch.path

text

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
85% confidence
Finding

Restarting the timer and path watcher under sudo enables the newly installed background services immediately. That turns documentation into an operational pathway for privileged persistence and automatic execution on the host.

Content

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

sudo cp ~/.openclaw/skills/rag-memory/systemd/sysclaw-rag-sync.timer /etc/systemd/system/ sudo cp ~/.openclaw/skills/rag-memory/systemd/sysclaw-rag-watch.path /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl restart sysclaw-rag-sync.timer sysclaw-rag-watch.path

text

---

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

When auto_inject is enabled, the plugin automatically sends the user's latest prompt text to the configured embedding endpoint and then uses the resulting vector to query Qdrant, without any user-facing notice or consent step. Because prompts may contain sensitive data and the endpoint is configurable, this creates a real privacy and data-governance risk, especially if the embedding service is remote or third-party.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest description states that relevant context is auto-injected before each response, which signals broad automatic activation rather than a clearly bounded, user-initiated trigger. In a memory/RAG plugin, this can cause unintended retrieval and disclosure of stored memory into unrelated conversations, especially if the agent invokes the capability implicitly.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The description explicitly promises automatic behavior before every response without indicating user consent, and the config also defaults auto_inject to true. For a vector memory skill that searches Qdrant-backed stored content, this increases the risk of privacy leakage, prompt contamination, and unintended exposure of sensitive memory records to the model output path.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/monitor_vector_search.js:26