Back to skill

Security audit

pg-memory

Security checks for vulnerabilities and agentic risk

Overview

This skill is a legitimate PostgreSQL memory system, but it handles sensitive cross-session agent history with several overbroad and unsafe database, credential, and restore behaviors that require review before installation.

Install only if you are comfortable administering PostgreSQL for sensitive agent memory. Use a dedicated least-privilege database role, restrict network access to trusted hosts or a VPN, require TLS for remote PostgreSQL, chmod credential files to 600, avoid the --reset/restore --drop paths unless you have verified backups, and do not enable shared multi-agent use until session scoping is fixed and tested.

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/memory_handler.py:211
Finding
Cross-Session Disclosure of Stored Agent Memory<![CDATA[ ## Vulnerability Details **File Location**: `scripts/memory_handler.py:211-220` **Vulnerability Type**: Missing session-level authorization and query scoping **Risk Level**: High ### Vulnerable Code ```python # If session_key provided, get that session if session_key: # Get recent exchanges from this session exchanges = mem.search_exchanges('', days=1, limit=20) # Filter to this session (will need session_id lookup) result['recent_exchanges'] = exchanges else: # Get recent exchanges across all sessions exchanges = mem.search_exchanges('', days=1, limit=10) result['recent_exchanges'] = exchanges ``` ### Technical Analysis The handler accepts a `session_key`, but it never uses that value as a database query constraint. The comment explicitly acknowledges that session filtering is still required. Instead, `search_exchanges()` retrieves recent exchanges across the accessible database. This violates tenant and session isolation in the documented multi-agent deployment model. Because raw exchanges may contain user messages, assistant reasoning, complete tool parameters, tool results, and user or channel metadata, an unscoped query can expose significantly more than ordinary memory summaries. The defect is an authorization failure rather than merely a relevance bug: possession of one valid session key does not limit the caller to that session's data. ### Attack Path 1. Multiple agents, users, or channels store exchanges in the shared PostgreSQL database. 2. An agent invokes the post-compaction handler with its own session key. 3. The handler enters the `if session_key` branch but performs an unscoped search for recent exchanges. 4. Exchanges belonging to unrelated sessions are returned in `recent_exchanges`. 5. The unrelated data is injected into the requesting agent's restored context or exposed through the command's JSON output. 6. Any credentials, private content, internal reasoning, or tool output in those exchanges bec ...[truncated 620 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Resolve the supplied `session_key` to an authorized database `session_id` and include it directly in the SQL query. 2. Scope every read by all applicable ownership attributes, such as `session_id`, `agent_id`, `instance_id`, provider, and channel. 3. Do not fetch globally and filter in application memory; enforce isolation in PostgreSQL. 4. Verify that the caller is authorized to access the requested session before returning any data. 5. Consider PostgreSQL Row-Level Security for shared deployments so accidental unscoped queries cannot cross tenant boundaries. 6. Return an error when a requested session does not exist or is not owned by the caller. 7. Add tests with multiple agents and sessions to prove that each caller can retrieve only its own exchanges. 8. Minimize returned fields and exclude assistant reasoning and complete tool payloads unless explicitly required. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/pg_memory.py:2459
Finding
Shell Command Injection in Database Backup and Restore<![CDATA[ ## Vulnerability Details **File Location**: `scripts/pg_memory.py:2459-2460` and `scripts/pg_memory.py:2539-2543` **Vulnerability Type**: OS command injection through `shell=True` **Risk Level**: High ### Vulnerable Code ```python # Add compression if requested if compress: cmd_str = " ".join(cmd) + f" | gzip > {backup_path}" result = subprocess.run(cmd_str, shell=True, capture_output=True, text=True) else: # Run pg_dump and redirect to file with open(backup_path, 'w') as f: result = subprocess.run(cmd, stdout=f, stderr=subprocess.PIPE, text=True) ``` ```python if is_compressed: cmd_str = f"gunzip -c {backup_path} | psql -h {db_host} -p {db_port} -U {db_user} -d {db_name}" result = subprocess.run(cmd_str, shell=True, capture_output=True, text=True) else: cmd = [ "psql", "-h", db_host, "-p", str(db_port), "-U", db_user, "-d", db_name, "-f", str(backup_path) ] result = subprocess.run(cmd, capture_output=True, text=True) ``` ### Technical Analysis The compressed backup and restore branches construct shell command strings by interpolating path and database configuration values, then execute those strings using `shell=True`. Values such as `backup_path`, `db_host`, `db_user`, and `db_name` are not safely shell-quoted. If an attacker can influence an output directory, backup filename, restore path, environment variable, or configuration file, shell metacharacters can terminate or extend the intended command. The safe argument-array behavior used in the uncompressed branches is lost when the code invokes a shell to implement pipelines and redirection. ### Attack Path 1. An attacker gains influence over `output_dir`, `backup_file`, or a PostgreSQL setting loaded from environment or `config.env`. 2. The attacker supplies a value containing shell syntax. 3. A user or automated process invokes compressed `backup()` or restores a `.gz` backup. 4. The value is inter ...[truncated 727 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove every use of `shell=True`. 2. For backups, start `pg_dump` with an argument array and stream its stdout through Python's `gzip` module into a file opened by the application. 3. For restores, read the gzip file with `gzip.open()` and pass the decompressed stream to a `psql` process created with an argument array. 4. Alternatively, connect two `Popen` processes using explicit `stdin` and `stdout` pipes without invoking a shell. 5. Canonicalize backup and restore paths and restrict them to an approved backup directory. 6. Validate database names, usernames, ports, and hosts before use. 7. Create backup files using restrictive permissions and reject symbolic links where an attacker could manipulate the backup directory. 8. Add regression tests using paths containing spaces and shell metacharacters, verifying that no additional process is executed. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
client-setup.sh:184
Finding
Plaintext Database Credential File Created Without Enforced Restrictive Permissions<![CDATA[ ## Vulnerability Details **File Location**: `client-setup.sh:184-203` **Vulnerability Type**: Insecure storage of database credentials **Risk Level**: Medium ### Vulnerable Code ```bash # Create config.env cat > "$CONFIG_DIR/config.env" << EOF # pg-memory Configuration # Generated: $(date -Iseconds) # Database Connection PG_MEMORY_HOST=$DB_HOST PG_MEMORY_PORT=$DB_PORT PG_MEMORY_DB=$DB_NAME PG_MEMORY_USER=$DB_USER PG_MEMORY_PASSWORD=$DB_PASSWORD # Agent Identity OPENCLAW_NAME=$AGENT_NAME # Performance PG_MEMORY_POOL_MIN=2 PG_MEMORY_POOL_MAX=10 PG_MEMORY_TIMEOUT=30 EOF echo "✓ Configuration saved to: $CONFIG_DIR/config.env" ``` ### Technical Analysis The setup script stores the database password in plaintext but does not set a restrictive umask before creating the file and does not apply mode `0600` afterward. The resulting permissions depend on the invoking user's environment. With a common `022` umask, the file may be readable by other local accounts. The documentation recommends `chmod 600`, but the installer does not enforce that control. The unquoted here-document also performs shell expansion while generating the file. Passwords containing expansion-sensitive characters may be changed or handled unexpectedly. ### Attack Path 1. A user runs `client-setup.sh` and enters credentials for the shared memory database. 2. The script writes the password to `config.env`. 3. The file inherits permissions from the current umask. 4. Another local user or compromised process reads the configuration file. 5. The attacker uses the recovered credentials to connect to the PostgreSQL server. 6. The attacker reads, modifies, or deletes memory records within the database role's permissions. ### Impact Assessment Exposure of this credential can grant access to a database containing complete conversations, tool parameters and results, user identifiers, observations, and potentially assistant reasoning. In a shared multi-agent installation, one stolen client ...[truncated 224 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Execute `umask 077` before creating the configuration directory and file. 2. Explicitly run `chmod 600 "$CONFIG_DIR/config.env"` after creation and verify the resulting mode. 3. Create the directory with mode `0700`. 4. Prefer an operating-system credential manager, PostgreSQL passfile with enforced permissions, or another dedicated secret store. 5. Avoid placing the password in generated shell source files. 6. Safely serialize values rather than inserting them through an unquoted here-document. 7. Fail setup if secure permissions cannot be applied. 8. Document credential rotation and immediately rotate any password previously stored in a broadly readable file. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
server-setup.sh:152
Finding
SQL Injection During Privileged Database Setup and Excessive CREATEDB Grant<![CDATA[ ## Vulnerability Details **File Location**: `server-setup.sh:152-153` **Vulnerability Type**: Unsafe SQL construction and violation of least privilege **Risk Level**: Medium ### Vulnerable Code ```bash $PSQL -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';" $PSQL -c "ALTER USER $DB_USER CREATEDB;" ``` ### Technical Analysis The database username and password are interpolated directly into SQL executed through a privileged PostgreSQL connection. A quote in a supplied value can alter the SQL structure. Shell quoting does not provide PostgreSQL identifier or literal escaping. The script then grants `CREATEDB` to the application account. Normal pg-memory operations require access to the designated memory database, not permission to create arbitrary databases. This privilege exceeds the minimum necessary for the declared functionality. The combination is particularly dangerous because setup commands are executed as the PostgreSQL administrative account on Linux. ### Attack Path 1. An attacker or malicious automation influences `PG_MEMORY_USER` or the password supplied during setup. 2. The crafted value is inserted into the `CREATE USER` statement without PostgreSQL-safe quoting. 3. The setup script invokes `psql` as the PostgreSQL administrator. 4. PostgreSQL parses the altered statement and may execute injected SQL with administrative privileges. 5. Even without injection, the resulting application account receives `CREATEDB`. 6. If that account is later compromised, the attacker can create databases beyond the memory application's needs. ### Impact Assessment SQL injection at setup time may permit creation or alteration of roles, changes to database ownership or permissions, or destructive administrative operations, subject to PostgreSQL statement parsing and server configuration. The unconditional `CREATEDB` grant expands the impact of stolen application credentials. It does not automatically confer operating-system root access, but it g ...[truncated 84 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate database and role names against a strict identifier policy before use. 2. Pass values through `psql` variables and apply PostgreSQL identifier and literal quoting rather than concatenating SQL strings. 3. Consider creating the role through a reviewed SQL script whose variables are safely bound. 4. Remove `ALTER USER ... CREATEDB`; grant only `CONNECT`, schema usage, and the specific table and sequence privileges required by pg-memory. 5. Use separate migration and runtime roles. The migration role may create schema objects, while the runtime role should only read and write application tables. 6. Avoid executing setup with superuser privileges after initial role and extension provisioning. 7. Add tests for usernames and passwords containing quotes, whitespace, and special characters. 8. Audit existing deployments and revoke `CREATEDB` from application roles that do not require it. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
server-setup.sh:205
Finding
Unsafe Remote PostgreSQL Exposure Guidance Without Enforced TLS Verification<![CDATA[ ## Vulnerability Details **File Location**: `server-setup.sh:205-214` and `scripts/pg_memory.py:384-396` **Vulnerability Type**: Insecure network configuration for sensitive data **Risk Level**: Medium ### Vulnerable Code ```bash echo "To allow remote connections:" echo "" echo "1. Edit postgresql.conf:" echo " listen_addresses = '*'" echo "" echo "2. Edit pg_hba.conf and add:" echo " host all all 0.0.0.0/0 md5" echo "" echo "3. Restart PostgreSQL:" ``` The client connection parameters do not require certificate-validated TLS: ```python conn_params = { 'dbname': self.config.db_name, 'user': self.config.db_user, 'host': self.config.db_host, 'port': self.config.db_port, 'connect_timeout': self.config.query_timeout, } if self.config.db_password: conn_params['password'] = self.config.db_password ``` ### Technical Analysis Remote PostgreSQL access is legitimate for the Skill's multi-instance feature, but the setup guidance recommends listening on all interfaces and allowing all IPv4 source addresses using legacy `md5` authentication. Although a later warning advises using specific ranges in production, the immediately actionable configuration remains unsafe. The Python client supplies no `sslmode`, CA certificate, or hostname-verification setting. Consequently, the application does not enforce encrypted, certificate-validated transport for conversation memory and database credentials. This exposure is especially significant because the database is designed to retain complete messages, tool calls, tool results, identifiers, and assistant reasoning. ### Attack Path 1. An operator follows the setup instructions and configures PostgreSQL to listen on all interfaces. 2. The operator adds the broad `0.0.0.0/0` host rule. 3. The PostgreSQL port becomes reachable from untrusted networks unless a separate firewall blocks it. 4. Attackers probe or brute-force the database service, while a network-positioned attacker may targ ...[truncated 686 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace `listen_addresses = '*'` with a private interface or explicitly approved address. 2. Replace `0.0.0.0/0` with narrowly scoped client CIDRs. 3. Require `scram-sha-256` authentication rather than legacy `md5`. 4. Require TLS on the server and use `hostssl` rules in `pg_hba.conf`. 5. Add client configuration for `sslmode=verify-full`, a trusted root certificate, and hostname verification. 6. Refuse remote non-TLS connections by default; require an explicit opt-out only for loopback development. 7. Recommend a private VPN or authenticated tunnel and a firewall allowlist for multi-instance deployments. 8. Separate database roles by agent or tenant where practical and enable Row-Level Security. 9. Update setup output so the secure configuration is the default example rather than a secondary warning. ]]>

T08 · Insecure Dependencies

Warning
Location
install.sh:111
Finding
Unpinned Third-Party Dependency Installed at Runtime<![CDATA[ ## Vulnerability Details **File Location**: `install.sh:111-114` and `client-setup.sh:122-125` **Vulnerability Type**: Unpinned dependency and non-reproducible installation **Risk Level**: Medium ### Vulnerable Code ```bash # Step 3: Install Python dependencies print_info "Installing Python dependencies..." pip3 install --user psycopg2-binary 2>/dev/null || pip3 install psycopg2-binary print_success "Python dependencies installed" ``` ```bash # Install psycopg2 echo "" echo "Installing psycopg2-binary..." $PYTHON -m pip install psycopg2-binary --quiet echo "✓ psycopg2-binary installed" ``` ### Technical Analysis Both installation paths retrieve and install the latest available `psycopg2-binary` package from the active pip index. No reviewed version, package hash, lockfile, or index restriction is enforced. The installed artifact is subsequently imported by the Skill and therefore executes in the agent's Python process. The exact code installed can change over time without any change to the audited project. The package name appears legitimate rather than typosquatted, so this is an unsafe dependency-management issue rather than evidence that the current dependency is malicious. ### Attack Path 1. A user runs the installer or client setup script. 2. Pip resolves `psycopg2-binary` using the user's configured package index and current latest release. 3. A compromised index, altered pip configuration, compromised future release, or maliciously substituted artifact is selected. 4. Pip installs the package into the user or active Python environment. 5. pg-memory imports the installed package. 6. Malicious package code executes with the privileges and data access of the OpenClaw process. ### Impact Assessment A compromised dependency could execute arbitrary Python or native code, access database credentials, read stored conversation memory, modify agent files, and communicate over the network using the permissions of the installing or running accoun ...[truncated 164 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `psycopg2-binary` to a reviewed, compatible version. 2. Maintain a requirements or lock file containing cryptographic hashes. 3. Install using `pip install --require-hashes -r requirements.txt`. 4. Restrict installation to the official, expected package index and document trusted index configuration. 5. Use an isolated virtual environment instead of modifying the global or user Python environment. 6. Review and update dependencies through a controlled release process with vulnerability scanning. 7. Record the exact dependency version in package metadata and test it in continuous integration. 8. Consider building and signing a reproducible installation artifact for deployment-sensitive environments. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (116)

Context-Inappropriate Capability

Critical
Confidence
98% confidence
Finding
The skill exposes full database restore capability and optionally drops and recreates the database first. In an agent-accessible component, this is highly dangerous because a bad prompt, misuse, or compromised caller could irreversibly destroy or overwrite all stored data.

Chaining Abuse

High
Category
Tool Misuse
Content
sudo -u postgres psql -d openclaw_memory < /tmp/migration_*.sql

# Or if compressed:
gunzip -c /tmp/migration_*.sql.gz | sudo -u postgres psql -d openclaw_memory
```

### Step 3: Reconfigure Client
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Chaining Abuse

High
Category
Tool Misuse
Content
sudo -u postgres psql -d openclaw_memory < /tmp/migration_*.sql

# Or if compressed:
gunzip -c /tmp/migration_*.sql.gz | sudo -u postgres psql -d openclaw_memory
```

### Step 3: Reconfigure Client
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Missing User Warnings

High
Confidence
99% confidence
Finding
The troubleshooting guidance tells users to set `listen_addresses = '*'` and allow `host all all 0.0.0.0/0 md5`, which can expose PostgreSQL to the entire internet or local network if copied verbatim. Even though a later checklist says not to use `0.0.0.0/0`, placing this as troubleshooting advice creates a strong insecure-default pattern that could lead to unauthorized access or brute-force attempts against the database.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The description presents a feature-rich structured memory system, but the provided code chunk is only an installer/bootstrap script. Its actual actions are limited to environment checks, package installation, PostgreSQL connectivity/user/database setup, schema initialization, optional destructive reset, CLI chmod, and config generation. While these setup tasks are consistent with supporting a PostgreSQL-backed memory system, the chunk does not evidence several prominent declared features such as compaction hooks, dual-write, markdown backup, context preservation logic, or multi-agent behavior. Because the declared purpose emphasizes runtime capabilities that are not represented here, and the chunk’s primary purpose is installation rather than the described memory functionality, this is a description/behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description presents the skill as a structured PostgreSQL memory system with compaction hooks, dual-write behavior, markdown backup, and context preservation for agents. The supplied code chunk does not implement those storage or lifecycle functions. Instead, it adds a separate natural-language querying feature: it constructs prompts, calls a local Ollama model through subprocess, extracts and sanitizes generated SQL, and runs SELECT queries on the pg-memory database. This is materially different from the declared primary purpose and introduces an undeclared capability (LLM-backed NL-to-SQL query execution). While it is related to the broader pg-memory ecosystem, this specific code chunk is not accurately represented by the supplied description.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The code generally matches the broad claim of being a PostgreSQL-based structured memory system with markdown export/backup behavior and multi-instance/multi-agent support. However, the description omits several substantial capabilities present in the code: natural-language querying (including optional LLM-assisted SQL generation via Ollama), backup/restore through external database tools, JSON import/export, markdown bulk import, reminder and chain management, template support, conflict tracking, and auto-creation of project/task observations. More importantly, some specifically declared features are not supported by the supplied chunk: there is no clear implementation of pre/post-compaction integration, no demonstrated dual-write mechanism, and no concrete full-context-preservation subsystem beyond general storage/export features. Because both undeclared significant capabilities and unsubstantiated declared features are present, this is a description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description presents a general-purpose PostgreSQL structured memory system emphasizing full context preservation, dual-write behavior, markdown backup, and compaction integration. The supplied code chunk instead implements a standalone pruning/cleanup script for an existing PostgreSQL memory database. Its primary behavior is retention enforcement: selecting old rows from raw_exchanges, tool_executions, and sessions; archiving some records to compressed JSONL files under a filesystem path; soft-deleting/hard-deleting data; running VACUUM ANALYZE; showing stats; and printing partitioning SQL. Those are materially different capabilities from the declared purpose. Most notably, the code deletes old memory and therefore conflicts with 'full context preservation,' and it does not show dual-write, markdown backup, or compaction integration.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents a broad agent memory subsystem with specialized memory features, but the supplied code chunk is narrowly focused on operational database partition management. Its primary purpose is maintaining monthly PostgreSQL partitions for raw_exchanges, including creating future partitions and archiving old ones to compressed JSONL before deleting the detached table. This is materially different from a structured memory system and introduces undeclared capabilities, including filesystem archival and destructive schema/data maintenance actions. While it imports AgentMemory for database connectivity, that appears to be a supporting dependency rather than evidence that this chunk implements the declared memory functionality. Therefore, the description does not accurately represent this code chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description presents a full PostgreSQL-backed memory system with pre/post-compaction integration, dual-write support, markdown backup, and multi-agent context preservation. The supplied code chunk does not implement that system; it is a narrow operational script for regenerating embeddings on existing observations. It accesses PostgreSQL and an Ollama HTTP API, selects records needing embeddings, generates new vectors, and writes them back. None of the headline features in the description—dual-write, markdown backup, compaction integration, or multi-agent orchestration—are evidenced here. While embedding maintenance could be related to a memory system, this chunk’s actual purpose is materially narrower and includes an undeclared external capability (embedding generation via Ollama).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
cat /opt/homebrew/var/log/postgresql@16.log

# Re-initialize (WARNING: loses data!)
rm -rf /opt/homebrew/var/postgresql@16
initdb --locale=en_US.UTF-8 -E UTF8 /opt/homebrew/var/postgresql@16
```
Confidence
99% confidence
Finding
The explicit `rm -rf /opt/homebrew/var/postgresql@16` instruction is a concrete high-risk deletion primitive. Because the skill also implies shell-based setup and maintenance, this materially increases the chance of unsafe execution and permanent loss of the agent's stored history and database state.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
cat /opt/homebrew/var/log/postgresql@16.log

# Re-initialize (WARNING: loses data!)
rm -rf /opt/homebrew/var/postgresql@16
initdb --locale=en_US.UTF-8 -E UTF8 /opt/homebrew/var/postgresql@16
```
Confidence
99% confidence
Finding
The explicit `rm -rf /opt/homebrew/var/postgresql@16` instruction is a concrete high-risk deletion primitive. Because the skill also implies shell-based setup and maintenance, this materially increases the chance of unsafe execution and permanent loss of the agent's stored history and database state.

Missing User Warnings

High
Confidence
99% confidence
Finding
When connection testing fails, the installer proceeds to attempt creation of a PostgreSQL superuser without a clear warning or consent gate. Automatically escalating database privileges is dangerous because it can alter shared local database security posture and create a highly privileged account tied to an application user.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The installer attempts to run `createuser -s "$DB_USER"`, which grants PostgreSQL superuser privileges to the configured database user. For a memory-storage skill, this is unnecessary and materially increases blast radius: compromise of the application or that DB user would enable unrestricted database-level actions across the PostgreSQL instance.

Context-Inappropriate Capability

High
Confidence
94% confidence
Finding
The code sends arbitrary natural-language input and the full database schema to an external LLM process, then executes the model-generated SQL directly against the database. Although it tries to restrict queries to `SELECT` and block obvious write operations, this is still dangerous because an LLM can generate expensive, data-exfiltrating, or side-effecting read queries, and the guardrails are based on brittle string filtering rather than robust query allowlisting or SQL parsing.

Context-Inappropriate Capability

High
Confidence
93% confidence
Finding
A structured memory skill would reasonably query PostgreSQL, but spawning subprocesses to run 'ollama list' is not an obvious requirement of memory storage or markdown backup. This adds host-level command execution capability unrelated to the manifest's stated core purpose.

Description-Behavior Mismatch

High
Confidence
95% confidence
Finding
The skill expands beyond memory storage into backup and restore of the whole PostgreSQL database, including filesystem writes and invocation of administrative tools. In an agent skill context, this significantly broadens capability and blast radius, making accidental misuse, data exfiltration, or destructive operations more likely.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
# Add compression if requested
    if compress:
        cmd_str = " ".join(cmd) + f" | gzip > {backup_path}"
        result = subprocess.run(cmd_str, shell=True, capture_output=True, text=True)
    else:
        # Run pg_dump and redirect to file
        with open(backup_path, 'w') as f:
Confidence
99% confidence
Finding
This is a classic tool-parameter abuse issue: attacker-influenced values are embedded into a shell command and executed with `shell=True`. In a skill that may receive parameters from an LLM-driven workflow, that context materially increases exploitability and risk of arbitrary command execution.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
if is_compressed:
        cmd_str = f"gunzip -c {backup_path} | psql -h {db_host} -p {db_port} -U {db_user} -d {db_name}"
        result = subprocess.run(cmd_str, shell=True, capture_output=True, text=True)
    else:
        cmd = [
            "psql",
Confidence
99% confidence
Finding
The restore path combines shell execution with attacker-influenced parameters and a highly privileged operation. This creates a compound risk: arbitrary command execution plus potential full database destruction or overwrite, making it especially severe in an agent-integrated skill.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# (On Synology: Package Center → PostgreSQL)

# Create database
sudo -u postgres createdb openclaw_memory

# Enable extensions
sudo -u postgres psql -d openclaw_memory -c "CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";"
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
# (On Synology: Package Center → PostgreSQL)

# Create database
sudo -u postgres createdb openclaw_memory

# Enable extensions
sudo -u postgres psql -d openclaw_memory -c "CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";"
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
# (On Synology: Package Center → PostgreSQL)

# Create database
sudo -u postgres createdb openclaw_memory

# Enable extensions
sudo -u postgres psql -d openclaw_memory -c "CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";"
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
# (On Synology: Package Center → PostgreSQL)

# Create database
sudo -u postgres createdb openclaw_memory

# Enable extensions
sudo -u postgres psql -d openclaw_memory -c "CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";"
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
# (On Synology: Package Center → PostgreSQL)

# Create database
sudo -u postgres createdb openclaw_memory

# Enable extensions
sudo -u postgres psql -d openclaw_memory -c "CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";"
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
# (On Synology: Package Center → PostgreSQL)

# Create database
sudo -u postgres createdb openclaw_memory

# Enable extensions
sudo -u postgres psql -d openclaw_memory -c "CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";"
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.