Back to skill

Security audit

SQ Memory

Security checks for vulnerabilities and agentic risk

Overview

This skill provides advertised persistent memory, but its current implementation and setup guidance can expose or over-share stored agent data if installed without careful review.

Install only after reviewing the data path. Do not store secrets, regulated data, or full transcripts unless you have explicit user consent and a retention plan. Prefer HTTPS endpoints, never send API keys over plain HTTP, bind self-hosted SQ to localhost or put it behind authenticated TLS, use separate backend scopes for separate users or agents, and pin the installer/Docker image you deploy.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (5)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
index.js:136
Finding
Namespace Restrictions and Prefix Filtering Can Be Bypassed<![CDATA[ ## Vulnerability Details **File Location**: `index.js:18-21`, `index.js:136-146` **Vulnerability Type**: Missing access-control enforcement and ineffective prefix filtering **Risk Level**: High ### Complete Code Snippet ```javascript _expandCoordinate(shorthand) { if (shorthand.match(/^\d+\.\d+\.\d+\/\d+\.\d+\.\d+\/\d+\.\d+\.\d+$/)) { return shorthand; // Already full format } ``` ```javascript async list_memories(prefix) { const fullPrefix = this._expandCoordinate(prefix); const encoded = encodeURIComponent(fullPrefix); try { const response = await this._request('GET', `/api/v2/toc?p=${encodeURIComponent(this.phext)}`); const lines = response.split('\n').filter(l => l.trim()); return lines; } catch (err) { if (err.message.includes('404')) { return []; // No memories found } throw err; } } ``` ### Technical Analysis The coordinate expansion function accepts a fully numeric 11-dimensional coordinate without applying the configured namespace. Consequently, namespace restrictions are not enforced for coordinates matching that format. The `list_memories` function also calculates `fullPrefix` and `encoded`, but never includes either value in the request or filters the response locally. It instead retrieves and returns the complete table of contents for the configured `phext`. These behaviors conflict with the documented claim that namespaces isolate agents. A namespace is being used as a naming convention rather than as an enforced authorization boundary. The risk is especially significant when multiple agents or users share the same backend storage scope or explicitly configure the same `phext`. ### Attack Path 1. Multiple agents are configured to use the same SQ endpoint and storage `phext`. 2. An untrusted agent or user invokes `list_memories("user/")`. 3. The function ignores the requested prefix and requests the complete table of contents. 4. Coordinates belonging to other workflows or agents wi ...[truncated 957 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat the namespace as an enforced access-control boundary rather than a coordinate convention. 2. Reject full coordinates that do not belong to the configured namespace. 3. Avoid accepting unqualified numeric full coordinates unless explicitly required and authorized. 4. Include the prefix in the table-of-contents API request when the backend supports it. 5. Independently filter returned coordinates against a canonical namespace and prefix before returning them. 6. Use separate authenticated backend scopes or `phext` values for separate users or agents. 7. Enforce tenant authorization on the SQ server because client-side validation alone is not a sufficient security boundary. 8. Add tests proving that: - A prefix query cannot return unrelated coordinates. - A caller cannot recall, overwrite, or delete another namespace. - Malformed and fully qualified coordinates fail closed. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
index.js:86
Finding
Sensitive Persistent Memory Is Transmitted in a GET Query String<![CDATA[ ## Vulnerability Details **File Location**: `index.js:86-99` **Vulnerability Type**: Sensitive data exposure through URL query parameters **Risk Level**: High ### Complete Code Snippet ```javascript async remember(coordinate, text) { const fullCoord = this._expandCoordinate(coordinate); const encoded = encodeURIComponent(fullCoord); const s = encodeURIComponent(text); await this._request('GET', `/api/v2/update?p=${encodeURIComponent(this.phext)}&c=${encoded}&s=${s}`); return { success: true, coordinate: fullCoord }; } ``` ### Technical Analysis The entire memory value is URL-encoded and placed in the `s` query parameter of a GET request. Encoding changes the representation but does not provide confidentiality. URLs and query strings are commonly retained by: - HTTP server access logs - Reverse proxies - Load balancers - Monitoring and application-performance systems - Debugging tools - Network security appliances - Error reports and diagnostic traces HTTPS protects the request in transit against passive network observers, but it does not prevent the destination server, reverse proxy, or monitoring infrastructure from recording the complete URL. The documented use cases include conversation history, identities, contacts, and user preferences, so the query parameter may contain sensitive personal information. Using GET for a state-changing operation also violates expected HTTP semantics and can interact unexpectedly with caches, crawlers, retries, and URL-length limits. ### Attack Path 1. An agent calls `remember` with sensitive content, such as a conversation summary or personal preference. 2. The Skill places the complete content in the request URL as the `s` query parameter. 3. A reverse proxy, SQ server, monitoring platform, or diagnostic component logs the URL. 4. A user with access to those logs searches or exports request records. 5. The encoded memory content is decoded and recovered without requiring access to the ...[truncated 485 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the state-changing GET request with `POST` or `PUT`. 2. Put memory content in the HTTP request body rather than the URL. 3. Use an appropriate content type, such as `application/json` or `text/plain`. 4. Configure server and reverse-proxy logging to redact sensitive parameters and authorization headers. 5. Disable caching for memory write operations. 6. Establish and enforce request-body size limits rather than relying on URL capacity. 7. Add automated tests confirming that stored text never appears in the request path or query string. 8. Document that callers should not store credentials or unnecessary sensitive data in persistent memory. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
index.js:38
Finding
Arbitrary Cleartext HTTP Endpoints Can Expose API Keys and Memory Data<![CDATA[ ## Vulnerability Details **File Location**: `index.js:10-14`, `index.js:38-58` **Vulnerability Type**: Cleartext transmission and unrestricted endpoint configuration **Risk Level**: High ### Complete Code Snippet ```javascript constructor(config) { this.endpoint = config.endpoint || 'http://localhost:1337'; this.apiKey = config.api_key; this.namespace = config.namespace || 'default-agent'; this.phext = config.phext || config.namespace || 'default'; } ``` ```javascript _request(method, path, body = null) { return new Promise((resolve, reject) => { const url = new URL(this.endpoint + path); const isHttps = url.protocol === 'https:'; const lib = isHttps ? https : http; const options = { hostname: url.hostname, port: url.port || (isHttps ? 443 : 80), path: url.pathname + url.search, method: method, headers: { 'Content-Type': 'text/plain', 'User-Agent': 'OpenClaw-SQ-Skill/1.0.1' } }; // Add API key if provided (SQ Cloud) if (this.apiKey) { options.headers['Authorization'] = `Bearer ${this.apiKey}`; } ``` ### Technical Analysis The Skill accepts an arbitrary configurable endpoint and automatically chooses the cleartext `http` module whenever the URL is not HTTPS. It then sends the configured API key as a bearer token and transmits memory operations to that endpoint. Plain HTTP is reasonable for a strictly loopback-only development service, but the implementation does not restrict HTTP endpoints to loopback addresses. It also does not require an explicit insecure-development option or warn when a bearer credential is about to be sent without transport encryption. A remote HTTP endpoint allows an on-path attacker to observe or modify requests and responses. Altered recall responses are particularly dangerous for an agent-memory system because corrupted content may influence future agent decisions. ### Attack Path 1. A user configures a remote endpoint ...[truncated 970 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require HTTPS for all non-loopback endpoints. 2. Permit HTTP only for validated loopback hosts such as `127.0.0.1`, `::1`, or an explicitly approved local Unix-socket design. 3. Reject unsupported URL schemes and URLs containing embedded credentials. 4. Refuse to transmit an API key over cleartext HTTP under all circumstances. 5. If insecure development mode is necessary, require an explicit opt-in flag and display a clear warning. 6. Validate endpoint configuration during initialization so failures occur before any data is transmitted. 7. Continue using standard TLS certificate and hostname verification; do not add options that disable verification. 8. Consider an administrator-controlled endpoint allowlist for managed deployments. 9. Add tests covering remote HTTP rejection, loopback exceptions, malformed URLs, and cleartext credential prevention. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SELF-HOSTED.md:37
Finding
Self-Hosting Instructions Can Expose an Unauthenticated Memory Service<![CDATA[ ## Vulnerability Details **File Location**: `SELF-HOSTED.md:37-44`, `SELF-HOSTED.md:88-101`, `SELF-HOSTED.md:241-249` **Vulnerability Type**: Insecure default service exposure **Risk Level**: High ### Complete Code Snippet ```bash # From source ./target/release/sq 1337 # Docker docker run -p 1337:1337 wbic16/sq 1337 ``` ```yaml skills: sq-memory: enabled: true endpoint: http://localhost:1337 # Your self-hosted endpoint api_key: "" # Leave empty for self-hosted namespace: my-assistant ``` ```text No API key needed - self-hosted SQ has no authentication by default. ``` ```bash # Test endpoint directly curl http://localhost:1337/api/v2/version # Check firewall sudo ufw status sudo ufw allow 1337/tcp ``` ### Technical Analysis The Docker command publishes port 1337 without specifying a host address. On typical Docker configurations, this binds the published port to all host interfaces. The documentation also states that self-hosted SQ has no authentication by default and later recommends opening TCP port 1337 in the firewall. Following these instructions together can expose the persistent-memory API to other network systems without authentication or transport encryption. Namespace values are identifiers and do not replace authentication or authorization. The risk arises from the deployment guidance rather than hidden runtime behavior. Nevertheless, it directly affects the confidentiality and integrity of the data managed by the Skill. ### Attack Path 1. A user launches SQ with `docker run -p 1337:1337 wbic16/sq 1337`. 2. The service becomes reachable through host network interfaces. 3. The user leaves authentication disabled as recommended for the default self-hosted configuration. 4. The user opens the firewall with `sudo ufw allow 1337/tcp`, or the network already permits access. 5. A remote attacker scans for or otherwise discovers TCP port 1337. 6. The attacker directly invokes SQ APIs to enumerate, ...[truncated 597 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Bind Docker publication to loopback by default: ```bash docker run -p 127.0.0.1:1337:1337 wbic16/sq 1337 ``` 2. Do not recommend opening port 1337 to a network while authentication is disabled. 3. For remote access, require an authenticated TLS reverse proxy or a private authenticated network. 4. Restrict firewall rules to specific trusted source addresses rather than all sources. 5. Clearly distinguish local development instructions from production deployment instructions. 6. Add prominent warnings that namespaces are not authentication boundaries. 7. Run SQ under a dedicated unprivileged account with access only to its required data directory. 8. Document secure Docker network configuration and avoid privileged containers or unnecessary host mounts. 9. Recommend testing external reachability after deployment and regularly reviewing listening interfaces. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:35
Finding
Primary Configuration Documentation Uses Credential Fields Ignored by the Runtime<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:35-47`, `index.js:10-14` **Vulnerability Type**: Security-sensitive configuration mismatch **Risk Level**: Medium ### Complete Code Snippet Documented configuration: ```yaml skills: sq-memory: enabled: true endpoint: http://localhost:1337 username: your-username password: your-api-key namespace: agent-name # Isolates this agent's memory ``` Runtime configuration handling: ```javascript constructor(config) { this.endpoint = config.endpoint || 'http://localhost:1337'; this.apiKey = config.api_key; this.namespace = config.namespace || 'default-agent'; this.phext = config.phext || config.namespace || 'default'; } ``` ### Technical Analysis The primary Skill documentation instructs users to configure `username` and `password`, but the implementation reads only `api_key`. Therefore, the documented API key is ignored and no Authorization header is generated from the supplied `password` field. Other project documents use `api_key`, demonstrating an internal documentation inconsistency. Because the runtime does not validate unknown fields or require credentials for hosted endpoints, this mistake does not fail during initialization. ### Attack Path 1. A user follows the configuration example in `SKILL.md`. 2. The API key is placed in the `password` field. 3. The runtime ignores `password` and leaves `this.apiKey` undefined. 4. Requests are sent without an Authorization header. 5. The result may be an authentication failure or, if the destination accepts anonymous operations, unintended unauthenticated access and storage under an incorrect security context. ### Impact Assessment The most likely impact is loss of availability because authenticated requests fail. If the configured server permits anonymous access, memories may be stored or retrieved without the intended account-level protection. This issue does not itself disclose the configured password through the run ...[truncated 101 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace `username` and `password` in `SKILL.md` with the runtime-supported `api_key` field. 2. Use one consistent configuration example across `README.md`, `SKILL.md`, `QUICKSTART.md`, and `SELF-HOSTED.md`. 3. Validate configuration keys during initialization and reject or warn about unsupported security-sensitive fields. 4. Require an API key for known hosted endpoints. 5. Fail closed when authentication is expected but no supported credential is configured. 6. Add tests confirming that documented configuration examples produce the expected Authorization header. 7. Avoid documenting HTTP endpoints with credentials; require HTTPS whenever an API key is present. ]]>
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
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (44)

Credential Access

High
Category
Privilege Escalation
Content
node_modules/
*.log
.env
.DS_Store
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Memory Manipulation

High
Category
Memory Poisoning
Content
Run it yourself (free) or use our hosted version (paid). Your agent gains four new abilities:
- `remember(key, value)` - Store something permanently
- `recall(key)` - Retrieve stored memory
- `forget(key)` - Delete memory
- `list_memories(prefix)` - Browse stored memories

## Quick Start
Confidence
80% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Memory Manipulation

High
Category
Memory Poisoning
Content
Run it yourself (free) or use our hosted version (paid). Your agent gains four new abilities:
- `remember(key, value)` - Store something permanently
- `recall(key)` - Retrieve stored memory
- `forget(key)` - Delete memory
- `list_memories(prefix)` - Browse stored memories

## Quick Start
Confidence
80% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Memory Manipulation

High
Category
Memory Poisoning
Content
Run it yourself (free) or use our hosted version (paid). Your agent gains four new abilities:
- `remember(key, value)` - Store something permanently
- `recall(key)` - Retrieve stored memory
- `forget(key)` - Delete memory
- `list_memories(prefix)` - Browse stored memories

## Quick Start
Confidence
80% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Missing User Warnings

High
Confidence
98% confidence
Finding
This code stores full conversation turns, including raw user and assistant messages, in persistent memory without any warning or consent mechanism. Full transcripts are more sensitive than summaries because they can capture credentials, health/financial details, or other personal data, increasing the risk of privacy violations, unauthorized reuse, and over-collection.

Missing User Warnings

High
Confidence
96% confidence
Finding
The comments explicitly promote using stored conversations for training data generation, but the example provides no consent, notice, or data governance safeguards. Reusing persistent conversation history for training materially increases privacy and compliance risk because users may not expect their chats to be repurposed beyond the immediate service interaction.

Memory Manipulation

High
Category
Memory Poisoning
Content
},
    {
      "name": "forget",
      "description": "Delete memory at a coordinate",
      "parameters": {
        "coordinate": {
          "type": "string",
Confidence
91% confidence
Finding
The skill exposes a deletion capability for persistent memory with no visible safeguards such as confirmation, scope restriction, soft delete, or authorization checks. In agent workflows, this enables prompt-induced or accidental erasure of long-term memory, potentially causing loss of critical state, policy context, or user data.

Rp1

Medium
Category
MCP Rug Pull
Confidence
97% confidence
Finding
The changelog instructs users to install or invoke a package via `npx clawhub` without pinning a specific version. Unpinned `npx` execution can fetch and run the latest published package at install time, which creates a supply-chain risk if a malicious or compromised version is released or if users expect reproducible behavior. In this skill context, the risk is elevated because the text is documentation that users may copy-paste directly into a shell.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
The quickstart instructs users to run `npx clawhub install sq-memory` without pinning a specific version of the package or installer. This creates a supply-chain risk: a compromised or newly published package/version could execute unexpected code during installation, and documentation-driven execution makes that risk more actionable.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly tells the agent to permanently remember user preferences, identity details, and conversation summaries, but it provides no consent, retention, minimization, or sensitive-data handling guidance. In a memory skill context this is especially risky because the feature is designed to persist data across sessions, increasing privacy exposure and the chance of storing personal or confidential information indefinitely.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The README encourages storing persistent user preferences, contact information, and conversation history, but it does not warn about privacy, retention, consent, access controls, or deletion policies. In a memory skill, this omission is security-relevant because users and operators may store sensitive personal data indefinitely or in a hosted service without understanding the risks.

Rp1

Medium
Category
MCP Rug Pull
Confidence
97% confidence
Finding
The documentation tells users to pull a Docker image without pinning a version tag or immutable digest. This creates a supply-chain risk because a future image change, tag retargeting, or registry compromise could cause users to run unexpected code when following the guide.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding
The `docker run -p 1337:1337 wbic16/sq 1337` example runs an unpinned image reference, which means execution behavior depends on whatever image is currently served under that name. In setup documentation, this is dangerous because users may repeatedly deploy a mutable image with no integrity guarantee.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Systemd service (Linux):**
```bash
sudo nano /etc/systemd/system/sq.service
```

```ini
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Systemd service (Linux):**
```bash
sudo nano /etc/systemd/system/sq.service
```

```ini
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Systemd service (Linux):**
```bash
sudo nano /etc/systemd/system/sq.service
```

```ini
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Systemd service (Linux):**
```bash
sudo nano /etc/systemd/system/sq.service
```

```ini
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Systemd service (Linux):**
```bash
sudo nano /etc/systemd/system/sq.service
```

```ini
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Systemd service (Linux):**
```bash
sudo nano /etc/systemd/system/sq.service
```

```ini
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Systemd service (Linux):**
```bash
sudo nano /etc/systemd/system/sq.service
```

```ini
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Systemd service (Linux):**
```bash
sudo nano /etc/systemd/system/sq.service
```

```ini
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Systemd service (Linux):**
```bash
sudo nano /etc/systemd/system/sq.service
```

```ini
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Systemd service (Linux):**
```bash
sudo nano /etc/systemd/system/sq.service
```

```ini
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Systemd service (Linux):**
```bash
sudo nano /etc/systemd/system/sq.service
```

```ini
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Static analysis

Detected: suspicious.prompt_injection_instructions

Prompt-injection style instruction pattern detected.

Warn
Code
suspicious.prompt_injection_instructions
Location
QUICKSTART.md:112