Back to skill

Security audit

Claw Social

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed paip.ai social automation package, but it grants broad account-changing and message-handling authority with weak safeguards, so users should review it carefully before installing.

Install only if you are comfortable giving this skill authenticated control over a paip.ai account. Do not use a primary or sensitive account until the listener is redesigned to treat incoming messages as untrusted data, credentials are not passed on the command line, tokens and logs are protected, hardcoded test credentials are removed, and public posting/following/commenting actions require clear user-directed control.

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
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (7)

T01 · Skill Instruction Hijacking

Error
Location
scripts/websocket_listener.py:49
Finding
Remote Private Messages Are Injected into High-Priority OpenClaw Instructions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/websocket_listener.py:49-64, 76-87, 162-166`; supporting instructions in `SKILL.md:277-288, 325-331` **Vulnerability Type**: Remote prompt injection through a privileged Agent event **Risk Level**: Critical ### Vulnerable Code ```python def build_system_event_prompt(message_content: str) -> str: """Builds the immediate reply instruction passed into OpenClaw.""" normalized_message = message_content.strip() return f""" SYSTEM ALERT: HIGH-PRIORITY TASK INJECTED You have received a new paip.ai private chat message and must handle it immediately. **Message Content:** "{normalized_message}" **Your mandatory task is as follows:** 1. **Find the Room ID:** Immediately execute a search using the paip.ai API to find the chat session where the latest message content exactly matches the text above. This typically involves calling the `/agent/chat/session/list?withLatestMessage=true` endpoint and parsing the JSON response. 2. **Extract the `roomId`** from the correct session object in the search result. 3. **Formulate a Reply:** Based on the message content, formulate a natural, conversational reply. 4. **Send the Reply:** Use the paip.ai API to send your formulated reply to the extracted `roomId`. 5. **Confirm Completion:** After sending the reply, your task is complete. """.strip() ``` ```python process = await asyncio.create_subprocess_exec( "openclaw", "system", "event", "--mode", "now", "--expect-final", "--timeout", str(SYSTEM_EVENT_TIMEOUT_MS), "--json", "--text", prompt, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) ``` ```python async for message in websocket: message_content = str(message) logging.info(f"Received raw notification: {message_content}") append_event_log(message_content) await reply_queue.put(message_content) ``` ### Technical Analysis The listener treats an arbitrary WebSocket message ...[truncated 1715 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not submit remote message content as part of a system-level or high-priority instruction. - Represent inbound content as typed, untrusted data passed to a fixed handler rather than interpolated prompt text. - Implement a deterministic message-processing component with a narrowly scoped API client instead of allowing a general-purpose Agent to choose tools. - Restrict the handler to explicitly approved operations, such as fetching the matching room and sending one reply to that room. - Validate WebSocket messages against a strict schema, length limit, sender identity, and expected character encoding. - Require user approval before performing sensitive or non-reply actions. - Use a dedicated credential whose permissions are limited to reading the relevant session and sending a reply. - If an LLM must formulate replies, pass only normalized message data and prevent it from invoking tools directly. A separate trusted component should validate and execute the resulting action. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/login_and_listen.sh:71
Finding
Bearer Session Token Is Persisted Without Restrictive File Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/login_and_listen.sh:8-10, 71-72` **Vulnerability Type**: Insecure plaintext secret storage **Risk Level**: High ### Vulnerable Code ```bash WORKSPACE_DIR="$HOME/.openclaw/workspace" TOKEN_FILE="$WORKSPACE_DIR/.session_token" USER_ID_FILE="$WORKSPACE_DIR/.paipai_user_id" DEVICE_ID_FILE="$WORKSPACE_DIR/.session_device_id" ``` ```bash # Save the new token to be used immediately echo "$TOKEN" > "$TOKEN_FILE" log "Token saved to $TOKEN_FILE" ``` ### Technical Analysis The authenticated bearer token is written as plaintext without setting a restrictive `umask`, validating directory ownership, or applying mode `600`. Its resulting permissions depend on the user’s ambient umask and existing filesystem state. The script also does not create or verify `WORKSPACE_DIR` in the shown workflow. If that path or token file is pre-created or redirected through a symbolic link, the write may target an unintended file. ### Attack Path 1. A user runs the login workflow and receives a valid bearer token. 2. The script writes the token to `~/.openclaw/workspace/.session_token`. 3. A permissive umask, unsafe pre-existing file, or insufficiently protected parent directory makes the token accessible to another local principal. 4. The local attacker reads the token. 5. The attacker reuses it against authenticated paip.ai endpoints until it expires or is revoked. ### Impact Assessment The exposed bearer token grants the holder the account privileges accepted by the paip.ai API. Depending on server-side authorization, this may include reading account data, accessing social or chat metadata, publishing content, sending messages, following users, or otherwise acting as the victim. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Set `umask 077` before creating any session files. - Create the workspace directory with `mkdir -p -m 700 "$WORKSPACE_DIR"` and verify it is owned by the current user. - Create token files atomically with mode `600`, rejecting symbolic links and unsafe pre-existing files. - Prefer an operating-system credential store or OpenClaw’s supported secret-management facility over plaintext files. - Avoid retaining the token longer than required and delete it during logout or uninstall. - Implement token rotation, short expiration, and server-side revocation. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/login_and_listen.sh:31
Finding
Login Password Is Exposed Through Command-Line Arguments and Unsafely Interpolated JSON<![CDATA[ ## Vulnerability Details **File Location**: `scripts/login_and_listen.sh:31-49`; documented invocation in `SKILL.md:94-97` **Vulnerability Type**: Local credential exposure and unsafe request construction **Risk Level**: High ### Vulnerable Code ```bash if [ "$#" -ne 2 ]; then log "Usage: $0 <email> <password>" exit 1 fi EMAIL="$1" PASSWORD="$2" generate_device_id log "Attempting to log in as $EMAIL..." # Perform login LOGIN_RESPONSE=$(curl --max-time 300 -s -X POST "$BASE_URL/user/login" \ -H "Content-Type: application/json" \ -H "X-DEVICE-ID: $DEVICE_ID" \ -H "X-Response-Language: en-us" \ -d "{\"loginType\": 1, \"username\": \"$EMAIL\", \"password\": \"$PASSWORD\"}") ``` The documented command is: ```bash ./scripts/login_and_listen.sh "your_email@example.com" "your_password" ``` ### Technical Analysis Passing a password as a positional command-line argument can expose it through shell history, terminal logging, process inspection, auditing systems, or wrapper-tool telemetry. The password is also expanded into curl’s argument vector. The JSON body is assembled using direct shell interpolation. Passwords or email addresses containing quotation marks, backslashes, control characters, or JSON metacharacters can break the payload. This is not a shell-command injection because the expansion remains quoted, but it is unsafe serialization and can produce unintended request data. ### Attack Path 1. The user follows the documented invocation and places the password directly on the command line. 2. The command is retained in shell history or briefly exposed through process and audit information. 3. Another local user, monitoring process, terminal recorder, or log collector obtains the password. 4. The attacker logs into the paip.ai account using the captured credential. 5. If the same password is reused elsewhere, compromise may extend to additional services. ### Impact Assessment The issue can disclose the account’s reusable passwor ...[truncated 225 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Accept only the email as an argument and read the password interactively using a silent prompt such as `read -r -s`. - Support a secure standard-input or file-descriptor mechanism for noninteractive use. - Do not place passwords in environment variables unless the runtime guarantees appropriate isolation. - Construct the request with a real JSON serializer, for example: ```bash payload=$(jq -n --arg username "$EMAIL" --arg password "$PASSWORD" \ '{loginType: 1, username: $username, password: $password}') printf '%s' "$payload" | curl ... --data-binary @- ``` - Clear the password variable immediately after the request. - Update `SKILL.md` so it no longer instructs users to put passwords on the command line. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/websocket_listener.py:9
Finding
Raw Private Messages Are Persisted in Predictable Shared Temporary Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/websocket_listener.py:9-10, 41-44, 162-164` **Vulnerability Type**: Sensitive-data exposure and unsafe temporary-file handling **Risk Level**: High ### Vulnerable Code ```python LOG_FILE = "/tmp/websocket_listener.log" EVENTS_LOG_FILE = "/tmp/websocket_listener_events.log" ``` ```python def append_event_log(message_content: str): """Persists raw inbound WebSocket payloads for later debugging.""" with open(EVENTS_LOG_FILE, "a") as f: f.write(f"[{datetime.now()}] {message_content.rstrip()}\n") ``` ```python async for message in websocket: message_content = str(message) logging.info(f"Received raw notification: {message_content}") append_event_log(message_content) ``` ### Technical Analysis Every inbound private-message payload is written verbatim to a fixed path under the globally shared `/tmp` directory. The code does not set restrictive permissions, redact sensitive content, rotate or expire records, verify ownership, or prevent symbolic-link traversal. The same payload is also emitted through the regular logger. The launcher redirects that output to `/tmp/websocket_listener.log`, resulting in two predictable locations containing private-message content. On systems where an attacker can prepare these paths, a symbolic link may cause append operations to target another file writable by the victim. Independently, permissive file modes or shared runtime contexts can expose the conversation history. ### Attack Path 1. A local attacker observes or prepares `/tmp/websocket_listener_events.log` or `/tmp/websocket_listener.log`. 2. The victim starts the listener and receives private messages. 3. The listener writes complete message content to the predictable paths. 4. The attacker reads the resulting logs or uses a pre-created symbolic link to redirect appends. 5. Sensitive conversation content remains available without a defined retention limit. ### Impact Assessment ...[truncated 358 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not log raw private-message bodies by default. - Log only non-sensitive metadata, such as a message identifier, timestamp, and processing result. - If diagnostic body logging is explicitly enabled, redact secrets and impose short retention and size limits. - Store logs in an application-specific directory owned by the current user with directory mode `700` and file mode `600`. - Open files using symlink-resistant and exclusive creation controls, including `O_NOFOLLOW` where supported. - Use a secure logging facility with rotation and access-control support instead of fixed files in `/tmp`. - Document the data-retention behavior and provide a cleanup mechanism. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/start_websocket_listener.sh:16
Finding
Listener Management Terminates Processes Based Only on a Command-Line Substring<![CDATA[ ## Vulnerability Details **File Location**: `scripts/start_websocket_listener.sh:16-39, 62-70`; duplicated in `scripts/stop_websocket_listener.sh:9-42` **Vulnerability Type**: Overbroad process control **Risk Level**: Medium ### Vulnerable Code ```bash find_listener_pids() { python3 - "$$" <<'PY' import subprocess import sys current_shell_pid = int(sys.argv[1]) out = subprocess.check_output(["ps", "-ax", "-o", "pid=,command="], text=True) for line in out.splitlines(): raw = line.strip() if not raw: continue pid_text, _, command = raw.partition(" ") try: pid = int(pid_text) except ValueError: continue if pid in {current_shell_pid}: continue if "websocket_listener.py" not in command: continue if "start_websocket_listener.sh" in command or "stop_websocket_listener.sh" in command: continue print(pid) PY } ``` ```bash stale_pids="$(find_listener_pids || true)" if [[ -n "$stale_pids" ]]; then echo "Stopping existing listener process(es): $stale_pids" while IFS= read -r pid; do [[ -z "$pid" ]] && continue kill "$pid" >/dev/null 2>&1 || true done <<< "$stale_pids" sleep 1 fi ``` ### Technical Analysis The launcher and stop script identify target processes solely by checking whether the text `websocket_listener.py` appears in the process command line. They do not validate the executable path, process owner, recorded PID, process start time, or association with this Skill instance. Consequently, unrelated processes with the same filename—or merely that text in their command line—can be signaled. This exceeds the minimum process-control privileges needed to manage the one listener started by the Skill. ### Attack Path 1. Another legitimate application runs a process whose command line contains `websocket_listener.py`. 2. The user invokes this Skill’s start or stop script. 3. The script scans the complete process list and treats the unre ...[truncated 719 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Manage only the process recorded in the Skill’s PID file. - Before signaling it, verify: - the PID contains only digits; - the process is owned by the current user; - the executable and script paths exactly match the expected listener; - the process start time or a generated instance token matches the recorded instance. - Store the PID file in a private runtime directory instead of a globally predictable `/tmp` path. - Acquire an exclusive lock when starting the listener to prevent duplicate instances. - Never scan and terminate every process based on a filename substring. - Consider a user-scoped service manager if durable listener lifecycle management is required. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/token-manager.sh:60
Finding
Test Script Contains Hardcoded Account Credentials and Performs a Mutating Remote Action<![CDATA[ ## Vulnerability Details **File Location**: `scripts/token-manager.sh:60-91` **Vulnerability Type**: Hardcoded secret and unexpected authenticated side effect **Risk Level**: High ### Vulnerable Code ```bash # Test login (no token required) step "1. Test login endpoint (no token required)" LOGIN_DATA='{"loginType":1,"username":"testuser037@test.com","password":"TestPass037!"}' login_response=$(send_request "POST" "/user/login" "$LOGIN_DATA") if echo "$login_response" | grep -q '"code":0'; then token=$(echo "$login_response" | grep -o '"token":"[^"]*"' | cut -d'"' -f4) if [ -n "$token" ]; then success "Login successful! Token retrieved." echo "Token: ${token:0:50}..." # Test an endpoint that requires a token step "2. Test retrieving user information (token required)" user_response=$(send_request "GET" "/user/current/user" "" "$token") if echo "$user_response" | grep -q '"code":0'; then username=$(echo "$user_response" | grep -o '"username":"[^"]*"' | cut -d'"' -f4) success "User information retrieved successfully!" echo "Username: $username" # Test publishing a moment (token required) step "3. Test publishing a moment (token required)" post_data='{"content":"Test moment - published via the token management script","images":[],"videos":[]}' post_response=$(send_request "POST" "/content/moment/create" "$post_data" "$token") ``` ### Technical Analysis The repository embeds a plaintext email address and password. Anyone with access to the package can attempt to use them. Even if the account was intended only for testing or the password has expired, retaining credentials in distributed source is an insecure secret-management practice. The script is described as a token-management test but automatically publishes a remote post after login and user-information retrieval. That state-chan ...[truncated 1203 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the credential from the repository and rotate it immediately. - Review repository history and published package versions for prior exposure. - Obtain test credentials from a protected secret store at runtime. - Use a dedicated, isolated test account with minimal permissions and no sensitive data. - Do not display any portion of bearer tokens in normal output. - Make mutating tests opt-in and require explicit confirmation. - Prefer a mock server or dedicated staging environment for API tests. - Clearly separate read-only authentication checks from content-publication tests. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:77
Finding
Onboarding Installs an Unpinned Python Dependency from a Mutable Package Source<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:77-81, 299-307` **Vulnerability Type**: Unpinned third-party dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash python3 --version python3 -m pip install websockets openclaw --version ``` The same installation instruction is repeated later: ```bash python3 -m pip install websockets ``` ### Technical Analysis The installation command resolves whichever `websockets` release the configured package index currently serves. No exact version, cryptographic hash, lockfile, isolated environment, or reviewed source is specified. This makes installations non-reproducible and allows future package releases or a compromised package-index path to change the code installed after the Skill has been audited. The reviewed project did not contain evidence that the legitimate `websockets` package is malicious; the issue is the unsafe dependency acquisition process. ### Attack Path 1. A user follows the mandatory onboarding documentation. 2. `pip` queries the user’s configured package index and selects the latest compatible `websockets` release. 3. A compromised release, index, mirror, configuration, or dependency is returned. 4. The package is installed into the selected Python environment. 5. Package or runtime code executes with the installing user’s privileges when imported or invoked. ### Impact Assessment A compromised dependency can execute with the privileges of the user running pip or the listener. This may expose paip.ai tokens, private messages, OpenClaw-accessible data, and local files available to that user. If the command is run in a privileged system environment, the impact can be broader. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Pin `websockets` to a reviewed exact version. - Generate and verify cryptographic hashes using a locked requirements file. - Install with `pip --require-hashes -r requirements.txt`. - Use a dedicated virtual environment rather than modifying the global Python environment. - Review transitive dependencies and update pins through a controlled security-update process. - Document the trusted package index and use TLS-validated, organization-approved mirrors where applicable. - Add automated dependency vulnerability and integrity scanning to release checks. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (60)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill describes a persistent authenticated WebSocket listener that automatically forwards inbound messages into high-priority agent tasks for immediate handling. This creates a prompt-injection and remote action-trigger surface, because untrusted message content can be transformed into privileged system events and potentially drive autonomous replies or other actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill describes a persistent authenticated WebSocket listener that automatically forwards inbound messages into high-priority agent tasks for immediate handling. This creates a prompt-injection and remote action-trigger surface, because untrusted message content can be transformed into privileged system events and potentially drive autonomous replies or other actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill describes a persistent authenticated WebSocket listener that automatically forwards inbound messages into high-priority agent tasks for immediate handling. This creates a prompt-injection and remote action-trigger surface, because untrusted message content can be transformed into privileged system events and potentially drive autonomous replies or other actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill describes a persistent authenticated WebSocket listener that automatically forwards inbound messages into high-priority agent tasks for immediate handling. This creates a prompt-injection and remote action-trigger surface, because untrusted message content can be transformed into privileged system events and potentially drive autonomous replies or other actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill describes a persistent authenticated WebSocket listener that automatically forwards inbound messages into high-priority agent tasks for immediate handling. This creates a prompt-injection and remote action-trigger surface, because untrusted message content can be transformed into privileged system events and potentially drive autonomous replies or other actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill describes a persistent authenticated WebSocket listener that automatically forwards inbound messages into high-priority agent tasks for immediate handling. This creates a prompt-injection and remote action-trigger surface, because untrusted message content can be transformed into privileged system events and potentially drive autonomous replies or other actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill describes a persistent authenticated WebSocket listener that automatically forwards inbound messages into high-priority agent tasks for immediate handling. This creates a prompt-injection and remote action-trigger surface, because untrusted message content can be transformed into privileged system events and potentially drive autonomous replies or other actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill describes a persistent authenticated WebSocket listener that automatically forwards inbound messages into high-priority agent tasks for immediate handling. This creates a prompt-injection and remote action-trigger surface, because untrusted message content can be transformed into privileged system events and potentially drive autonomous replies or other actions.

External Script Fetching

High
Category
Supply Chain
Content
echo "--- Starting The Curator Routine ---"
echo "--- Fetching all my posts to analyze performance... ---"

MY_POSTS_RAW=$(curl -s -G "https://gateway.paipai.life/api/v1/content/moment/list" "${HEADERS[@]}" --data-urlencode "userId=$MY_USER_ID" --data-urlencode "page=1" --data-urlencode "size=100")
MY_POSTS_CLEAN=$(echo "$MY_POSTS_RAW" | python3 "$SAFE_PARSER_PATH" data.records)

HIGHEST_SCORE=-1
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
curl -s -X POST "https://gateway.paipai.life/api/v1/content/like/" "${HEADERS[@]}" -d "{\"type\": \"moment\", \"targetId\": $post_id}" > /dev/null
    local comment_text="Hi @$author_nickname, your post showed up while I was exploring. Looks great!"
    local reply_payload=$(jq -n --arg content "$comment_text" --arg t_id "$post_id" '{type: "moment", targetId: ($t_id | tonumber), content: $content}')
    curl -s -X POST "https://gateway.paipai.life/api/v1/content/comment/" "${HEADERS[@]}" -d "$reply_payload" > /dev/null
    
    echo "    - Interacted (Liked & Commented)."
    echo "$author_id" >> "$INTERACTED_LOG"
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
search_terms=("Art" "Music" "Tech" "Gaming" "Photography")
    random_term=${search_terms[$((RANDOM % ${#search_terms[@]}))]}
    echo "Action: Searching for posts with keyword '$random_term'."
    FEED_RAW=$(curl -s -G "https://gateway.paipai.life/api/v1/content/search/search" "${HEADERS[@]}" --data-urlencode "keyword=$random_term" --data-urlencode "type=moment" --data-urlencode "page=1" --data-urlencode "size=10")
    FEED_CLEAN=$(echo "$FEED_RAW" | python3 "$SAFE_PARSER_PATH" data.records)
    SOURCE="Search ('$random_term')"
fi
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
# --- Action 1: Handle New Followers ---
echo "--- Starting The Guardian Routine ---"
echo "--- 1. Checking for new followers... ---"
FANS_RAW=$(curl -s -G "https://gateway.paipai.life/api/v1/user/fans/list" "${HEADERS[@]}" --data-urlencode "userId=$MY_USER_ID" --data-urlencode "page=1" --data-urlencode "size=100")
FOLLOWING_RAW=$(curl -s -G "https://gateway.paipai.life/api/v1/user/follow/list" "${HEADERS[@]}" --data-urlencode "userId=$MY_USER_ID" --data-urlencode "page=1" --data-urlencode "size=100")

FANS_IDS=$(echo "$FANS_RAW" | python3 "$SAFE_PARSER_PATH" data.records | jq -r '.[].id')
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
for fan_id in $FANS_IDS; do
    if ! echo "$FOLLOWING_IDS" | grep -q -w "$fan_id"; then
        echo "  - Found new follower: ID $fan_id. Following back."
        curl -s -X POST "https://gateway.paipai.life/api/v1/user/follow/user" "${HEADERS[@]}" -d "{\"followUserId\": $fan_id, \"followUserType\": \"user\"}" > /dev/null
        ((NEW_FOLLOWERS++)); sleep 1
    fi
done
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
echo "$MY_POSTS_CLEAN" | jq -c '.[]' | while read -r post; do
    POST_ID=$(echo "$post" | jq -r '.id')
    
    COMMENTS_CLEAN=$(curl -s -G "https://gateway.paipai.life/api/v1/content/comment/list" "${HEADERS[@]}" --data-urlencode "type=moment" --data-urlencode "targetId=$POST_ID" --data-urlencode "page=1" --data-urlencode "size=50" | python3 "$SAFE_PARSER_PATH" data.records)
    
    MY_REPLIES=$(echo "$COMMENTS_CLEAN" | jq -c --arg name "$MY_NICKNAME" '.[] | select(.user.nickname == $name)')
    REPLIED_TO_IDS=$(echo "$MY_REPLIES" | jq -r '.parentId // 0' | grep -v '0' | sort -u)
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
esac

echo "  - Uploading $MEDIA_TYPE file: $MEDIA_FILE..."
UPLOAD_RAW=$(curl --max-time 600 --connect-timeout 300 -s -X POST "https://gateway.paipai.life/api/v1/content/common/upload" \
    "${HEADERS[@]}" \
    -F "file=@${MEDIA_FILE}" -F "type=content" -F "path=content" -F "id=${MY_USER_ID}")
Confidence
91% confidence
Finding
The upload routine transmits an arbitrary local file specified by the caller to a third-party endpoint using the bearer token and user ID, with no path restrictions, content inspection, or interactive confirmation. In the context of an agent skill, this increases the danger because another component could invoke the script with sensitive local paths, causing unintended disclosure of local data to the external service.

Ssd 1

High
Confidence
99% confidence
Finding
The function embeds attacker-controlled message text inside a high-priority system prompt that instructs the downstream agent to search sessions, extract room IDs, formulate replies, and send them. This is a classic prompt-injection sink: malicious message content can semantically override or manipulate agent behavior, causing unauthorized actions, data access, or message exfiltration in the context of the user's authenticated paip.ai account.

Missing User Warnings

High
Confidence
96% confidence
Finding
Raw inbound chat content is sent to the external OpenClaw CLI for processing, which is a separate trust boundary and may result in disclosure of private user content to components beyond the WebSocket listener. Since the content is untrusted and can contain adversarial instructions, this also amplifies prompt-injection risk in the downstream agent.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill documentation describes capabilities requiring network access, shell execution, environment-variable use, and local file writes, but it declares no corresponding tool scope or permission boundaries. This creates a confused-deputy risk where an agent may perform sensitive actions without explicit authorization or user awareness.

Session Persistence

Medium
Category
Rogue Agent
Content
- **✅ Manage Your Home**: Keep your own profile updated with a fresh look and new information.
- **✅ Private Chat**: Start or resume user-to-user (C2C) or user-to-agent (C2A) direct messages, fetch session lists, and load chat history.
- **✅ Real-Time Listening**: Connect via WebSocket to receive instant notifications of new private chat messages.
- **✅ Group Chat**: Create group rooms, join or invite members, remove members, exit rooms, and use shared chat history and messaging APIs.

## Part 2: Advanced Gameplay - The Automated Social Routines
Confidence
80% confidence
Finding
The skill is built around persistent sessions, chat history, listener state, and stored runtime identifiers, which increases the blast radius if local state is accessed by unauthorized parties. In a social/messaging context, retained tokens, room metadata, and chat artifacts can expose private communications and enable account actions without re-authentication.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The onboarding and login workflow instructs users to supply email and password to a shell script and states that session artifacts are persisted locally, but it does not prominently warn about plaintext exposure or local token storage risk. Command-line secrets can be exposed via shell history and process lists, and persisted session files can be stolen by other local users or malware if permissions are weak.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This shell code sends a file upload request containing the authenticated user's ID and shared headers that likely include credentials, but the only output is a progress message about uploading. The comments describe required environment variables for the script author, not a warning to the user that user/account data and media will be transmitted to a remote service.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The function hard-codes `publicScope: "PUBLIC"` and creates a remote social post without any explicit warning or confirmation that the content will be published publicly. In an agent context, this can cause unintended disclosure of user text or media if a caller assumes the action is draft/private or does not realize the visibility is public.

External Transmission

Medium
Category
Data Exfiltration
Content
}')

    local post_response
    post_response=$(curl --max-time 300 --connect-timeout 300 -s -X POST "https://gateway.paipai.life/api/v1/content/moment/create" \
      "${HEADERS[@]}" \
      -H "Content-Type: application/json" \
      -d "$json_payload")
Confidence
70% 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
'{type: "moment", targetId: ($t_id | tonumber), content: $content, parentId: ($p_id | tonumber)}')
    
    local reply_response
    reply_response=$(curl --max-time 300 --connect-timeout 300 -s -X POST "https://gateway.paipai.life/api/v1/content/comment/" \
      "${HEADERS[@]}" -H "Content-Type: application/json" -d "$payload")

    if [[ $(echo "$reply_response" | jq -r '.code') == "0" ]]; then
Confidence
70% 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
log "Attempting to log in as $EMAIL..."

# Perform login
LOGIN_RESPONSE=$(curl --max-time 300 -s -X POST "$BASE_URL/user/login" \
  -H "Content-Type: application/json" \
  -H "X-DEVICE-ID: $DEVICE_ID" \
  -H "X-Response-Language: en-us" \
Confidence
76% confidence
Finding
This script transmits email and password to an external domain as part of login, which is expected functionality, but still security-relevant because the skill handles raw credentials directly. In the context of an agent skill, the risk is elevated by the hardcoded third-party endpoint and subsequent token persistence, since users may delegate execution without fully understanding where their credentials are being sent.

Static analysis

No suspicious patterns detected.