Back to skill

Security audit

Schelling Protocol

Security checks for vulnerabilities and agentic risk

Overview

The skill largely matches its stated coordination-network purpose, but it needs review because it sends user data to an external service and handles API keys in ways that could expose them.

Install only if you are comfortable publishing agent profile details and sending requests/messages to schellingprotocol.com or a configured Schelling server. Do not put secrets, private business details, or sensitive contact data in intents or cards. Treat the returned API key like a password, avoid passing literal keys in shell commands, and avoid setting SCHELLING_URL to non-HTTPS or untrusted hosts.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/inbox.sh:4
Finding

Bearer Credentials Can Be Redirected to an Untrusted or Plaintext Endpoint

Content
View full analysis

Vulnerability Details

File Locations:

  • scripts/inbox.sh:4,31-33
  • scripts/respond.sh:4,45-50
  • scripts/update-card.sh:4,65-70
  • README.md:66-69

Vulnerability Type: Unvalidated destination for authenticated network requests
Risk Level: High

Vulnerable Code

scripts/inbox.sh:4,31-33:

bash
BASE_URL="${SCHELLING_URL:-https://schellingprotocol.com}"

RESPONSE=$(curl -sf \
  -H "Authorization: Bearer ${API_KEY}" \
  "${BASE_URL}/api/cards/${SLUG}/requests") || {

scripts/respond.sh:4,45-50:

bash
BASE_URL="${SCHELLING_URL:-https://schellingprotocol.com}"

RESPONSE=$(curl -sf \
  -X PUT \
  -H "Authorization: Bearer ${API_KEY}" \
  -H "Content-Type: application/json" \
  -d "$BODY" \
  "${BASE_URL}/api/cards/${SLUG}/requests/${REQUEST_ID}") || {

scripts/update-card.sh:4,65-70:

bash
BASE_URL="${SCHELLING_URL:-https://schellingprotocol.com}"

RESPONSE=$(curl -sf \
  -X PUT \
  -H "Authorization: Bearer ${API_KEY}" \
  -H "Content-Type: application/json" \
  -d "$BODY" \
  "${BASE_URL}/api/cards/${SLUG}") || {

README.md:66-69:

bash
Set `SCHELLING_URL` to use a different server (useful for local development):

export SCHELLING_URL=http://localhost:3000

Technical Analysis

The authenticated scripts derive the complete destination origin from the externally controlled SCHELLING_URL environment variable. They do not validate its scheme, hostname, port, or trust level before attaching the bearer API key.

Consequently, an inherited or attacker-modified environment can redirect the authenticated request to an arbitrary server. The documentation also explicitly permits an HTTP URL. When HTTP is used, the authorization header and request content are transmitted without transport encryption and may be captured by a network-positioned attacker.

Although the default endpoint uses HTTPS, that default does not protect exec ...[truncated 1564 chars]

Remediation
View remediation

Remediation Suggestions

  1. Require HTTPS for every request carrying an API key. Reject URLs whose parsed scheme is not exactly https.
  2. Allowlist schellingprotocol.com as the authenticated production origin rather than trusting an unrestricted environment variable.
  3. If local development is necessary, require an explicit opt-in flag and restrict insecure HTTP to loopback addresses such as 127.0.0.1 and ::1.
  4. Parse and validate the URL structurally; do not rely on string-prefix checks that can be bypassed with crafted hostnames or user-info components.
  5. Separate public and authenticated endpoint configuration. An endpoint accepted for unauthenticated search should not automatically be trusted to receive credentials.
  6. Configure curl with appropriate TLS verification and redirect restrictions. Avoid forwarding authorization headers across redirects to a different origin.
  7. Document how users can revoke and rotate a credential after suspected endpoint redirection or plaintext exposure.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/inbox.sh:8
Finding

API Keys Are Exposed Through Positional Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Locations:

  • scripts/inbox.sh:8,26-32
  • scripts/respond.sh:8,29-47
  • scripts/update-card.sh:8,38-41,65-67
  • SKILL.md:53-64,102-117
  • README.md:45-49

Vulnerability Type: Sensitive credential exposure through process arguments and command history
Risk Level: Medium

Vulnerable Code

scripts/inbox.sh:8,26-32:

bash
Usage: $0 <slug> <api_key>

[ $# -lt 2 ] && usage

SLUG="$1"
API_KEY="$2"

RESPONSE=$(curl -sf \
  -H "Authorization: Bearer ${API_KEY}" \

scripts/respond.sh:8,29-47:

bash
Usage: $0 <slug> <api_key> <request_id> <accepted|declined> [response_message]

[ $# -lt 4 ] && usage

SLUG="$1"
API_KEY="$2"
REQUEST_ID="$3"
STATUS="$4"

RESPONSE=$(curl -sf \
  -X PUT \
  -H "Authorization: Bearer ${API_KEY}" \

scripts/update-card.sh:8,38-41,65-67:

bash
Usage: $0 <slug> <api_key> <field=value> [field=value ...]

[ $# -lt 3 ] && usage

SLUG="$1"
API_KEY="$2"

RESPONSE=$(curl -sf \
  -X PUT \
  -H "Authorization: Bearer ${API_KEY}" \

SKILL.md:53-55:

bash
# SAVE THE API KEY from the response — shown only once!
# Then check for incoming requests:
./scripts/inbox.sh my-agent $API_KEY

README.md:45-49:

bash
# 5. Check your inbox
./inbox.sh my-agent $MY_API_KEY

# 6. Accept a request
./respond.sh my-agent $MY_API_KEY <request_id> accepted "Great, let's talk!"

Technical Analysis

The authenticated scripts require the API key as their second positional argument. Shell expansion places the resulting secret in the process argument vector. Depending on the operating system and execution environment, process arguments may be available to same-host users, process-monitoring agents, audit systems, orchestration platforms, crash diagnostics, or wrapper scripts.

Entering a literal ...[truncated 1734 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the API key from positional arguments.
  2. Read the credential from a dedicated environment variable without passing it through argv, or preferably from a mode-0600 credential file or protected secret manager.
  3. Support reading the credential from standard input or a dedicated file descriptor for one-shot use.
  4. If interactive entry is supported, use a silent prompt so the credential is not echoed or stored in history.
  5. Update every usage message and example to avoid literal or expanded secrets in command arguments.
  6. Ensure errors, debug traces, and telemetry never print the authorization header or credential source.
  7. Document secure storage, least-access file permissions, revocation, and rotation procedures.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared description presents a broad network-participation capability: joining the Schelling network, submitting intents, discovering agents, matching with them, and coordinating on the user's behalf. The supplied code does something much narrower: it posts a message to an already-known target agent/card slug. There is no logic for registration, identity creation, agent discovery, matching, or broader coordination workflows. While sending a coordination request is related to the domain, the primary implemented behavior is direct outbound contact to a specified agent, which materially underdelivers and differs from the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a broad coordination-network skill: joining the network, submitting intents, matching with agents, coordinating, and discovering any other agent. The supplied code only implements agent-card creation/registration against the Schelling API. It sends user-provided profile fields to the /api/cards endpoint and returns the created card response, warning the user to save the api_key. While this partially aligns with 'gets a public identity,' it does not implement the core advertised behaviors of intent submission, matching, coordination, or agent discovery. Therefore the description materially overstates what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The declared description presents a broad networking and coordination capability: joining the Schelling network, publishing identity, submitting intents, matching with agents, and discovering others. The supplied code chunk does something much narrower: it fetches incoming coordination requests for an already-existing agent card using a slug and API key. While this is related to coordination, it does not implement most of the declared functionality, and its primary purpose is inbox retrieval rather than network joining or agent discovery. Therefore the description does not accurately represent this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The implemented behavior is much narrower than the declared description. The script only submits a single search/seek intent to a remote API endpoint and returns the response. There is no code for account or identity creation, network enrollment, agent discovery, persistent coordination, or matching workflows beyond whatever the backend may return from the quick-seek call. While 'submit intents' is represented, most of the claimed capabilities are not implemented in this code chunk, so the description materially overstates the behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description presents a broad network participation capability: joining the Schelling network, publishing identity, discovering other agents, submitting intents, and coordinating on the user's behalf. The actual code chunk is much narrower. It only updates the status of an existing coordination request to accepted or declined via an authenticated API call. While this is loosely related to coordination, it does not implement the main declared functions such as joining the network, discovering agents, or submitting intents. Therefore the description materially overstates and misrepresents what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a broad network-participation capability: joining the coordination network, submitting intents, coordinating, and obtaining a public identity, in addition to discovering agents. The supplied code only performs a GET request to /api/cards with search filters and outputs the response. This supports only the discovery/search portion of the description. The major declared capabilities around joining, identity creation, intent submission, and coordination are not implemented in this code chunk, so the description materially overstates what the code actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a broad network participation and coordination capability, including intent submission, agent discovery, and matching. The actual code only updates fields on an existing agent card using a slug and API key. It neither creates/joins a network identity nor performs search, matching, discovery, or coordination actions. This is a materially different and much narrower function than the declared purpose, so it is a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description presents a full network participation and coordination capability: joining Schelling, submitting intents, matching with agents, coordinating, and discovering agents. The supplied code only implements a narrow read-only action: GET /api/cards/ to view one agent's public card. While viewing a public card is loosely related to discovering agents, it is only a small subset of the declared functionality and does not support the primary claimed purpose. Therefore the description materially overstates what this code chunk actually does.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
83% confidence
Finding

The skill is designed around persistent external state: creating an agent card, maintaining an inbox, and using an API key for later actions. That persistence is not inherently malicious, but in this context it means user data, identifiers, messages, and authentication material may remain stored on an external service across sessions, increasing privacy and account exposure if users are not clearly informed.

Content

Scanner excerpt · README.md (reported line 3)May include surrounding context.

md
# Schelling Protocol — OpenClaw Skill

Give your AI agent a public identity on the [Schelling Protocol](https://schellingprotocol.com) coordination network. Create a card, find other agents, send coordination requests, and manage your inbox.

## What This Skill Does

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README encourages users to create a public agent identity and share profile/contact information on an external coordination network, but it does not clearly warn that this data becomes publicly discoverable outside the local tool. This can lead to unintended disclosure of personal, organizational, or sensitive operational information, especially if users assume the skill is only for local agent coordination.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares shell and network-capable behavior via curl-based scripts but does not define an explicit tool scope such as permissions or allowed-tools. This increases the chance an agent runtime grants broader execution capability than intended, making unintended outbound requests or shell execution easier if the skill is invoked in the wrong context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill encourages sending user intents and optional contact details to a public coordination network over HTTP-based workflows without a prominent privacy warning or data-minimization guidance. In this context, user requests may contain sensitive personal, professional, or financial information, so silent transmission to a third-party network can cause confidentiality and privacy harm.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill instructs the agent to persist an API key and notes it is only shown once, but provides no security guidance for secret storage, access control, rotation, or log redaction. In agent environments, this can lead to credentials being stored in plaintext, exposed in prompts, shell history, telemetry, or shared state, enabling unauthorized inbox access and profile manipulation.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/contact-agent.sh (reported line 52)May include surrounding context.

sh
[ -n "$FROM_CARD_SLUG" ] && BODY=$(jq -n --argjson b "$BODY" --arg v "$FROM_CARD_SLUG"  '$b + {from_card_slug: $v}')
[ -n "$BUDGET_CENTS" ]   && BODY=$(jq -n --argjson b "$BODY" --argjson v "$BUDGET_CENTS" '$b + {budget_cents: $v}')

RESPONSE=$(curl -sf \
  -X POST \
  -H "Content-Type: application/json" \
  -d "$BODY" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/create-card.sh (reported line 61)May include surrounding context.

sh
[ -n "$FROM_CARD_SLUG" ] && BODY=$(jq -n --argjson b "$BODY" --arg v "$FROM_CARD_SLUG"  '$b + {from_card_slug: $v}')
[ -n "$BUDGET_CENTS" ]   && BODY=$(jq -n --argjson b "$BODY" --argjson v "$BUDGET_CENTS" '$b + {budget_cents: $v}')

RESPONSE=$(curl -sf \
  -X POST \
  -H "Content-Type: application/json" \
  -d "$BODY" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

The script performs an outbound POST request to an external endpoint and includes user-provided content in the JSON body. Because this skill is specifically designed to publish and match agent intents on a public coordination network, the data flow is expected, but it still creates a real external transmission risk if users provide confidential or identifying information.

Content

Scanner excerpt · scripts/quick-seek.sh (reported line 19)May include surrounding context.

sh
INTENT="$1"

curl -s -X POST "${BASE_URL}/schelling/quick_seek" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --arg intent "$INTENT" '{intent: $intent, auto_advance: false}')" \
  | jq '.'

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script transmits arbitrary user-supplied intent text to a remote service, and the operation itself gives no inline disclosure, confirmation, or warning that the entered text will leave the local environment. In this skill’s context, intents may contain sensitive personal, business, hiring, or location data, so silent transmission increases privacy and data-leak risk even if the endpoint is the skill’s expected backend.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/respond.sh (reported line 45)May include surrounding context.

sh
BODY=$(jq -n --arg status "$STATUS" '{status: $status}')
[ -n "$RESPONSE_MESSAGE" ] && BODY=$(jq -n --argjson b "$BODY" --arg v "$RESPONSE_MESSAGE" '$b + {response_message: $v}')

RESPONSE=$(curl -sf \
  -X PUT \
  -H "Authorization: Bearer ${API_KEY}" \
  -H "Content-Type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/update-card.sh (reported line 65)May include surrounding context.

sh
BODY=$(jq -n --arg status "$STATUS" '{status: $status}')
[ -n "$RESPONSE_MESSAGE" ] && BODY=$(jq -n --argjson b "$BODY" --arg v "$RESPONSE_MESSAGE" '$b + {response_message: $v}')

RESPONSE=$(curl -sf \
  -X PUT \
  -H "Authorization: Bearer ${API_KEY}" \
  -H "Content-Type: application/json" \